在我的应用程序中,我必须使用我已经拥有的RSA私钥来签名。完成此操作后,我想稍后使用签名。 我检查了几个库,但是它们都做了我需要的更多。 这就是我想做的事情:
NSString *message = @"This is a message";
NSString *privateKey = ...;
NSString *signature = [self signMessage:message withPrivateKey:privateKey];
怎么会
(NSString *)signMessage:(NSString *)message withPrivateKey:(NSString *)privateKey {
}
看起来像?
答案 0 :(得分:3)
iOS有一个用于执行此操作的C API。我自己从来没有使用它,但看起来你需要一个带有私钥的PKCS12格式文件,你用SecKeyPKCS12Imort导入它并获取私钥。然后该函数为SecKeyRawSign以对您的字符串进行签名。
首先应使用已知的字符编码将字符串转换为NSData对象 - 可能是UTF-8,并且NSData中的字节已签名。
如果在字符串中使用非ASCII字符,并确保使用定义良好的编码,则还需要注意如何表示某些字符。例如,é可以表示为单个Unicode数字或Unicode急性重音,后跟字母e。
答案 1 :(得分:3)
我已经尝试了数百万种签名方法,包括Keychain,提取SecKeyRef,证书(.p12),。pem密钥文件,但仍无法实现我的主要目标:
我的私钥是PKCS#1私钥,格式如下:
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCx9YWznzT3irAArr+INM5m0i6UCNICq4E8yrWwPbGh8/kdU/oh
..... ..... ..... ..... ..... ..... ..... .....
eF9lWooBNGgSh5vmkgECQGJwmDLKohSKEtVwGOIp3S3j+CHs0vVnznmtmC9sfrj4
ef48Sx1KFI8iQa3Nfv5bokaJkiIVVx/eMaa96Vracjc=
-----END RSA PRIVATE KEY-----
最终我搬到了OpenSSL,事情变得更加光明。 所以整个过程如下:
从https://github.com/x2on/OpenSSL-for-iPhone
下载图书馆将build-libssl.sh复制到项目文件夹 使用终端运行以下命令:
cd [your project folder]
/build-libssl.sh
将“include”文件夹从OpenSSL复制到项目文件夹
将libcrypto * .a和libss * .a文件拖放到XCode文件夹中
打开“目标”的构建设置
将Library Search Paths
更改为$(inherited) “$(SRCROOT)”
将User Header Search Paths
更改为include
激活Always Search User Paths
#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,您必须更改以下内容:
SHA_DIGEST_LENGTH => SHA256_DIGEST_LENGTH
sign[128] => sign[256]
SHA1(data, dataLen, hash) => SHA256(data, dataLen, hash)
NID_sha1 => NID_sha256
由于Swift语言不是C ++的超集,因此无法直接与C ++结合使用,因此需要创建一个C ++代码的Objective-C包装器,然后从Swift代码中调用它(Obj-C)。
为您的C ++代码创建一个Obj-C类。
重要提示:该文件必须为.mm扩展名或设置类型为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
创建一个Bridging-Header文件。
<强> YourProject-桥接-Header.h 强>
#import "OpenSSLWrapper.h"
在Swift文件中使用Obj-C中的方法。
<强> 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) ;
}
希望有所帮助