关于RSAES-OAEP和RSASSA-PSS编码的介绍及C语言实现

首先介绍下OAEP和PSS的英文缩写:

OAEP= Optimal Asymmetric Encryption Padding, 翻译为中文是最优非对称加密填充。

PSS = Probabilistic Signature Scheme,翻译为中文就是概率签名方案。

RSA的加密机制有两种方案:一个是RSAES-OAEP,另一种是RSAES-PKCS1-v1_5。RSAES前缀的意思是RSA ENCRYPTION SCHEME。PKCS#1推荐在新的应用中使用RSAES-OAEP,因为其安全性更高,规范保留对RSAES-PKCS#1-v1_5的支持是为了跟老的应用保持兼容。它们两的区别仅仅在于加密前编码的方式不同。而加密前的编码是为了提供了抵抗各种活动的敌对攻击的安全机制。

PKCS#1的签名机制也有种方案:RSASSA-PSS和RSASSA-PKCS1-v1_5。RSASSA前缀的意思是SIGNATURE SCHEMES WITH APPENDIX。同样,推荐RSASSA-PSS用于新的应用,而RSASSA-PKCS1-v1_5只用于兼容老的应用。

两种填充算法在openssl中都有实现,但是如果希望在嵌入式芯片中实现这部分内容就比较困难了,本文参考openssl代码实现了一份可在嵌入式固件中使用的纯C代码,供大家参考。为了简单,只实现编码解码部分内容,不涉及加密解密、签名验签的完整功能。

工程文件如下图所示:

rsa_oaep.h文件内容:

#ifndef __RSA_OAEP_H
#define __RSA_OAEP_H

#ifndef IN
#define IN
#endif

#ifdef __cplusplus
extern "C" {
#endif


/*
// Prototype:int RSA_padding_add_PKCS1_OAEP(int hash_alg,
//    unsigned char *to, int tlen,
//    const unsigned char *from, int flen,
//    const unsigned char *label, int lable_len);
// Parameters:
//    hash_alg: Hash alogorithm, could be the following value:
//        HASH_ALG_SHA1: SHA-1;
//        HASH_ALG_SHA256: SHA-256;
//    to: The buffer which is used to store the target data after padding.
//    tlen: The expected length of data after padding.
//    from: Original data.
//    flen: The length of original data.
//    label: Optional label to be associated with the message; if not provided, is the empty string.
//    label_len: The length of label, if not provided, should be set to 0.
// return:
//    1: Succeed;
//    0: Fail;
// remarks: This function is used to pad the original data according to PKCS#1 OAEP rules.
*/
int RSA_padding_add_PKCS1_OAEP(IN int hash_alg,
    OUT unsigned char *to, IN int tlen,
    IN const unsigned char *from, IN int flen,
    IN const unsigned char *label, IN int lable_len);

/*
// int RSA_padding_check_PKCS1_OAEP(int hash_alg, unsigned char *to, int tlen,
//    IN unsigned char *from, int flen, int num,
//    IN unsigned char *param, int plen);
// Parameters:
//    hash_alg: Hash alogorithm, could be the following value:
//        HASH_ALG_SHA1: SHA-1;
//        HASH_ALG_SHA256: SHA-256;
//    to: The buffer which is used to store the original data after decoding.
//    tlen: The buffer length of "to".
//    from: The data buffer for decoding.
//    flen: The buffer length of "from".
//    num: The length of RSA modulus.
//    param: Optional label to be associated with the message; if not provided, is the empty string.
//    plen: The length of label, if not provided, should be set to 0.
// return:
//    >0: Succeed, return the length of original data (before padding).
//    Other values: Fail;
// remarks: This function is used to check the format of PKCS #1 OAEP padding.
*/
int RSA_padding_check_PKCS1_OAEP(IN int hash_alg, OUT unsigned char *to, IN int tlen,
    IN unsigned char *from, IN int flen, IN int num,
    IN unsigned char *param, IN int plen);

#ifdef __cplusplus
}
#endif

#endif // __RSA_OAEP_H

rsa_pss.h文件内容:

#ifndef __RSA_PSS_H
#define __RSA_PSS_H

#ifndef IN
#define IN
#endif

#ifdef __cplusplus
extern "C" {
#endif

/*
// Prototype:int RSA_padding_add_PKCS1_PSS(int rsaLen, unsigned char *EM,
//    IN unsigned char *mHash,
//    int hash_alg, int sLen);
// Parameters:
//    rsaLen: The length of RSA modulus in bits;
//    EM: Encoded message after padding.
//    mHash: The digest value.
//    hash_alg: Hash alogorithm, could be the following value:
//        HASH_ALG_SHA1: SHA-1;
//        HASH_ALG_SHA256: SHA-256;
//    sLen: The length of salt data. If it's set to -1, it will be set to the length of digest internally.
// return:
//    1: Succeed;
//    0: Fail;
// remarks: This function is used to pad the original data according to EMSA-PSS encoding rules.
*/
int RSA_padding_add_PKCS1_PSS(IN int rsaLen, OUT unsigned char *EM,
    IN unsigned char *mHash,
    IN int hash_alg, IN int sLen);

/*
// Prototype:int RSA_verify_PKCS1_PSS(int rsaLen, unsigned char *mHash,
//    int hash_alg, IN unsigned char *EM, int sLen);
// Parameters:
//    rsaLen: The length of RSA modulus in bits;
//    mHash: The digest value.
//    hash_alg: Hash alogorithm, could be the following value:
//        HASH_ALG_SHA1: SHA-1;
//        HASH_ALG_SHA256: SHA-256;
//    EM: Encoded message.
//    sLen: The length of salt data.
// return:
//    1: Succeed;
//    0: Fail;
// remarks: This function is used to check the format of EMSA-PSS padding.
*/
int RSA_verify_PKCS1_PSS(IN int rsaLen, IN unsigned char *mHash,
    IN int hash_alg, IN unsigned char *EM, IN int sLen);



#ifdef __cplusplus
}
#endif


#endif // __RSA_PSS_H

测试代码:

void TestRsaOaepEncoding()
{
    BYTE pbData[256];
    BYTE pbTo[256];

    int i;
    int ret;

    char *szOrigData = "151515151515151551515151515151511515151515151515";
    BYTE pbOrigData[256];
    WORD wOrigDataLen = (WORD)strlen(szOrigData) / 2;
    utlStrToHex(pbOrigData, szOrigData, wOrigDataLen);

    ret = RSA_padding_add_PKCS1_OAEP(HASH_ALG_SHA256, pbData, 256,
        pbOrigData, wOrigDataLen,
        //NULL, 0);
        (const BYTE *)"Hello", 5);
    if (!ret)
    {
        printf("RSA_padding_add_PKCS1_OAEP failed!");
        return;
    }

    ret = RSA_padding_check_PKCS1_OAEP(HASH_ALG_SHA256, 
        pbTo, 256,    //Used to store original data
        pbData, 256, //The data used for decoding
        256,    //Rsa modulus len
        //NULL, 0);
        (BYTE*)"Hello", 5);    //Optional label
    if (!ret)
    {
        printf("RSA_padding_check_PKCS1_OAEP failed!");
        return;
    }
}


void TestRsaPssEncoding()
{
    unsigned char mHash[32];
    unsigned char EM[256];

    for (int i = 0; i < 32; i++)
    {
        mHash[i] = i;
    }

    int ret = RSA_padding_add_PKCS1_PSS(2048, //RSA len, in bits
        EM,        //Buffer to store encoded message
        mHash,    //Digest of Hash, if we use SHA-1, only the first 20 bytes are used.
        HASH_ALG_SHA256, //Hash algorithm
        13);    //Salt data length
    if (!ret)
    {
        printf("RSA_padding_add_PKCS1_PSS failed!");
        return;
    }

    ret = RSA_verify_PKCS1_PSS(2048, //RSA len, in bits
        mHash,    //Digest of hash
        HASH_ALG_SHA256, //Hash algorithm
        EM, //Encoded message
        13);    //Salt data length
    if (!ret)
    {
        printf("RSA_verify_PKCS1_PSS failed!");
        return;
    }
}

因为CSDN上传附件比较麻烦, PKCS#1 V2.2规范及完整代码请到我的主页下载:

www.sec007.com

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

l_z_h

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值