使用RSA私钥对字符串进行签名 [英] Sign a string with an RSA private key
问题描述
在我的应用程序中,我必须使用我已经拥有的RSA私钥来签名。完成此操作后,我想稍后使用签名。
我检查了几个库,但是它们都做了我需要的更多。
这就是我想做的事情:
In my app i have to sign a message with an RSA private key i already have. After this done, i want to use the signature later. I've checked several libraries, but all of them do much more that i need. This is what i'd like to do:
NSString *message = @"This is a message";
NSString *privateKey = ...;
NSString *signature = [self signMessage:message withPrivateKey:privateKey];
如何
(NSString *)signMessage:(NSString *)message withPrivateKey:(NSString *)privateKey {
}
看起来像?
推荐答案
我已经尝试了数百万的签名方法,包括Keychain,解压缩SecKeyRef,证书(.p12),。pem密钥文件,但仍无法实现我的主要目标:
I've tried millions of signing methods, that include Keychain, extracting SecKeyRef's, certificates (.p12), .pem key-files, but still didn't manage to achieve my main goal:
- 签署一个使用PKCS#1 v1.5和SHA1的字符串摘要
- 使用从服务器(JSON)接收的字符串base64密钥而不是使用证书文件。
我的私钥是PKCS#1私钥,格式如下:
My private key is a PKCS#1 private key formatted like this:
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCx9YWznzT3irAArr+INM5m0i6UCNICq4E8yrWwPbGh8/kdU/oh
..... ..... ..... ..... ..... ..... ..... .....
eF9lWooBNGgSh5vmkgECQGJwmDLKohSKEtVwGOIp3S3j+CHs0vVnznmtmC9sfrj4
ef48Sx1KFI8iQa3Nfv5bokaJkiIVVx/eMaa96Vracjc=
-----END RSA PRIVATE KEY-----
最终我搬到了OpenSSL,事情变得更加光明。
所以整个过程如下所示:
Eventually I moved to OpenSSL and things got much brighter. So the whole process looks like the following:
- 下载并构建 iOS OpenSSL库。
- 将lib添加到项目中。
- 使用OpenSSL最终签署消息。
步骤1:OpenSSL库
从 https:// github下载库.com / x2on / OpenSSL-for-iPhone
将build-libssl.sh复制到项目文件夹
使用终端运行以下命令: / p>
Copy build-libssl.sh to your project folder Using Terminal run the following:
cd [your project folder]
/build-libssl.sh
第2步:添加OpenSSL
将include文件夹从OpenSSL复制到您的项目中 - 文件夹
Step 2: adding OpenSSL
Copy the "include" folder from OpenSSL into your project-folder
将libcrypto * .a和libss * .a文件拖放到您的XCode文件夹中
Drag-copy the libcrypto*.a and libss*.a files into your XCode Folder
打开目标的构建设置
将图书馆搜索路径
改为 $(继承)$(SRCROOT)
将用户标题搜索路径
更改为包含
激活始终搜索用户路径
#include <openssl/pem.h>
#include <openssl/engine.h>
#include <iomanip>
- (NSString*) signHeader:(NSString*) pTextString withPrivateKey: (NSString*) pPrivateKey {
int retEr;
char* text = (char*) [pTextString UTF8String];
unsigned char *data;
unsigned int dataLen;
// converting nsstring base64 private key to openssl RSA key
BIO *mem = NULL;
RSA *rsa_private = NULL;
char *private_key = (char*)[pPrivateKey UTF8String];
mem = BIO_new_mem_buf(private_key, strlen(private_key));
if (mem == NULL)
{
char buffer[120];
ERR_error_string(ERR_get_error(), buffer);
fprintf(stderr, "OpenSSL error: %s", buffer);
exit(0);
}
rsa_private = PEM_read_bio_RSAPrivateKey(mem, NULL, NULL, NULL);
BIO_free (mem);
if (rsa_private == NULL)
{
char buffer[120];
ERR_error_string(ERR_get_error(), buffer);
fprintf(stderr, "OpenSSL error: %s", buffer);
exit(0);
}
// end of convertion
data = (unsigned char *) text;
dataLen = strlen(text);
//// creating signature
// sha1
unsigned char hash[SHA_DIGEST_LENGTH];
unsigned char sign[128];
unsigned int signLen;
SHA1(data, dataLen, hash);
// signing
retEr = RSA_sign(NID_sha1, hash, SHA_DIGEST_LENGTH, sign, &signLen, rsa_private);
// printf("Signature len gth = %d\n", signLen);
printf("RSA_sign: %s\n", (retEr == 1) ? "RSA_sign success" : "RSA_sign error");
// convert unsigned char -> std:string
std::stringstream buffer;
for (int i = 0; i < 128; i++)
{
buffer << std::hex << std::setfill('0');
buffer << std::setw(2) << static_cast<unsigned>(sign[i]);
}
std::string signature = buffer.str();
// convert std:string -> nsstring
NSString *signedMessage = [NSString stringWithCString:signature.c_str() encoding:[NSString defaultCStringEncoding]];
RSA_free(rsa_private);
return signedMessage;
}
如果您想使用SHA256或任何其他SHA,您必须更改以下内容:
If you want to use SHA256 or any other SHA you must change the following:
SHA_DIGEST_LENGTH => SHA256_DIGEST_LENGTH
sign[128] => sign[256]
SHA1(data, dataLen, hash) => SHA256(data, dataLen, hash)
NID_sha1 => NID_sha256
替代步骤3:签署(Swift)
由于Swift语言不是C ++的超集,因此无法直接与C ++结合,因此您需要创建一个C ++代码的Objective-C包装器,然后从Swift代码中调用它(Obj-C)。
Alternative Step 3: Signing (Swift)
Since Swift language isn't a superset of C++ it can't be combined with C++ directly, therefore you need to create a Objective-C wrapper of C++ code and then call it (Obj-C) from your Swift code.
为您的C ++代码创建一个Obj-C类。
重要提示:该文件必须为.mm扩展名或设置类型为 Objective-C ++ Source
Create an Obj-C class for your C++ code.
IMPORTANT: the file must be either with .mm extension or set type to Objective-C++ Source
OpenSSLWrapper.h
#import <Foundation/Foundation.h>
@interface OpenSSLWrapper : NSObject
+ (NSString*) signHeader:(NSString*) pTextString withPrivateKey: (NSString*) pPrivateKey;
@end
OpenSSLWrapper.mm
#import "OpenSSLWrapper.h"
#include <openssl/pem.h>
#include <openssl/engine.h>
#include <iomanip>
@implementation OpenSSLWrapper
+ (NSString*) signHeader:(NSString*) pTextString withPrivateKey: (NSString*) pPrivateKey {
int retEr;
char* text = (char*) [pTextString UTF8String];
unsigned char *data;
unsigned int dataLen;
// converting nsstring base64 private key to openssl RSA key
BIO *mem = NULL;
RSA *rsa_private = NULL;
char *private_key = (char*)[pPrivateKey UTF8String];
mem = BIO_new_mem_buf(private_key, strlen(private_key));
if (mem == NULL)
{
char buffer[120];
ERR_error_string(ERR_get_error(), buffer);
fprintf(stderr, "OpenSSL error: %s", buffer);
exit(0);
}
rsa_private = PEM_read_bio_RSAPrivateKey(mem, NULL, NULL, NULL);
BIO_free (mem);
if (rsa_private == NULL)
{
char buffer[120];
ERR_error_string(ERR_get_error(), buffer);
fprintf(stderr, "OpenSSL error: %s", buffer);
exit(0);
}
// end of convertion
data = (unsigned char *) text;
dataLen = strlen(text);
//// creating signature
// sha1
unsigned char hash[SHA_DIGEST_LENGTH];
unsigned char sign[128];
unsigned int signLen;
SHA1(data, dataLen, hash);
// signing
retEr = RSA_sign(NID_sha1, hash, SHA_DIGEST_LENGTH, sign, &signLen, rsa_private);
// printf("Signature len gth = %d\n", signLen);
printf("RSA_sign: %s\n", (retEr == 1) ? "RSA_sign success" : "RSA_sign error");
// convert unsigned char -> std:string
std::stringstream buffer;
for (int i = 0; i < 128; i++)
{
buffer << std::hex << std::setfill('0');
buffer << std::setw(2) << static_cast<unsigned>(sign[i]);
}
std::string signature = buffer.str();
// convert std:string -> nsstring
NSString *signedMessage = [NSString stringWithCString:signature.c_str() encoding:[NSString defaultCStringEncoding]];
RSA_free(rsa_private);
return signedMessage;
}
@end
步骤3.2
创建一个Bridging-Header文件。
Step 3.2
Create a Bridging-Header file.
YourProject-Bridging-Header.h
#import "OpenSSLWrapper.h"
步骤3.3
在Swift文件中使用Obj-C中的方法。
Step 3.3
Use the method from Obj-C in your Swift file.
DigestSignature.swift
import Cocoa
class DigestSignature: NSObject {
let privateKey = "-----BEGIN RSA PRIVATE KEY-----MIICXAIBAAKBgQCx9YWznzT3irAArr+INM5m0i6UCNICq4E8yrWwPbGh8/kdU/oh ..... ..... eF9lWooBNGgSh5vmkgECQGJwmDLKohSKEtVwGOIp3S3j+CHs0vVnznmtmC9sfrj4ef48Sx1KFI8iQa3Nfv5bokaJkiIVVx/eMaa96Vracjc=-----END RSA PRIVATE KEY-----"
var digest: String = OpenSSLWrapper.signHeader("Hello World", withPrivateKey: privateKey) ;
}
在结果中,你有一个十六进制NSString *签名摘要。
希望有帮助
In the result, you have a hex NSString* signed digest.
Hope that helps
这篇关于使用RSA私钥对字符串进行签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!