rsa 公 填充模式的_RSA填充方式

本文详细介绍了RSA加密算法的两种填充模式:PKCS1_type_1(私钥加密,填充01和FF)和PKCS1_type_2(公钥加密,填充非零随机数)。通过填充方式的实现代码,展示了如何进行加解密过程中的数据填充,确保数据安全和正确性。

// RSA 加密算法填充方式.

// memcpy(目的地址,原地址,长度);

// 私钥加密的填充 01 ,使用oxFF 填充.

int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen,

const unsigned char *from, int flen)

{

int j;

unsigned char *p;

if (flen > (tlen - RSA_PKCS1_PADDING_SIZE)) {

RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1,

RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);

return (0);

}

p = (unsigned char *)to;

*(p++) = 0;

*(p++) = 1; /* Private Key BT (Block Type) */

/* pad out with 0xff data */

j = tlen - 3 - flen;

memset(p, 0xff, j);

p += j;

*(p++) = '\0';

memcpy(p, from, (unsigned int)flen);

return (1);

}

int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen,

const unsigned char *from, int flen,

int num)

{

int i, j;

const unsigned char *p;

p = from;

if ((num != (flen + 1)) || (*(p++) != 01)) {

RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,

RSA_R_BLOCK_TYPE_IS_NOT_01);

return (-1);

}

/* scan over padding data */

j = flen - 1; /* one for type. */

for (i = 0; i < j; i++) {

if (*p != 0xff) { /* should decrypt to 0xff */

if (*p == 0) {

p++;

break;

} else {

RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,

RSA_R_BAD_FIXED_HEADER_DECRYPT);

return (-1);

}

}

p++;

}

if (i == j) {

RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,

RSA_R_NULL_BEFORE_BLOCK_MISSING);

return (-1);

}

if (i < 8) {

RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,

RSA_R_BAD_PAD_BYTE_COUNT);

return (-1);

}

i++; /* Skip over the '\0' */

j -= i;

if (j > tlen) {

RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1, RSA_R_DATA_TOO_LARGE);

return (-1);

}

memcpy(to, p, (unsigned int)j);

return (j);

}

// 公钥加密的填充, 使用非零随机数填充 . 02

int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen,

const unsigned char *from, int flen)

{

int i, j;

unsigned char *p;

// 填充条件 : 数据长度必须小于Modulus长度 - 11 字节.

if (flen > (tlen - 11)) {

RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2,

RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);

return (0);

}

p = (unsigned char *)to;

*(p++) = 0;

*(p++) = 2; /* Public Key BT (Block Type) */

/* pad out with non-zero random data */

j = tlen - 3 - flen;

if (RAND_bytes(p, j) <= 0)

return (0);

for (i = 0; i < j; i++) {

if (*p == '\0')

do {

if (RAND_bytes(p, 1) <= 0)

return (0);

} while (*p == '\0');

p++;

}

*(p++) = '\0';

memcpy(p, from, (unsigned int)flen);

return (1);

}

int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,

const unsigned char *from, int flen,

int num)

{

int i;

/* |em| is the encoded message, zero-padded to exactly |num| bytes */

unsigned char *em = NULL;

unsigned int good, found_zero_byte;

int zero_index = 0, msg_index, mlen = -1;

if (tlen < 0 || flen < 0)

return -1;

/*

* PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography Standard",

* section 7.2.2.

*/

if (flen > num)

goto err;

if (num < 11)

goto err;

em = OPENSSL_malloc(num);

if (em == NULL) {

RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, ERR_R_MALLOC_FAILURE);

return -1;

}

memset(em, 0, num);

/*

* Always do this zero-padding copy (even when num == flen) to avoid

* leaking that information. The copy still leaks some side-channel

* information, but it's impossible to have a fixed memory access

* pattern since we can't read out of the bounds of |from|.

*

* TODO(emilia): Consider porting BN_bn2bin_padded from BoringSSL.

*/

memcpy(em + num - flen, from, flen);

good = constant_time_is_zero(em[0]);

good &= constant_time_eq(em[1], 2);

found_zero_byte = 0;

for (i = 2; i < num; i++) {

unsigned int equals0 = constant_time_is_zero(em[i]);

zero_index =

constant_time_select_int(~found_zero_byte & equals0, i,

zero_index);

found_zero_byte |= equals0;

}

/*

* PS must be at least 8 bytes long, and it starts two bytes into |em|.

* If we never found a 0-byte, then |zero_index| is 0 and the check

* also fails.

*/

good &= constant_time_ge((unsigned int)(zero_index), 2 + 8);

/*

* Skip the zero byte. This is incorrect if we never found a zero-byte

* but in this case we also do not copy the message out.

*/

msg_index = zero_index + 1;

mlen = num - msg_index;

/*

* For good measure, do this check in constant time as well; it could

* leak something if |tlen| was assuming valid padding.

*/

good &= constant_time_ge((unsigned int)(tlen), (unsigned int)(mlen));

/*

* We can't continue in constant-time because we need to copy the result

* and we cannot fake its length. This unavoidably leaks timing

* information at the API boundary.

* TODO(emilia): this could be addressed at the call site,

* see BoringSSL commit 0aa0767340baf925bda4804882aab0cb974b2d26.

*/

if (!good) {

mlen = -1;

goto err;

}

memcpy(to, em + msg_index, mlen);

err:

if (em != NULL)

OPENSSL_free(em);

if (mlen == -1)

RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2,

RSA_R_PKCS_DECODING_ERROR);

return mlen;

}

// 无填充

int RSA_padding_add_none(unsigned char *to, int tlen,

const unsigned char *from, int flen)

{

if (flen > tlen) {

RSAerr(RSA_F_RSA_PADDING_ADD_NONE, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);

return (0);

}

if (flen < tlen) {

RSAerr(RSA_F_RSA_PADDING_ADD_NONE, RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE);

return (0);

}

memcpy(to, from, (unsigned int)flen);

return (1);

}

int RSA_padding_check_none(unsigned char *to, int tlen,

const unsigned char *from, int flen, int num)

{

if (flen > tlen) {

RSAerr(RSA_F_RSA_PADDING_CHECK_NONE, RSA_R_DATA_TOO_LARGE);

return (-1);

}

memset(to, 0, tlen - flen);

memcpy(to + tlen - flen, from, flen);

return (tlen);

}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值