用RSA私钥签署一个字符串[英] Sign a string with an RSA private key

本文是小编为大家收集整理的关于用RSA私钥签署一个字符串的处理方法,想解了用RSA私钥签署一个字符串的问题怎么解决?用RSA私钥签署一个字符串问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

在我的应用程序中,我必须使用我已经拥有的 RSA 私钥签署消息.完成后,我想稍后使用签名.我检查了几个库,但它们都做了我需要的更多.这就是我想做的:

NSString *message = @"This is a message";
NSString *privateKey = ...;

NSString *signature = [self signMessage:message withPrivateKey:privateKey];

会怎样

(NSString *)signMessage:(NSString *)message withPrivateKey:(NSString *)privateKey {
}

看起来像?

推荐答案

我已经尝试了数百万种签名方法,包括 Keychain、提取 SecKeyRef's、证书 (.p12)、.pem 密钥文件,但仍然没有设法实现我的主要目标:

  • 使用 PKCS#1 v1.5 和 SHA1 签署字符串摘要
  • 使用从服务器 (JSON) 接收的字符串 base64 密钥,而不是使用证书文件.

我的私钥是一个 PKCS#1 私钥,格式如下:

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCx9YWznzT3irAArr+INM5m0i6UCNICq4E8yrWwPbGh8/kdU/oh
.....   .....   .....   .....   .....   .....   .....   .....   
eF9lWooBNGgSh5vmkgECQGJwmDLKohSKEtVwGOIp3S3j+CHs0vVnznmtmC9sfrj4
ef48Sx1KFI8iQa3Nfv5bokaJkiIVVx/eMaa96Vracjc=
-----END RSA PRIVATE KEY-----

最终我转向了 OpenSSL,事情变得更加光明.所以整个过程如下:

  1. 下载并构建 iOS OpenSSL 库.
  2. 将库添加到项目中.
  3. 最终使用 OpenSSL 对消息进行签名.
<小时>

第 1 步:OpenSSL 库

https://github.com/x2on/OpenSSL-for-iPhone<下载库/a>

将 build-libssl.sh 复制到您的项目文件夹使用终端运行以下命令:

cd [your project folder]
/build-libssl.sh

第 2 步:添加 OpenSSL

将"include"文件夹从 OpenSSL 复制到您的项目文件夹中

将 libcrypto*.a 和 libss*.a 文件拖放到您的 XCode 文件夹中

打开"目标"的构建设置

将Library Search Paths改为$(inherited) "$(SRCROOT)"

将User Header Search Paths改为include

激活Always Search User Paths

第 3 步:签名

#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

替代步骤 3:签名 (Swift)

由于 Swift 语言不是 C++ 的超集,它不能直接与 C++ 结合,因此您需要创建 C++ 代码的 Objective-C 包装器,然后从您的 Swift 代码中调用它 (Obj-C).

步骤 3.1

为您的 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

步骤 3.2

创建一个桥接头文件.

YourProject-Bridging-Header.h

#import "OpenSSLWrapper.h"

步骤 3.3

在你的 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) ;

}

在结果中,你有一个十六进制 NSString* 签名的摘要.

希望有帮助

本文地址:https://www.itbaoku.cn/post/924507.html