[英]Sign a string with an RSA private key
在我的應用程序中,我必須使用已經擁有的RSA私鑰對消息簽名。 完成此操作后,我想稍后使用簽名。 我已經檢查了幾個庫,但是它們都做了很多我需要做的事情。 這就是我想做的:
NSString *message = @"This is a message";
NSString *privateKey = ...;
NSString *signature = [self signMessage:message withPrivateKey:privateKey];
怎么會
(NSString *)signMessage:(NSString *)message withPrivateKey:(NSString *)privateKey {
}
看起來像?
iOS具有執行此操作的C API。 我自己從未使用過它,但是看起來您需要一個包含私鑰的PKCS12格式的文件,您可以使用SecKeyPKCS12Imort導入該文件並取出私鑰。 然后,該函數是SecKeyRawSign以對您的字符串進行簽名。
首先應使用已知的字符編碼將字符串轉換為NSData對象-可能為UTF-8,並對NSData中的字節進行簽名。
如果在字符串中使用非ASCII字符,並確保使用定義良好的編碼,則還需要注意某些字符的表示方式。 例如,é可以表示為單個Unicode數字,也可以表示為Unicode重音符號,后跟字母e。
我已經嘗試了數百萬種簽名方法,包括鑰匙串,提取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復制到您的項目文件夾中使用Terminal運行以下命令:
cd [your project folder]
/build-libssl.sh
將OpenSSL中的“ include”文件夾復制到您的項目文件夾中
將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
創建一個橋接頭文件。
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) ;
}
希望能有所幫助
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.