使用RSA私钥对字符串进行签名 [英] Sign a string with an RSA private key

查看:248
本文介绍了使用RSA私钥对字符串进行签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序中,我必须使用我已经拥有的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:


  1. 下载并构建 iOS OpenSSL库

  2. 将lib添加到项目中。

  3. 使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆