`
lobin
  • 浏览: 427372 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

RSA Cryptography Specifications Version 2.1

 
阅读更多
写道
Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography
Specifications Version 2.1

 

 

目录

1介绍3

2标记法3

3密钥类型4

3.1RSA公钥4

3.2RSA私钥5

4数据转换原语6

4.1I2OSP6

4.2OS2IP7

5密码原语7

5.1加密解密原语7

5.1.1RSAEP7

5.1.2RSADP7

5.2签名和验证原语8

6方案概要8

7加密方案8

7.1RSAES-OAEP8

7.2RSAES-PKCS1-v1_58

8签名方案-附8

8.1RSASSA-PSS8

8.2RSASSA-PKCS1-v1_58

9签名的编码方式-附9

9.1EMSA-PSS9

9.2EMSA-PKCS1-v1_59

10Openssl9

10.1DER9

10.2PEM9

10.2.1例子:PEM格式内容9

10.3rsa_public_key.pem10

10.3.1PEM文件解析11

附录 A ASN.1语法19

A.1 RSA 密钥描述19

A.1.1 RSA 公钥语法19

A.1.2 RSA 私钥语法19

A.2 体系验证20

 

1介绍

文档提供了基于RSA算法的公钥密码体系的实现提议,包括以下几个方面:

*加密原语

*加密方案

*签名方案-附

*

 

在RSA wiki(https://en.wikipedia.org/wiki/RSA)上看到有如下描述:

RSA (cryptosystem), the Rivest-Shamir-Adleman cryptosystem, a cryptosystem for public-key encryption

从以上描述中可以看出RSA是一种公钥加密的密码系统。RSA也叫Rivest-Shamir-Adleman cryptosystem,由Ron Rivest, Adi Shamir和Leonard Adleman于MIT提出。RSA名称也是由Ron Rivest, Adi Shamir和Leonard Adleman三人名字中的首字母而来。

 

2标记法

 

3密钥类型

本文档中定义的原语和方案中使用了两种密钥类型:RSA公钥和RSA私钥。同时,RSA公钥和RSA私钥组成一个RSA密钥对。

该规范支持所谓的“多素数”("multi-prime")RSA,模数(modulus)可能有两个以上的素因子(prime factor)。

 

3.1RSA公钥

RSA公钥由两个组件组成:

n RSA模数,一个正整数

e RSA公开(public)指数,一个正整数

一个有效的RSA公钥,RSA模数n为u个不同的奇素数(r_i,i = 1, 2, ..., u,u>=2, 如r_1, r_2, r_3, r_4, r_5,…,r_u。)的乘积。RSA公开(public)指数e是一个3到n-1之间的正整数,满足:

GCD(e,\lambda(n)) = 1

 

其中\lambda(n)=LCM(r_1 - 1, ..., r_u - 1),例如一组奇素数r_1, r_2, r_3, r_4, r_5,r_6, r_7为2、3、5、7、11、13、17,那么\lambda(n)为1,2,4,6,10,12,16的公倍数。

 

按照惯例,开始的两个素数r_1和r_2也可能分别由p和q指定。

 

素数又称质数(prime number),有无限个。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数

质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数的数称为质数。

如2、3、5、7、11、13、17都是些素数

 

GCD(greatest common divisor),最大公约数。

LCM(least common multiple),最小公倍数。

 

3.2RSA私钥

一个RSA私钥可能有两种表示。

第一种表示由(n, d)对组成

n     RSA模数,一个正整数

d    RSA私有指数,一个正整数

第二种表示由一个5元组(p, q, dP, dQ, qInv)和一序列(可能为空)3元组(r_i, d_i, t_i)

组成。i = 3, ..., u,其中的每一个素数不会在5元组中出现。

 

p   首因子,一个正整数

q   次因子,一个正整数

dP  首因子的CRT指数,一个正整数

dQ  次因子的CRT指数,一个正整数

qInv  CRT系数(第一个),一个正整数

r_i   因子(第i个),一个正整数

d_i   因子(第i个)的CRT指数,一个正整数

t_i  因子(第i个)的CRT系数,一个正整数

对于第一种表示,一个有效的RSA私钥,RSA中的模数n和对应RSA公钥中的模数是相同的,并且模数n为u个不同的奇素数(r_i,i = 1, 2, ..., u,u>=2, 如r_1, r_2, r_3, r_4, r_5,…,r_u。)的乘积。RSA私有指数d是一个小于n的正整数,满足:

 

e * d == 1 (mod \lambda(n))

 

其中e是RSA公钥中的公开(public)指数,\lambda(n)的定义也和RSA公钥中定义的一样。

 

对于第二种表示,一个有效的RSA私钥,p和q这两个因子就是RSA模数n的开始两个素数因子(例如,r_1和r_2),CRT指数dP和dQ是一个分别小于p和q的正整数,满足:

e * dP == 1 (mod (p-1))

e * dQ == 1 (mod (q-1))

 

CRT系数qInv是一个小于p的正整数,满足:

q * qInv == 1 (mod p)

 

如果u>2, 这种表示将包含一个或多个3元组(r_i, d_i, t_i),i=3, ..., u。因子r_i就是RSA模数n额外的素数因子。每一个CRT指数d_i (i = 3, ..., u)满足:

e * d_i == 1 (mod (r_i - 1))

 

每一个CRT系数t_i (i = 3, ..., u)是一个小于r_i的正整数,满足:

R_i * t_i == 1 (mod r_i)

其中R_i = r_1 * r_2 * ... * r_(i-1)

 

 

 

4数据转换原语

文档中定义的体系使用了两种数据转换原语。

I2OSP:Integer-to-Octet-String原语

OS2IP: Octet-String-to-Integer原语

4.1I2OSP

I2OSP转换非负整数为一个指定长度的8位位组字符串(octet string)。

 

I2OSP (x, xLen)

 

输入:

x        将被转换的非负整数

xLen     返回的8位位组字符串(octet string)的长度。

 

输出:

X        对应的8位位组字符串(octet string),长度为xLen

 

错误: “传入的非负整数太大”

 

 

 

 

4.2OS2IP

 

5密码原语

 

5.1加密解密原语

加密原语输入一个表示明文的整数,在指定公钥下加密输出一个表示密文的整数,解密原语是加密原语的逆过程,输入表示密文的整数,在指定对应的私钥下输出恢复原来的表示明文的整数。

文档中定义加密体系使用了一对加密解密原语:

RSAEP/RSADP

RSAEP和RSADP围绕相同的数学操作,只是输入的密钥不同,RSAEP输入的是公钥,RSADP输入的是私钥。

这里定义的原语和IEEE标准 1363-2000 [26]中IFEP-RSA/IFDP-RSA是一致的(除非新增了RSA多素数的支持),同时兼容PKCS #1 v1.5

 

这两个原语主要的数学操作就是求幂。

 

5.1.1RSAEP

 

RSAEP(RSA Encryption primitives), RSA加密原语

 

RSAEP((n, e), m)

 

输入:

(n, e)  RSA公钥

m       信息描述,一个整数(0到n-1)

 

输出:

c       密文描述,一个整数(0到n-1)

 

错误:“信息描述超过了范围”

 

假定:RSA公钥(n, e)有效

 

步骤:

1、如果信息描述m不在0到n-1之间,输出“信息描述超过了范围”并退出。

2、对c作如下运算:c = m^e mod n

3、输出c。

 

5.1.2RSADP

RSADP(RSA Decryption primitives), RSA解密原语

RSADP (K, c)

输入:

K        RSA私钥,其中K可以是以下形式中的一个:

         - (n, d)对

         -一个5元组(p, q, dP, dQ, qInv)和一序列(可能为空)3元组(r_i, d_i, t_i), i = 3, ..., u

c        一个表示密文的整数,该整数在0到n-1之间。

 

输出:

m        一个表示明文的整数,该整数在0到n-1之间。

错误:“表示密文的整数超过了范围”

 

假定:RSA私钥K有效

 

步骤:

1、如果表示密文的整数c不在0到n-1之间,输出“表示密文的整数超过了范围”并退出。

2、对表示明文的整数m作如下运算:

a.如果K使用的是第一种形式:(n, d)对,对m作如下运算:m = c^d mod n

b.如果K使用的是第二种形式:一个5元组(p, q, dP, dQ, qInv)和一序列(可能为空)3元组(r_i, d_i, t_i), i = 3, ..., u,处理如下:

i.赋值m_1 = c^dP mod p,以及m_2 = c^dQ mod q

ii.如果u>2,赋值m_i = c^(d_i) mod r_i, i = 3, ..., u

iii.赋值h = (m_1 - m_2) * qInv mod p

iv.赋值m = m_2 + q * h

v.如果u>2,赋值R = r_1,并且遍历i=3到u,执行:

1.赋值R = R * r_(i-1)

2.赋值h = (m_i - m) * t_i mod r_i

3.赋值m = m + R * h

3、输出m

5.2签名和验证原语

 

6方案概要

 

7加密方案

 

7.1RSAES-OAEP

 

7.2RSAES-PKCS1-v1_5

 

8签名方案-附

 

8.1RSASSA-PSS

 

8.2RSASSA-PKCS1-v1_5

 

9签名的编码方式-附

 

9.1EMSA-PSS

 

9.2EMSA-PKCS1-v1_5

 

10Openssl

 

10.1DER

 

二进制DER编码

10.2PEM

 

PEM stands for Privacy Enhanced Mail. PEM文件采用的是ASCII(Base64)编码,PEM文件使用Base64进行编码。

 

10.2.1例子:PEM格式内容

-----BEGIN PRIVACY-ENHANCED MESSAGE-----

Proc-Type: 4,ENCRYPTED

Content-Domain: RFC822

DEK-Info: DES-CBC,F8143EDE5960C597

Originator-ID-Symmetric: linn@zendia.enet.dec.com,,

Recipient-ID-Symmetric: linn@zendia.enet.dec.com,ptf-kmc,3

Key-Info: DES-ECB,RSA-MD2,9FD3AAD2F2691B9A,

          B70665BB9BF7CBCDA60195DB94F727D3

Recipient-ID-Symmetric: pem-dev@tis.com,ptf-kmc,4

Key-Info: DES-ECB,RSA-MD2,161A3F75DC82EF26,

          E2EF532C65CBCFF79F83A2658132DB47

 

LLrHB0eJzyhP+/fSStdW8okeEnv47jxe7SJ/iN72ohNcUk2jHEUSoH1nvNSIWL9M

8tEjmF/zxB+bATMtPjCUWbz8Lr9wloXIkjHUlBLpvXR0UrUzYbkNpk0agV2IzUpk

J6UiRRGcDSvzrsoK+oNvqu6z7Xs5Xfz5rDqUcMlK1Z6720dcBWGGsDLpTpSCnpot

dXd/H5LMDWnonNvPCwQUHt==

-----END PRIVACY-ENHANCED MESSAGE-----

 

 

 

 

genrsa -out rsa_key.pem 1024

 

rsa -in rsa_key.pem -noout -text

 

genrsa -des -out rsa_key_endes.pem 1024

 

genrsa -des3 -out rsa_key_endes3.pem 1024

 

genrsa -aes128 -out rsa_key_enaes128.pem 1024

 

 

pkcs8 -topk8 -inform PEM -in rsa_key.pem -outform PEM -nocrypt -out key.pem

 

 

rsa -in rsa_key.pem -pubout -out rsa_public_key.pem

 

10.3rsa_public_key.pem

假设生成的RSA公钥(rsa_public_key.pem文件)内容如下:

 

-----BEGIN PUBLIC KEY-----

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDW/XkRFZ+FtYB3bfHYnRoLyRIm

ch4+6ymFh3K8O9Cbb0HZg64MLi3lnyW3zoqMWjUI5aszCoZ2duqNy/BSBFtmuBGn

OK6i6QWmPZu+c8NpfVbWe5GxWXg/yeaYv5GlpA2hBlnDw3UDUdl6pyZyUH+PAN5i

yQwAq7JjDh8p9V4G9QIDAQAB

-----END PUBLIC KEY-----

 

10.3.1PEM文件解析

 

typedef void bio_info_cb(struct bio_st *, int, const char *, int, long, long);

 

struct crypto_ex_data_st

{

STACK_OF(void) *sk;

int dummy; /* gcc is screwing up this data structure :-( */

};

 

typedef struct crypto_ex_data_st CRYPTO_EX_DATA;

 

 

struct bio_st

{

BIO_METHOD *method;

/* bio, mode, argp, argi, argl, ret */

long (*callback)(struct bio_st *,int,const char *,int, long,long);

char *cb_arg; /* first argument for the callback */

 

int init;

int shutdown;

int flags;/* extra storage */

int retry_reason;

int num;

void *ptr;

struct bio_st *next_bio;/* used by filter BIOs */

struct bio_st *prev_bio;/* used by filter BIOs */

int references;

unsigned long num_read;

unsigned long num_write;

 

CRYPTO_EX_DATA ex_data;

};

 

 

typedef struct bio_st BIO;

 

 

typedef struct bio_method_st

{

int type;

const char *name;

int (*bwrite)(BIO *, const char *, int);

int (*bread)(BIO *, char *, int);

int (*bputs)(BIO *, const char *);

int (*bgets)(BIO *, char *, int);

long (*ctrl)(BIO *, int, long, void *);

int (*create)(BIO *);

int (*destroy)(BIO *);

        long (*callback_ctrl)(BIO *, int, bio_info_cb *);

} BIO_METHOD;

 

static int MS_CALLBACK file_gets(BIO *bp, char *buf, int size)

{

int ret=0;

 

buf[0]='\0';

if (bp->flags&BIO_FLAGS_UPLINK)

{

if (!UP_fgets(buf,size,bp->ptr))

goto err;

}

else

{

if (!fgets(buf,size,(FILE *)bp->ptr))

goto err;

}

if (buf[0] != '\0')

ret=strlen(buf);

err:

return(ret);

}

 

 

static BIO_METHOD methods_filep=

{

BIO_TYPE_FILE,

"FILE pointer",

file_write,

file_read,

file_puts,

file_gets,

file_ctrl,

file_new,

file_free,

NULL,

};

 

BIO_METHOD *BIO_s_file(void)

{

return(&methods_filep);

}

 

BIO *BIO_new(BIO_METHOD *method)

{

BIO *ret=NULL;

 

ret=(BIO *)OPENSSL_malloc(sizeof(BIO));

if (ret == NULL)

{

BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE);

return(NULL);

}

if (!BIO_set(ret,method))

{

OPENSSL_free(ret);

ret=NULL;

}

return(ret);

}

 

long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)

{

long ret;

long (*cb)(BIO *,int,const char *,int,long,long);

 

if (b == NULL) return(0);

 

if ((b->method == NULL) || (b->method->ctrl == NULL))

{

BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);

return(-2);

}

 

cb=b->callback;

 

if ((cb != NULL) &&

((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0))

return(ret);

 

ret=b->method->ctrl(b,cmd,larg,parg);

 

if (cb != NULL)

ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd,

larg,ret);

return(ret);

}

 

 

#define BIO_set_fp(b,fp,c)BIO_ctrl(b,BIO_C_SET_FILE_PTR,c,(char *)fp)

 

int BIO_gets(BIO *b, char *in, int inl)

{

int i;

long (*cb)(BIO *,int,const char *,int,long,long);

 

if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL))

{

BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD);

return(-2);

}

 

cb=b->callback;

 

if ((cb != NULL) &&

((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0))

return(i);

 

if (!b->init)

{

BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED);

return(-2);

}

 

i=b->method->bgets(b,in,inl);

 

if (cb != NULL)

i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl,

0L,(long)i);

return(i);

}

 

 

int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,

    long *len)

{

EVP_ENCODE_CTX ctx;

int end=0,i,k,bl=0,hl=0,nohead=0;

char buf[256];

BUF_MEM *nameB;

BUF_MEM *headerB;

BUF_MEM *dataB,*tmpB;

 

nameB=BUF_MEM_new();

headerB=BUF_MEM_new();

dataB=BUF_MEM_new();

if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL))

{

BUF_MEM_free(nameB);

BUF_MEM_free(headerB);

BUF_MEM_free(dataB);

PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);

return(0);

}

 

buf[254]='\0';

for (;;)

{

i=BIO_gets(bp,buf,254);

 

if (i <= 0)

{

PEMerr(PEM_F_PEM_READ_BIO,PEM_R_NO_START_LINE);

goto err;

}

 

while ((i >= 0) && (buf[i] <= ' ')) i--;

buf[++i]='\n'; buf[++i]='\0';

 

if (strncmp(buf,"-----BEGIN ",11) == 0)

{

i=strlen(&(buf[11]));

 

if (strncmp(&(buf[11+i-6]),"-----\n",6) != 0)

continue;

if (!BUF_MEM_grow(nameB,i+9))

{

PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);

goto err;

}

memcpy(nameB->data,&(buf[11]),i-6);

nameB->data[i-6]='\0';

break;

}

}

hl=0;

if (!BUF_MEM_grow(headerB,256))

{ PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }

headerB->data[0]='\0';

for (;;)

{

i=BIO_gets(bp,buf,254);

if (i <= 0) break;

 

while ((i >= 0) && (buf[i] <= ' ')) i--;

buf[++i]='\n'; buf[++i]='\0';

 

if (buf[0] == '\n') break;

if (!BUF_MEM_grow(headerB,hl+i+9))

{ PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }

if (strncmp(buf,"-----END ",9) == 0)

{

nohead=1;

break;

}

memcpy(&(headerB->data[hl]),buf,i);

headerB->data[hl+i]='\0';

hl+=i;

}

 

bl=0;

if (!BUF_MEM_grow(dataB,1024))

{ PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }

dataB->data[0]='\0';

if (!nohead)

{

for (;;)

{

i=BIO_gets(bp,buf,254);

if (i <= 0) break;

 

while ((i >= 0) && (buf[i] <= ' ')) i--;

buf[++i]='\n'; buf[++i]='\0';

 

if (i != 65) end=1;

if (strncmp(buf,"-----END ",9) == 0)

break;

if (i > 65) break;

if (!BUF_MEM_grow_clean(dataB,i+bl+9))

{

PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);

goto err;

}

memcpy(&(dataB->data[bl]),buf,i);

dataB->data[bl+i]='\0';

bl+=i;

if (end)

{

buf[0]='\0';

i=BIO_gets(bp,buf,254);

if (i <= 0) break;

 

while ((i >= 0) && (buf[i] <= ' ')) i--;

buf[++i]='\n'; buf[++i]='\0';

 

break;

}

}

}

else

{

tmpB=headerB;

headerB=dataB;

dataB=tmpB;

bl=hl;

}

i=strlen(nameB->data);

if ((strncmp(buf,"-----END ",9) != 0) ||

(strncmp(nameB->data,&(buf[9]),i) != 0) ||

(strncmp(&(buf[9+i]),"-----\n",6) != 0))

{

PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_END_LINE);

goto err;

}

 

EVP_DecodeInit(&ctx);

i=EVP_DecodeUpdate(&ctx,

(unsigned char *)dataB->data,&bl,

(unsigned char *)dataB->data,bl);

if (i < 0)

{

PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE);

goto err;

}

i=EVP_DecodeFinal(&ctx,(unsigned char *)&(dataB->data[bl]),&k);

if (i < 0)

{

PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE);

goto err;

}

bl+=k;

 

if (bl == 0) goto err;

*name=nameB->data;

*header=headerB->data;

*data=(unsigned char *)dataB->data;

*len=bl;

OPENSSL_free(nameB);

OPENSSL_free(headerB);

OPENSSL_free(dataB);

return(1);

err:

BUF_MEM_free(nameB);

BUF_MEM_free(headerB);

BUF_MEM_free(dataB);

return(0);

}

 

 

int PEM_read(FILE *fp, char **name, char **header, unsigned char **data,

    long *len)

        {

        BIO *b;

        int ret;

 

        if ((b=BIO_new(BIO_s_file())) == NULL)

{

PEMerr(PEM_F_PEM_READ,ERR_R_BUF_LIB);

                return(0);

}

        BIO_set_fp(b,fp,BIO_NOCLOSE);

        ret=PEM_read_bio(b, name, header, data,len);

        BIO_free(b);

        return(ret);

        }

 

附录 A ASN.1语法

 

A.1 RSA 密钥描述

 

A.1.1 RSA 公钥语法

 

RSAPublicKey ::= SEQUENCE {

modulus           INTEGER,  -- n

publicExponent    INTEGER   -- e

}

 

A.1.2 RSA 私钥语法

 

RSAPrivateKey ::= SEQUENCE {

version           Version,

modulus           INTEGER,  -- n

publicExponent    INTEGER,  -- e

privateExponent   INTEGER,  -- d

prime1            INTEGER,  -- p

prime2            INTEGER,  -- q

exponent1         INTEGER,  -- d mod (p-1)

exponent2         INTEGER,  -- d mod (q-1)

coefficient       INTEGER,  -- (inverse of q) mod p

otherPrimeInfos   OtherPrimeInfos OPTIONAL

}

 

 

A.2 体系验证

 

Java RSA加密解密实例

private static RSAPrivateKey privateKey = null;
private static byte[] privateKeyEncoded = null;

private static RSAPublicKey publicKey = null;
private static byte[] publicKeyEncoded = null;

@BeforeClass
public static void init() /* throws NoSuchAlgorithmException */ {
    KeyPairGenerator keyPairGenerator = null;
    try {
        keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    } catch (NoSuchAlgorithmException e) {
        Assert.fail("no such algorithm: " + e.getMessage());
    }
    keyPairGenerator.initialize(512);
    KeyPair keyPair = keyPairGenerator.generateKeyPair();

    privateKey = (RSAPrivateKey) keyPair.getPrivate();
    publicKey = (RSAPublicKey) keyPair.getPublic();

    privateKeyEncoded = ((Key) privateKey).getEncoded();
    publicKeyEncoded = ((Key) publicKey).getEncoded();
    System.out.println("private key: " + Base64.byteArrayToBase64(privateKeyEncoded));
    System.out.println("public key: " + Base64.byteArrayToBase64(publicKeyEncoded));
}

 

加密解密

@org.junit.Test
public void test() {
    String message = "13120983870";
    System.out.println(message);

    PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyEncoded);
    KeyFactory keyFactory = null;
    try {
        keyFactory = KeyFactory.getInstance("RSA");
    } catch (NoSuchAlgorithmException e) {
        Assert.fail("no such algorithm: " + e.getMessage());
    }

    PrivateKey privateKey = null;
    try {
        privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
    } catch (InvalidKeySpecException e) {
        Assert.fail("invalid key spec: " + e.getMessage());
    }
    System.out.println("private key: " + Base64.byteArrayToBase64(((Key) privateKey).getEncoded()));

    Cipher cipher = null;
    try {
        cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    } catch (NoSuchAlgorithmException e) {
        Assert.fail("no such algorithm: " + e.getMessage());
    } catch (NoSuchPaddingException e) {
        Assert.fail("no such padding: " + e.getMessage());
    }
    try {
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
    } catch (InvalidKeyException e) {
        Assert.fail("invalid key: " + e.getMessage());
    }

    byte[] encryption = null;
    try {
        encryption = cipher.doFinal(message.getBytes());
    } catch (IllegalBlockSizeException e) {
        Assert.fail("illegal block size: " + e.getMessage());
    } catch (BadPaddingException e) {
        Assert.fail("bad padding: " + e.getMessage());
    }
    System.out.println("encryption: " + Base64.byteArrayToBase64(encryption));


    X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyEncoded);
    try {
        keyFactory = KeyFactory.getInstance("RSA");
    } catch (NoSuchAlgorithmException e) {
        Assert.fail("no such algorithm: " + e.getMessage());
    }
    PublicKey publicKey = null;
    try {
        publicKey = keyFactory.generatePublic(x509KeySpec);
    } catch (InvalidKeySpecException e) {
        Assert.fail("invalid key spec: " + e.getMessage());
    }
    System.out.println("public key: " + Base64.byteArrayToBase64(((Key) publicKey).getEncoded()));
    try {
        cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    } catch (NoSuchAlgorithmException e) {
        Assert.fail("no such algorithm: " + e.getMessage());
    } catch (NoSuchPaddingException e) {
        Assert.fail("no such padding: " + e.getMessage());
    }
    try {
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
    } catch (InvalidKeyException e) {
        Assert.fail("invalid key: " + e.getMessage());
    }

    byte[] decryption = null;
    try {
        decryption = cipher.doFinal(encryption);
    } catch (IllegalBlockSizeException e) {
        Assert.fail("illegal block size: " + e.getMessage());
    } catch (BadPaddingException e) {
        Assert.fail("bad padding: " + e.getMessage());
    }
    System.out.println("decryption: " + new String(decryption) + ", base64:" + Base64.byteArrayToBase64(decryption));
}

 

 

/**
 * 使用私钥加密,再使用公钥解密
 */
@org.junit.Test
public void test1() {
    String message = "13120983870";
    System.out.println(message);

    // 加密
    Cipher cipher = null;
    try {
        cipher = Cipher.getInstance("RSA");
    } catch (NoSuchAlgorithmException e) {
        Assert.fail("no such algorithm: " + e.getMessage());
    } catch (NoSuchPaddingException e) {
        Assert.fail("no such padding: " + e.getMessage());
    }
    try {
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
    } catch (InvalidKeyException e) {
        Assert.fail("invalid key: " + e.getMessage());
    }

    byte[] encryption = null;
    try {
        encryption = cipher.doFinal(message.getBytes());
    } catch (IllegalBlockSizeException e) {
        Assert.fail("illegal block size: " + e.getMessage());
    } catch (BadPaddingException e) {
        Assert.fail("bad padding: " + e.getMessage());
    }
    System.out.println("encryption: " + Base64.byteArrayToBase64(encryption));

    // 解密
    try {
        cipher = Cipher.getInstance("RSA");
    } catch (NoSuchAlgorithmException e) {
        Assert.fail("no such algorithm: " + e.getMessage());
    } catch (NoSuchPaddingException e) {
        Assert.fail("no such padding: " + e.getMessage());
    }
    try {
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
    } catch (InvalidKeyException e) {
        Assert.fail("invalid key: " + e.getMessage());
    }

    byte[] decryption = null;
    try {
        decryption = cipher.doFinal(encryption);
    } catch (IllegalBlockSizeException e) {
        Assert.fail("illegal block size: " + e.getMessage());
    } catch (BadPaddingException e) {
        Assert.fail("bad padding: " + e.getMessage());
    }
    System.out.println("decryption: " + new String(decryption) + ", base64:" + Base64.byteArrayToBase64(decryption));
}

 

private key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAhLKv2wOrV2BGqXxRyrLSJ6jzMey1kxuthXFO+EBjiI7GuTxYpr6lXxyrfnwuhBz0OrXS4QatE9PT2JudFWMsSQIDAQABAkBSNtM1goR50jB1eYzDZR9Haymh2OJ2jkNn1dfzfxEr3UTjlhv42v7FfmLWl0TISEuW5AxZyZBFHhWP7YNF3RYBAiEAxRixL6dmIpRxndVxcCvml16Cn3J+NDkRyWmzwS0WyXECIQCsWwu6+P88wUEOFTgQ/Z5EQFkCXm5h6dL/EmhUordkWQIgTCvuzmvznQmhn04OOTu+MmHkOZsWCzjDFwQy5EV4uQECIEwTN79EbmxjpJJRvViKiVP4zxDjm3cuXQpnFpPc6nOpAiAEiLzfZvzCI4Vx3KxGrOLxaTWC9KbpCG3IRsLBMN/EqA==
public key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAISyr9sDq1dgRql8Ucqy0ieo8zHstZMbrYVxTvhAY4iOxrk8WKa+pV8cq358LoQc9Dq10uEGrRPT09ibnRVjLEkCAwEAAQ==
13120983870
encryption: ZVT1Gt5cP/KHmogMcWU0TxLm1hYqRXzqsvLCvQr9pDgjVA+yzXM6IWZSdXf2dm+j9XeGS72bHayOIo7Py+tEbQ==
decryption: 13120983870, base64:MTMxMjA5ODM4NzA=

 

Java RSA数字签名实例

 

/**
 * private key: MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEApTHMs+zR16SE0v3npoVbMGo70xX5tJ7HF23SvM2rARkJNtRs4xZRQpWQ1JBZnGna9HcVQsrRAORqYhhTrZ9rMQIDAQABAkAFNrlYrasZErJGQEEiIWP9lwHCvZchLTB4j+TahIV+2iLTiLa21QOqQFmpBqw/uqmHsJGtqtHIXdtgCrGtoLVhAiEA4zpbZ52vkCskvZ2eJ34n6dTsiybZLIMYIdp21kd6mpECIQC6HJ2f0R6BwL/ORYhF6tA1YeXZEKyAuTgDkwgmGN/WoQIgPsXrZHeafbB9iOiXPX/LlPyekF6eFn7s1sVcmRvMEhECIBnJDS2vU4K2qdxyVccaGW7L+YRxgvTytIgKPv7IQ3sBAiEAh3XrxyuR3nJhFD5pPcRLmnst9Ag6WQuthc/SgkKJlXk=
 * public key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKUxzLPs0dekhNL956aFWzBqO9MV+bSexxdt0rzNqwEZCTbUbOMWUUKVkNSQWZxp2vR3FULK0QDkamIYU62fazECAwEAAQ==
 */
@Test
public void signAndVerityWithEncoded0() {
    String privateKey = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEApTHMs+zR16SE0v3npoVbMGo70xX5tJ7HF23SvM2rARkJNtRs4xZRQpWQ1JBZnGna9HcVQsrRAORqYhhTrZ9rMQIDAQABAkAFNrlYrasZErJGQEEiIWP9lwHCvZchLTB4j+TahIV+2iLTiLa21QOqQFmpBqw/uqmHsJGtqtHIXdtgCrGtoLVhAiEA4zpbZ52vkCskvZ2eJ34n6dTsiybZLIMYIdp21kd6mpECIQC6HJ2f0R6BwL/ORYhF6tA1YeXZEKyAuTgDkwgmGN/WoQIgPsXrZHeafbB9iOiXPX/LlPyekF6eFn7s1sVcmRvMEhECIBnJDS2vU4K2qdxyVccaGW7L+YRxgvTytIgKPv7IQ3sBAiEAh3XrxyuR3nJhFD5pPcRLmnst9Ag6WQuthc/SgkKJlXk=";
    String publicKey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKUxzLPs0dekhNL956aFWzBqO9MV+bSexxdt0rzNqwEZCTbUbOMWUUKVkNSQWZxp2vR3FULK0QDkamIYU62fazECAwEAAQ==";

    byte[] privateKeyEncoded = Base64.base64ToByteArray(privateKey);
    byte[] publicKeyEncoded = Base64.base64ToByteArray(publicKey);

    String message = "13120983870";
    System.out.println(message);

    signAndVerity(message, privateKeyEncoded, publicKeyEncoded);
}

 

private void signAndVerity(String message, byte[] privateKeyEncoded, byte[] publicKeyEncoded) {
    // 签名
    PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyEncoded);
    KeyFactory keyFactory = null;
    try {
        keyFactory = KeyFactory.getInstance("RSA");
    } catch (NoSuchAlgorithmException e) {
        Assert.fail("no such algorithm: " + e.getMessage());
    }

    PrivateKey privateKey = null;
    try {
        privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
    } catch (InvalidKeySpecException e) {
        Assert.fail("invalid key spec: " + e.getMessage());
    }
    System.out.println("private key: " + Base64.byteArrayToBase64(((Key) privateKey).getEncoded()));

    Signature signature = null;
    try {
        signature = Signature.getInstance("MD5withRSA");
    } catch (NoSuchAlgorithmException e) {
        Assert.fail("no such algorithm: " + e.getMessage());
    }
    try {
        signature.initSign(privateKey);
    } catch (InvalidKeyException e) {
        Assert.fail("invalid key: " + e.getMessage());
    }

    byte[] sign = null;
    try {
        signature.update(message.getBytes());
        sign = signature.sign();
    } catch (SignatureException e) {
        Assert.fail("signature: " + e.getMessage());
    }
    System.out.println("signature: " + Base64.byteArrayToBase64(sign));

    // 验证
    X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyEncoded);
    try {
        keyFactory = KeyFactory.getInstance("RSA");
    } catch (NoSuchAlgorithmException e) {
        Assert.fail("no such algorithm: " + e.getMessage());
    }
    PublicKey publicKey = null;
    try {
        publicKey = keyFactory.generatePublic(x509KeySpec);
    } catch (InvalidKeySpecException e) {
        Assert.fail("invalid key spec: " + e.getMessage());
    }
    System.out.println("public key: " + Base64.byteArrayToBase64(((Key) publicKey).getEncoded()));
    try {
        signature.initVerify(publicKey);
    } catch (InvalidKeyException e) {
        Assert.fail("invalid key: " + e.getMessage());
    }

    byte[] decryption = null;
    try {
        signature.update(message.getBytes());
        boolean result = signature.verify(sign);
        Assert.assertTrue(result);
    } catch (SignatureException e) {
        Assert.fail("signature: " + e.getMessage());
    }
}

 

private key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA36Luv7yDI5RCnvC/d8HFvqXHa5Iry2bBX1qDo2KQkzlMzr5mVnMCk3WOA49PVyQ9EPJa7kIrfRlSdp38R3FB1wIDAQABAkA5nUxM8VAHtoaDVBq/y5gaSbNar0nBGTPwUO1hBl+gzcMGgPEw4F1DaYelt+dUxbD7po4OPiiHz/F5+HJAV5SBAiEA72yOz+HfhCqkvQ5l4dSIpoSmfcw05CxnMBe2p+FtskcCIQDvHpAGQ8po0l0NIgyK+bUIuuHDOUb5ePWtiA4kSrGr8QIgWfgONlnndy/bFdv6NwF5lDFWqwD4gyGYaP8QOUfBw/MCIBQJx5/+xlOKbWnQVKTA0D7vCkRF5IC7djsYj7bS25jBAiAS/IX4KRsV9TayXXDeuqaD8Z+ONQ/98xJwAabcNAmXrA==
public key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAN+i7r+8gyOUQp7wv3fBxb6lx2uSK8tmwV9ag6NikJM5TM6+ZlZzApN1jgOPT1ckPRDyWu5CK30ZUnad/EdxQdcCAwEAAQ==
13120983870
private key: MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEApTHMs+zR16SE0v3npoVbMGo70xX5tJ7HF23SvM2rARkJNtRs4xZRQpWQ1JBZnGna9HcVQsrRAORqYhhTrZ9rMQIDAQABAkAFNrlYrasZErJGQEEiIWP9lwHCvZchLTB4j+TahIV+2iLTiLa21QOqQFmpBqw/uqmHsJGtqtHIXdtgCrGtoLVhAiEA4zpbZ52vkCskvZ2eJ34n6dTsiybZLIMYIdp21kd6mpECIQC6HJ2f0R6BwL/ORYhF6tA1YeXZEKyAuTgDkwgmGN/WoQIgPsXrZHeafbB9iOiXPX/LlPyekF6eFn7s1sVcmRvMEhECIBnJDS2vU4K2qdxyVccaGW7L+YRxgvTytIgKPv7IQ3sBAiEAh3XrxyuR3nJhFD5pPcRLmnst9Ag6WQuthc/SgkKJlXk=
signature: YVuyrhVPkQhydhWWe9+TMAPnDCRVpy3mM0Q2tDQsWhJTOntYlH7t7/ENj76flzOmXr6zSfNZX6Qnh2SbRQkm+Q==
public key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKUxzLPs0dekhNL956aFWzBqO9MV+bSexxdt0rzNqwEZCTbUbOMWUUKVkNSQWZxp2vR3FULK0QDkamIYU62fazECAwEAAQ==

 

 

1、PKCS #1: RSA Encryption Version 1.5,https://www.rfc-editor.org/rfc/rfc2313.txt

2、PKCS #1: RSA Cryptography Specifications Version 2.0,https://www.ietf.org/rfc/rfc2437.txt

3、Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.1,https://www.rfc-editor.org/rfc/rfc3447.txt

4、https://people.cs.umass.edu/~emery/classes/cmpsci691st/scribe/lecture14-rsa.pdf

5、https://en.wikipedia.org/wiki/RSA_(cryptosystem)

6、https://en.wikipedia.org/wiki/RSA

7、PEM, Privacy Enhancement for Internet Electronic Mail: Part I: Message Encipherment and Authentication Procedures, https://www.rfc-editor.org/rfc/rfc1040.txt

8、PEM, Privacy Enhancement for Internet Electronic Mail: Part I -- Message Encipherment and Authentication Procedures, https://www.rfc-editor.org/rfc/rfc1113.txt

9、PEM,Privacy Enhancement for Internet Electronic Mail: Part I: Message Encryption and Authentication Procedures,https://www.rfc-editor.org/rfc/rfc1421.txt

10、PEM, Privacy Enhancement for Internet Electronic Mail: Part II: Certificate-Based Key Management, https://www.rfc-editor.org/rfc/rfc1422.txt

11、PEM, Privacy Enhancement for Internet Electronic Mail: Part III: Algorithms, Modes, and Identifiers, https://www.rfc-editor.org/rfc/rfc1423.txt

12、PEM, Privacy Enhancement for Internet Electronic Mail: Part IV: Key Certification and Related Services, https://www.rfc-editor.org/rfc/rfc1424.txt

 

分享到:
评论

相关推荐

    PKCS #1: RSA Cryptography Specifications Version 2.2

    PKCS #1(Public-Key Cryptography Standards #1)是RSA安全公司制定的一系列公开密钥加密标准之一,其中“PKCS #1: RSA Cryptography Specifications Version 2.2”是关于RSA算法实施的重要规范,详细定义了基于RSA...

    psck 公钥证书标准(英文版)

    总之,《PKCS #1: RSA Cryptography Specifications Version 2.1》是一份详尽的技术文档,不仅为实现基于RSA算法的公钥密码系统提供了全面的指导,还深入介绍了RSA算法本身及其各种应用场景。这对于理解和应用RSA...

    rsa.rar_rsa

    RFC3447,又称为“Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.1”,是由互联网工程任务组(IETF)发布的一份规范,详细定义了RSA算法的操作和安全建议。该文档涵盖了...

    RSA_密码学_

    RFC文档是互联网相关的技术规范和协议,关于RSA,可能参考的是RFC 3447(Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.1)。遵循RFC标准能确保实现的兼容性和安全性。...

    PKCS #1 v2.2 RSA Cryptography Standard.pdf

    RSA加密标准,全称为Public-Key Cryptography Standards(公钥密码标准)的第1号标准版本2.2,由RSA实验室于2012年10月27日发布。这一标准规范了基于RSA算法的公钥加密技术的应用,内容广泛,涵盖了密码学原语、加密...

    java安全算法RSA 工具类

    ### Java安全算法RSA...- [RFC 3447 - PKCS #1: RSA Cryptography Specifications Version 2.1](https://tools.ietf.org/html/rfc3447) - [Bouncy Castle Cryptography APIs](http://www.bouncycastle.org/java.html)

    RSA加密手册 (2.1)

    在RSA加密手册(2.1)中,详细介绍了RSA加密的各种技术细节和实施标准。根据手册内容,以下是相关的知识点: 1. RSA公钥和私钥:RSA算法中包含两种密钥,分别是公钥和私钥。公钥可以公开,用于加密数据;私钥必须...

    RSA PKCS1-2.1 RSAEP_OAEP补位、去补位源码

    PKCS(Public Key Cryptography Standards)是由RSA安全公司制定的一系列密码学标准,其中PKCS#1是关于RSA密钥管理和操作的标准。在PKCS#1 v2.1中,RSAEP_OAEP是对RSA加密操作的一种增强方式,它引入了OAEP(Optimal...

    PKCS #5- Password-Based Cryptography Specification Version 2.0.pdf

    PKCS #5是RSA实验室发布的公钥密码标准(PKCS)系列的一部分,其文档编号为PKCS#5 v2.0,该版本由B. Kaliski起草,当前为草稿状态,有效期至2000年11月。该文档为密码学领域提供了基于密码的加密规范建议,旨在为...

    PKCS #1 v2.1: RSA Cryptography Standard

    PKCS #1 v2.1 是 RSA 加密标准的一个版本,由 RSA 实验室发布,旨在为基于 RSA 算法的公钥密码学提供实施建议。该标准涵盖了以下几个核心方面: 1. **加密原语**:PKCS #1 提供了 RSA 加密的基本操作,包括加密...

    pkcs-1v2-1 RSA Cryptography Standard 中文版

    在PKCS#1 v2.1标准中,详细规定了RSA加密和签名的机制,包括RSA加密过程(RSAEP)、RSA解密过程(RSADP)、以及用于数字签名的RSA签名过程(RSASP1)和验证过程(RSAVP1)。其中,RSAES-OAEP(Optimal Asymmetric ...

    RSA公司的PKCS系列标准

    PKCS #1 v2.1: RSA Cryptography Standard PKCS #1 v2.0: RSA Cryptography Standard PKCS #1 v2.0 Amendment 1: Multi-Prime RSA PKCS #1: RSA Encryption Standard PKCS #3: Diffie-Hellman Key-Agreement ...

    PKCS#1 RSA 算法标准.doc

    PKCS(Public-Key Cryptography Standards)是由RSA安全公司制定的一系列标准,其中PKCS#1是关于RSA算法的标准,详细定义了RSA算法的使用方式和数据格式。 在PKCS#1 v2.1版本中,主要涵盖了RSA算法的实现细节,包括...

    RSA程序算法分析.rar_RSA 算法_RSA算法_c RSA_cryptography_rsa

    RSA算法是一种非对称加密算法,它在信息安全领域扮演着至关重要的角色,特别是在网络通信、数据加密和数字签名等方面。该算法由Ron Rivest、Adi Shamir和Leonard Adleman于1977年提出,因此得名RSA。在C语言中实现...

    PKCS__1_v2.1_RSA_算法标准+RSA-oaep_spec

    《PKCS#1 v2.1 RSA算法标准》是中国版的RSA算法标准文档,PKCS(Public Key Cryptography Standards)是由RSA安全公司制定的一系列公开密钥加密标准,其中PKCS#1主要涉及RSA公钥加密算法。该标准详细规定了RSA加密、...

    PKCS__1_v2.1_RSA_算法标准.pdf

    PKCS__1_v2.1_RSA_算法标准.pdf 中文版 这篇文档是介绍基于 RSA 算法[42]的公钥密码系统的实现方法的,它包括以下几个方面: z 密码原语 z 加密方案 z 带附属的签名方案 z 密钥和方案的 ASN.1 描述

    RSA 加密程序 Version 1.5(支持文件、文本加密解密, 支持多种语言)

    采用Visual C++ 6.0开发的一个RSA加解密工具。支持文件加密、文件解密、文本加密、文本解密。 此版本相对于1.0版本加入了本地化的功能,支持英文、简体中文和繁体中文三种语言方案,可以动态在配置文件里面根据需要...

    RSA 加密工具 Version 1.0(支持文件、文本加密解密)

    采用Visual C++ 6.0开发的一个RSA加解密工具。支持文件加密、文件解密、文本加密、文本解密。 文件包括源代码和安装包,源代码里包括自定义的RSA加密解密模型,方便复用。 程序采用分层的设计方案,将底层的RSA加密...

    RSA.rar_RSA implementation_cryptography rsa_rsa_密码学_密码学RSA

    RSA算法,全称为Rivest-Shamir-Adleman,是公钥密码学领域中最著名的一种非对称加密算法,由Ron Rivest、Adi Shamir和Leonard Adleman在1977年提出。它在互联网安全、数字签名、数据加密等方面有着广泛的应用。RSA的...

Global site tag (gtag.js) - Google Analytics