2014-03-13 82 views
0

一個問題:供應商表示,對於某些加密目的使用帶有SHA-256的PKCS#1 V2.1 OAEP ...這甚至有可能嗎? 我已經檢查並重新檢查openssl,他們所有的都是RSA公鑰加密,應該是PKCS#1 V2.1與SHA1RSA公鑰加密openssl

那麼我該怎麼做?我如何在RSA PUBLIC KEY加密中使用SHA256?

它甚至有可能嗎?

最好的問候,

編輯:怎麼回答就可使用RSA加密使用OpenSSL OAEP填充和SHA256 DIGEST

#include "openssl/rsa.h" 
#include <openssl/err.h> 
#define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1  154 

int RSA_padding_add_PKCS1_OAEP_mgf1_SHA256(unsigned char *to, int tlen, 
    const unsigned char *from, int flen, 
    const unsigned char *param, int plen, 
    const EVP_MD *md, const EVP_MD *mgf1md) 
{ 
    int i, emlen = tlen - 1; 
    unsigned char *db, *seed; 
    unsigned char *dbmask, seedmask[EVP_MAX_MD_SIZE]; 
    int mdlen; 

    if (md == NULL) 
     md = EVP_sha256(); //HERE IS THE ACTUAL USE OF SHAR256 digest! 
    if (mgf1md == NULL) 
     mgf1md = md; 

    mdlen = EVP_MD_size(md); 

    if (flen > emlen - 2 * mdlen - 1) 
    { 
     RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, 
      RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); 
     return 0; 
    } 

    if (emlen < 2 * mdlen + 1) 
    { 
     RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, RSA_R_KEY_SIZE_TOO_SMALL); 
     return 0; 
    } 

    to[0] = 0; 
    seed = to + 1; 
    db = to + mdlen + 1; 

    if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL)) 
     return 0; 
    memset(db + mdlen, 0, 
     emlen - flen - 2 * mdlen - 1); 
    db[emlen - flen - mdlen - 1] = 0x01; 
    memcpy(db + emlen - flen - mdlen, from, (unsigned int)flen); 
    if (RAND_bytes(seed, mdlen) <= 0) 
     return 0; 
#ifdef PKCS_TESTVECT 
    memcpy(seed, 
     "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f", 
     20); 
#endif 

    dbmask = (unsigned char*)OPENSSL_malloc(emlen - mdlen); 
    if (dbmask == NULL) 
    { 
     RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE); 
     return 0; 
    } 

    if (PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md) < 0) 
     return 0; 
    for (i = 0; i < emlen - mdlen; i++) 
     db[i] ^= dbmask[i]; 

    if (PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md) < 0) 
     return 0; 
    for (i = 0; i < mdlen; i++) 
     seed[i] ^= seedmask[i]; 

    OPENSSL_free(dbmask); 
    return 1; 
} 

int RSA_padding_add_PKCS1_OAEP_SHA256(unsigned char *to, int tlen, 
    const unsigned char *from, int flen, 
    const unsigned char *param, int plen) 
{ 
    return RSA_padding_add_PKCS1_OAEP_mgf1_SHA256(to, tlen, from, flen, 
     param, plen, NULL, NULL); 
} 

static int RSA_eay_public_encrypt_SHA256(int flen, const unsigned char *from, 
    unsigned char *to, RSA *rsa, int padding) 
{ 
    BIGNUM *f, *ret; 
    int i, j, k, num = 0, r = -1; 
    unsigned char *buf = NULL; 
    BN_CTX *ctx = NULL; 

#ifdef OPENSSL_FIPS 
    if (FIPS_selftest_failed()) 
    { 
     FIPSerr(FIPS_F_RSA_EAY_PUBLIC_ENCRYPT, FIPS_R_FIPS_SELFTEST_FAILED); 
     goto err; 
    } 

    if (FIPS_module_mode() && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW) 
     && (BN_num_bits(rsa->n) < OPENSSL_RSA_FIPS_MIN_MODULUS_BITS)) 
    { 
     RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_KEY_SIZE_TOO_SMALL); 
     return -1; 
    } 
#endif 

    if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) 
    { 
     RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_MODULUS_TOO_LARGE); 
     return -1; 
    } 

    if (BN_ucmp(rsa->n, rsa->e) <= 0) 
    { 
     RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE); 
     return -1; 
    } 

    /* for large moduli, enforce exponent limit */ 
    if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS) 
    { 
     if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) 
     { 
      RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE); 
      return -1; 
     } 
    } 

    if ((ctx = BN_CTX_new()) == NULL) goto err; 
    BN_CTX_start(ctx); 
    f = BN_CTX_get(ctx); 
    ret = BN_CTX_get(ctx); 
    num = BN_num_bytes(rsa->n); 
    buf = (unsigned char*)OPENSSL_malloc(num); 
    if (!f || !ret || !buf) 
    { 
     RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, ERR_R_MALLOC_FAILURE); 
     goto err; 
    } 

    switch (padding) 
    { 
    case RSA_PKCS1_PADDING: 
     i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen); 
     break; 
#ifndef OPENSSL_NO_SHA 
    case RSA_PKCS1_OAEP_PADDING: 
     i = RSA_padding_add_PKCS1_OAEP_SHA256(buf, num, from, flen, NULL, 0); 
     break; 
#endif 
    case RSA_SSLV23_PADDING: 
     i = RSA_padding_add_SSLv23(buf, num, from, flen); 
     break; 
    case RSA_NO_PADDING: 
     i = RSA_padding_add_none(buf, num, from, flen); 
     break; 
    default: 
     RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); 
     goto err; 
    } 
    if (i <= 0) goto err; 

    if (BN_bin2bn(buf, num, f) == NULL) goto err; 

    if (BN_ucmp(f, rsa->n) >= 0) 
    { 
     /* usually the padding functions would catch this */ 
     RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); 
     goto err; 
    } 

    if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) 
     if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx)) 
      goto err; 

    if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx, 
     rsa->_method_mod_n)) goto err; 

    /* put in leading 0 bytes if the number is less than the 
    * length of the modulus */ 
    j = BN_num_bytes(ret); 
    i = BN_bn2bin(ret, &(to[num - j])); 
    for (k = 0; k<(num - i); k++) 
     to[k] = 0; 

    r = num; 
err: 
    if (ctx != NULL) 
    { 
     BN_CTX_end(ctx); 
     BN_CTX_free(ctx); 
    } 
    if (buf != NULL) 
    { 
     OPENSSL_cleanse(buf, num); 
     OPENSSL_free(buf); 
    } 
    return(r); 
} 
int RSA_public_encrypt_sha256(int flen, const unsigned char *from, unsigned char *to, 
    RSA *rsa, int padding) 
{ 
    return(RSA_eay_public_encrypt_SHA256(flen, from, to, rsa, padding)); 
} 

只需添加這幾個功能和呼叫RSA_public_encrypt_sha256,而不是RSA_public_encrypt瞧你有RSA_OAEP_SHA256

嗯,我知道這是濫用openssl代碼,但這是一個解決方案,如果你不能自己編譯openssl lib,就像我不能,因爲我收到了這個作爲ARM平臺的一部分。

在下面的答案中,我要感謝JARIQ!

謝謝!

+0

看起來這是可能的,這個傢伙做到了[這裏](http://stackoverflow.com/questions/13419201/why-are-the-rsa-sha256-signatures-i-generate-with-openssl-and- java-different) – 2014-03-13 08:58:27

+0

@Mayerz:在你連接的問題中沒有使用OAEP加密 – jariq

+0

噢好吧,那麼我沒有得到它。等待看到答案 – 2014-03-13 10:21:34

回答

1

我不確定OpenSSL API,但在PKCS#11 API中,當您使用OAEP填充進行RSA加密時,您可以指定消息摘要算法以及掩碼生成函數,如my code sample (take a look at _03_EncryptAndDecryptSinglePartOaepTest() method)中所示。它用C#編寫,但我認爲它應該容易理解。但是我從來沒有嘗試過任何比SHA1更好的東西。

更多信息可在RFC 3447PKCS#11 specification (chapter 12.1.7 and chapter 12.1.8)中找到。

編輯的OpenSSL:

在OpenSSL的RSA加密基於公鑰和OAEP填充順序進行:

  1. 你需要傳遞RSA_PKCS1_OAEP_PADDING標誌的功能RSA_public_encrypt()在rsa_crpt.c實施
  2. RSA_public_encrypt()然後調用在rsa_eay.c中實現的函數RSA_eay_public_encrypt()(除非通過引擎使用某些加密硬件設備)
  3. RSA_eay_public_encrypt()然後調用rsa_oaep.c

它使用SHA1這似乎是目前的OpenSSL實現,但我認爲,唯一的選擇實施的功能RSA_padding_add_PKCS1_OAEP()應該可以在rsa_oaep.c稍微修改代碼文件來實現你所需要的。

+0

是的,但只有在使用C++的嵌入式板上openssl :)所以需要找到一些解決方案來使用SHA256 ... – Lonko

+0

偉大的發現,但如果我只在特殊的arm平臺上預編譯openssl加密庫,該怎麼辦:S damm最後我將不得不自己完成整個加密 – Lonko

+0

jariq你是一個天才!回答我的問題顯示整個解決方案RSA OAEP SHA256 – Lonko