如何从RSA_private_encrypt获取人类可读的std :: string

时间:2015-08-25 21:53:04

标签: c++ openssl

我有RSA加密我的字符串,但它现在是一个unsigned char *。如何创建可以为用户输出的人类可读的std :: string?我想在亚马逊签名的网址中使用它。以下是GitHub

代码中的肉和土豆
unsigned char* RSA_SHA1_Sign(std::string policy, RSA *privateKey) throw(std::runtime_error)
{

    //sha1 digest the data
    unsigned char hash[SHA_DIGEST_LENGTH] = {'0'};
    SHA1((const unsigned char *)policy.c_str(), policy.length(), hash);

    // Sign the data
    int rsaSize = RSA_size(privateKey);
//    std::unique_ptr<unsigned char[]> signedData(new unsigned char[size]);//if c++11 available
unsigned char *signedData = (unsigned char *)malloc(sizeof(unsigned char) * rsaSize);
    unsigned int signedSize = 0;

    //use RSA_sign instead of RSA_private_encrypt
    if(!RSA_sign(NID_sha1, hash, SHA_DIGEST_LENGTH, signedData, &signedSize, privateKey)){
        throw std::runtime_error("Failed to sign");
    }

    return signedData;
}

std::string base64Encode(unsigned char *signedData)
{
    //prepare
    BIO *b64 = BIO_new(BIO_f_base64());
    BIO *bmem = BIO_new(BIO_s_mem());
    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
    b64 = BIO_push(b64, bmem);

    //write
    BIO_write(b64, signedData, 256);
    BIO_flush(b64);


    //create string
    BUF_MEM *bptr;
    BIO_get_mem_ptr(b64, &bptr);
    std::string base64String(bptr->data);

    BIO_free_all(b64);
    return base64String;
}
int main(int argc, const char * argv[]) {

    RSA *privateKey = createRSAFromPrivateKeyFile("/path/to/privatekey");
    std::string sourceString = "testing";
    std::string signature = RSA_SHA1_Sign(sourceString, privateKey);
    std::string encodedSignature = base64Encode(signature);
    std::cout << "RESULT: " << encodedSignature << std::endl;

    return 0;
}

更新:我使用了错误的签名功能。更新后,使用base64编码为我提供了正确的字符串。

  

RSA_PKCS1_PADDING              PKCS#1 v1.5填充。此函数不处理PKCS#1中指定的algorithmIdentifier。              生成或验证PKCS#1签名时,应使用RSA_sign(3)和RSA_verify(3)。

2 个答案:

答案 0 :(得分:1)

首先,将它放入std::string对象中,这通常可能会有所帮助:

std::string s{private_key, size};

但是,为了使其与Amazon的方案兼容,您需要挑选(或编写自己的)Base64库和URL编码器以逃避特殊的URL字符。粗略搜索Google或StackOverflow将为您提供在这方面所需的内容,并且在C ++中编写如何进行Base64编码和URL转义超出了本问题的范围。

此外,由于您使用的是C ++,请考虑std::unique_ptr<unsigned char[]>而不是直接malloc();

std::unique_ptr<unsigned char[]> signedData{new unsigned char[size]};

答案 1 :(得分:1)

要保存所有数据,请使用此std :: string构造函数:std :: string(char * data,int size)。由于输出MIGHT包含空字符,因此大小将很有用。

要通过网址将其发送到亚马逊,请再次考虑使用base64编码,因为加密数据可能包含NULL和其他恶作剧。