RSA

GCD-greatest common divisor       最大公约数

Modular exponentiation   模幂运算;模指数运算

modulus          模数

exponent        指数

denominator   分母

Montgomery precomputation   蒙哥马利预计算    大整数幂取模算法   “蒙哥马利算法” 也叫反复平方法 【计算  超大整数 的 超大数次幂  然后  对超大整数取模】 

Euclid扩展算法(扩展欧几里得算法)      计算私钥d

公钥密码学标准 PKCS (Public Key Cryptography Standards)

公钥基础设施     PKIX  (Public-Key Infrastructure X.509)


RSA的三个重要大数:公钥指数e、私钥指数d和模值n。但我们说的“密钥长度”一般只是指模值的位长度。目前主流可选值:1024、2048、3072、4096...

公钥指数是随意选的,但目前行业上公钥指数普遍选的都是65537(0x10001,5bits),该值是除了1、3、5、17、257之外的最小素数,为什么不选的大一点?当然可以,只是考虑到既要满足相对安全、又想运算的快一点(加密时),PKCS#1的一个建议值而已。

在实际运算和存储时为方便一般都是按照标准位长进行使用,前面不足部分补0填充,所以,使用保存和转换这些密钥需要注意统一缓冲区的长度。

RSA,常说的非对称加密。加密解密密钥不一致,它们是成对出现,公钥加密的私钥解密,私钥加密的要公钥解密。本工具支持RSA超长文本公私钥加密,将长文本以特定字符分隔然后连接。往往私钥是不公开的,公钥是大家共享的。相同内容,相同私钥每次加密后结果还会不一样。RSA已被ISO推荐为公钥数据加密标准,能够阻击各种破解方案。 本工具提供公钥加密,解密功能。 通过公钥加密结果,必须私钥解密。 同样私钥加密结果,公钥可以解密。RSA加密也是块加密,因此一样存在填充模式。默认填充方式是pkcs#1。另外 私钥加密解密模块,可以看这里RSA私钥加密解密 生成RSA密钥对。 

RSA是一种块文件加密系统,他需要将输入的数据分zhi成固定大小的块,然后对这些数据块进行加密。加密以后输出的数据块长度和输入时一样的。你发现加密后的长度不同的话,应该是RSA加密的那个padding(填充)配置不一样,从而使得每次加密数据块的长度不同,这样最后出来的长度也就不一样了。

明文长度:

明文长度需要小于密钥长度,而密文长度则等于密钥长度。因此当加密内容长度大于密钥长度时,有效的RSA加解密就需要对内容进行分段。

网上有说明文长度小于等于密钥长度(Bytes)-11,这说法本身不太准确,会给人感觉RSA 1024只能加密117字节长度明文。实际上,RSA算法本身要求加密内容也就是明文长度m必须0<m<n,也就是说内容这个大整数不能超过n,否则就出错。那么如果m=0是什么结果?普遍RSA加密器会直接返回全0结果。如果m>n,运算就会出错?!那怎么办?且听下文分解。

所以,RSA实际可加密的明文长度最大也是1024bits,但问题就来了:

如果小于这个长度怎么办?就需要进行padding,因为如果没有padding,用户无法确分解密后内容的真实长度,字符串之类的内容问题还不大,以0作为结束符,但对二进制数据就很难理解,因为不确定后面的0是内容还是内容结束符。

只要用到padding,那么就要占用实际的明文长度,于是才有117字节的说法。我们一般使用的padding标准有NoPPadding、OAEPPadding、PKCS1Padding等,其中PKCS#1建议的padding就占用了11个字节。

如果大于这个长度怎么办?很多算法的padding往往是在后边的,但PKCS的padding则是在前面的,此为有意设计,有意的把第一个字节置0以确保m的值小于n。

这样,128字节(1024bits)-减去11字节正好是117字节,但对于RSA加密来讲,padding也是参与加密的,所以,依然按照1024bits去理解,但实际的明文只有117字节了。

关于PKCS#1 padding规范可参考:RFC2313 chapter 8.1,我们在把明文送给RSA加密器前,要确认这个值是不是大于n,也就是如果接近n位长,那么需要先padding再分段加密。除非我们是“定长定量自己可控可理解”的加密不需要padding。


 

RSA 原理:

选取两个不同的大素数p、q,并计算N=p*q
选取小素数d,并计算e,使d*e % (p-1)(q-1)=1

对于任意A<N:

若B=A**d % N
则A=B**e % N

可见d、e形成了非对称秘钥关系,加密者用公钥d加密,解密者可用私钥e解密,第
三者即使拦截了密文B、公钥d和N,在不知道p、q的前提下,无法推算出e,从而无
法获得明文A。当N取非常大的值时,将其因式分解成p、q是非常困难的。

RSA 密钥的选取和加解密过程都非常简洁,在算法上主要要实现四个问题:

1、如何处理大数运算
2、如何求解同余方程 XY % M = 1
3、如何快速进行模幂运算 ModExp
4、如何获取大素数


RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年首次公布,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。

RSA是目前最有影响力的非对称公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。

RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。

RSA加密

RSA的加密过程可以使用一个通式来表达

密文  =  明文^E   mod   N

也就是说RSA加密是对明文的E次方后除以N后求余数的过程。
从通式可知,只要知道E和N任何人都可以进行RSA加密了,所以说E、N是RSA加密的密钥,也就是说E和N的组合就是公钥,我们用(E,N)来表示公钥

公钥 = (E,N)

不过E和N不并不是随便什么数都可以的,它们都是经过严格的数学计算得出的,关于E和N拥有什么样的要求及其特性后面会讲到。E是加密(Encryption)的首字母,N是数字(Number)的首字母。

RSA解密

明文   =  密文^D    mod    N

也就是说对密文进行D次方后除以N的余数就是明文,这就是RSA解密过程。知道D和N就能进行解密密文了,所以D和N的组合就是私钥

私钥=(D,N)

从上述可以看出RSA的加密方式和解密方式是相同的,加密是求“E次方的mod N”; 解密是求“D次方的mod N” 此处D是解密(Decryption)的首字母;N是数字(Number)的首字母。
4. 生成密钥对

生成密钥对(E,D,N)的步骤:
4.1 求N
准备两个质数p,q。这两个数不能太小,太小则会容易破解,将p乘以q就是N

N = p * q

4.2 求L(L为中间过程的中间数)
L 是 p-1 和 q-1的最小公倍数,可用如下表达式表示

L=lcm(p-1,q-1)

4.3 求E
E必须满足两个条件:E是一个比1大比L小的数,E和L的最大公约数为1(互质)
用gcd(X,Y)来表示X,Y的最大公约数则E条件如下:

1 < E < L
gcd(E,L)=1

之所以需要E和L的最大公约数为1是为了保证一定存在解密时需要使用的数D。现在我们已经求出了E和N也就是说我们已经生成了密钥对中的公钥了。

4.4 求D
数D是由数E计算出来的。D、E和L之间必须满足以下关系:

1 < D < L
E*D mod L = 1

只要D满足上述2个条件,则通过E和N进行加密的密文就可以用D和N进行解密。
简单地说条件2是为了保证密文解密后的数据就是明文。 现在私钥自然也已经生成了,密钥对也就自然生成了。


首先是密钥对的生成:

    (1)选取两个大素(质数)数p和q(目前两个数的长度都接近512bit是安全的)

    (2)计算乘积n=p*q

    (3)计算Φ(n) = (p-1)(q-1),其中Φ(n)为n的欧拉函数(两素数乘积的欧拉函数等于两数分别减一后的乘积)

    (4)随机选取整数e(1<e<Φ(n))作为公钥,要求 e 与Φ(n)的最大公约数为1,即两者互素

    (5)用Euclid扩展算法(扩展欧几里得算法)计算私钥d,满足( d * e) mod   Φ(n)  ≡ 1,即d ≡ e^(-1) (mod Φ(n))。则e与n是公钥,d是私钥

    注意:e与n应公开,两个素数p和q不再需要,可销毁,但绝不可泄露。

 

在RSA算法过程中容易出现天文数字(像上文的0224^13),而这些天文数字会为我们编程的过程造成一定的麻烦,更可恶的是会影响速度!!为了避免这种情况,快速取模指数算法可以很有效地算出c≡m^e mod n的准确结果且避免过程中出现天文数字~~ 


25行代码实现完整的RSA算法(Python3.X版本)


  网络上很多关于RSA算法的原理介绍,但是翻来翻去就是没有一个靠谱、让人信服的算法代码实现,即使有代码介绍,也都是直接调用JDK或者Python代码包中的API实现,也有可能并没有把核心放在原理的实现上,而是字符串转数字啦、或者数字转字符串啦、或者即使有代码也都写得特别烂。无形中让人感觉RSA加密算法竟然这么高深,然后就看不下去了。看到了这样的代码我就特别生气,四个字:误人子弟。还有我发现对于“大整数的幂次乘方取模”竟然采用直接计算的幂次的值,再取模,类似于(2 ^ 1024) ^ (2 ^ 1024),这样的计算就直接去计算了,我不知道各位博主有没有运行他们的代码???知道这个数字有多大吗?这么说吧,把全宇宙中的物质都做成硬盘都放不下,更何况你的512M内存的电脑。所以我说他们的代码只可远观而不可亵玩已。
  于是我用了2天时间,没有去参考网上的代码重新开始把RSA算法的代码完全实现了一遍以后发现代码竟然这么少,基本上25行就全部搞定。为了方便整数的计算,我使用了Python语言。为什么用Python?因为Python在数值计算上比较直观,即使没有学习过python的人,也能一眼就看懂了代码。而Java语言需要用到BigInteger类,数值的计算都是用方法调用,所以使用起来比较麻烦。如果有同学对我得代码感兴趣的话,先二话不说,不管3X7=22,把代码粘贴进pydev中运行一遍,是驴是马拉出来溜溜。看不懂可以私信我,我就把代码具体讲讲,如果本文章没有人感兴趣,我就不做讲解了。
  RSA算法的步骤主要有以下几个步骤:
    1、选择 p、q两个超级大的质数 ,都是1024位,显得咱们的程序货真价实。
    2、令n = p * q。取 φ(n) =(p-1) * (q-1)。 计算与n互质的整数的个数。
    3、取 e ∈ 1 < e < φ(n) 且 e 与 n 互质,( n , e )作为公钥对,正式环境中取65537。可以打开任意一个被认证过的https证书,都可以看到。
    4、令 ed mod φ(n) = 1,计算d,( n , d ) 作为私钥对。 计算d可以利用扩展欧几里得的算法进行计算,非常简单,不超过5行代码就搞定。
    5、销毁 p、q。密文 = 明文 ^ e mod n , 明文 = 密文 ^ d mod n。利用蒙哥马利方法进行计算,也叫反复平方法,非常简单,不超过10行代码搞定。
    实测:秘钥长度在2048位的时候,我的thinkpad笔记本T440上面、python3.6.3环境的运行时间是0.038秒,1024位的时候是0.007秒。说明了RSA加密算法的算法复杂度应该是O(N^2),其中n是秘钥长度。不知道能不能优化到O(NlogN)。其实该程序还有很大的理论优化空间。
  代码主要涉及到三个Python可执行文件:计算最大公约数、大整数幂取模算法、公钥私钥生成及加解密。这三个文件构成了RSA算法的核心。
  这个时候很多同学就不干了,说为什么我在网上看到的很多RSA理论都特别多,都分很多个章节,在每个章节中,都有好多个屏幕才能显示完,这么多的理论,想想怎么也得上千行代码才能实现,怎么到了你这里25行就搞定了呢?北门大官人你不会是在糊弄我们把?其实真的没有,我是良心博主,绝对不会糊弄大家,你们看到的理论确实这么多,我也都看过了,我把这些理论用了zip,gzip,hafuman,tar,rar等很多的压缩算法一遍遍地进行压缩,才有了这个微缩版的rsa代码实现,代码虽少,五脏俱全,是你居家旅行,课程设计、忽悠小白、必备良药。其实里边的几乎每一行代码都能写一篇博客专门进行介绍。
  前方高能,我要开始装逼了。看不懂的童鞋请绕道,先去看看理论,具体内容如下:
  1. 计算最大公约数
  2. 超大整数的超大整数次幂取超大整数模算法(好拗口,哈哈,不拗口一点就显示不出这个算法的超级牛逼之处)
  3. 公钥私钥生成

1、计算最大公约数与扩展欧几里得算法

  ***gcd.py***文件,gcd方法用来计算两个整数的最大公约数。ext_gcd是扩展欧几里得方法的计算公式。

# -*- coding: utf-8 -*-

# 求两个数字的最大公约数(欧几里得算法)
def gcd(a, b):
    if b == 0:
        return a
    else:
        return gcd(b, a % b)

'''
扩展欧几里的算法
计算 ax + by = 1中的x与y的整数解(a与b互质)
'''
def ext_gcd(a, b):
    if b == 0:
        x1 = 1
        y1 = 0
        x = x1
        y = y1
        r = a
        return r, x, y
    else:
        r, x1, y1 = ext_gcd(b, a % b)
        x = y1
        y = x1 - a // b * y1
        return r, x, y

2、大整数幂取模算法

  ***exponentiation.py***文件,主要用于计算超大整数超大次幂然后对超大的整数取模。我在网上查询到这个算法叫做“蒙哥马利算法”。也叫反复平方法。非常简单,具体算法详情请参考这里蒙哥马利算法

# -*- coding: utf-8 -*-

'''
超大整数超大次幂然后对超大的整数取模
(base ^ exponent) mod n
'''
import time
def exp_mode(base, exponent, n):
    bin_array = bin(exponent)[2:][::-1]
    r = len(bin_array)
    base_array = []
    
    pre_base = base
    base_array.append(pre_base)
    
    for _ in range(r - 1):
        next_base = (pre_base * pre_base) % n 
        base_array.append(next_base)
        pre_base = next_base
        
    a_w_b = __multi(base_array, bin_array, n)
    return a_w_b % n

def __multi(array, bin_array, n):
    result = 1
    for index in range(len(array)):
        a = array[index]
        if not int(bin_array[index]):
            continue
        result *= a
        result = result % n # 加快连乘的速度
    return result

  有同学就不服了,说是我为啥不把这个幂次的数字计算出来,再取模。我说这样做,理论上是对的,但是实际上行不通。因为:一个2048位的数字的2048位次的幂,计算出来了以后,这个数字很可能把全宇宙的物质都做成硬盘也放不下。不懂的童鞋请私信我。所以需要用“蒙哥马利算法”进行优化。

3、公钥私钥生成

rsa.py生成公钥、私钥、并对信息加密解密
  咱是实在博主,绝对不会弄虚作假,在p和q的选择上,今年过年不选p、q,要选就选1024位。很多博客中在选取p和q的时候都是使用10000以内的质数,象征性地给大家演示一下,把问题说明白,结果在计算的时候就偷懒了,直接把幂次计算出来。这个明显偷懒了,没有把问题说明白。

# -*- coding: utf-8 -*-
from gcd import ext_gcd
from exponentiation import exp_mode
import time

# 生成公钥私钥,p、q为两个超大质数
def gen_key(p, q):
    n = p * q
    fy = (p - 1) * (q - 1)      # 计算与n互质的整数个数 欧拉函数
    e = 65537                    # 选取e   一般选取65537
    # generate d
    a = e
    b = fy
    r, x, y = ext_gcd(a, b)
    # 计算出的x不能是负数,如果是负数,说明p、q、e选取失败,不过可以把x加上fy,使x为正数,才能计算。
    if x < 0:
        x = x + fy
    d = x
    # 返回:   公钥     私钥
    return    (n, e), (n, d)
    
# 加密 m是被加密的信息 加密成为c
def encrypt(m, pubkey):
    n = pubkey[0]
    e = pubkey[1]
    
    c = exp_mode(m, e, n)
    return c

# 解密 c是密文,解密为明文m
def decrypt(c, selfkey):
    n = selfkey[0]
    d = selfkey[1]
    
    m = exp_mode(c, d, n)
    return m
    
    
if __name__ == "__main__":
    '''公钥私钥中用到的两个大质数p,q,都是1024位'''
    p = 106697219132480173106064317148705638676529121742557567770857687729397446898790451577487723991083173010242416863238099716044775658681981821407922722052778958942891831033512463262741053961681512908218003840408526915629689432111480588966800949428079015682624591636010678691927285321708935076221951173426894836169
    q = 144819424465842307806353672547344125290716753535239658417883828941232509622838692761917211806963011168822281666033695157426515864265527046213326145174398018859056439431422867957079149967592078894410082695714160599647180947207504108618794637872261572262805565517756922288320779308895819726074229154002310375209
    '''生成公钥私钥'''
    pubkey, selfkey = gen_key(p, q)
    '''需要被加密的信息转化成数字,长度小于秘钥n的长度,如果信息长度大于n的长度,那么分段进行加密,分段解密即可。'''
    m = 1356205320457610288745198967657644166379972189839804389074591563666634066646564410685955217825048626066190866536592405966964024022236587593447122392540038493893121248948780525117822889230574978651418075403357439692743398250207060920929117606033490559159560987768768324823011579283223392964454439904542675637683985296529882973798752471233683249209762843835985174607047556306705224118165162905676610067022517682197138138621344578050034245933990790845007906416093198845798901781830868021761765904777531676765131379495584915533823288125255520904108500256867069512326595285549579378834222350197662163243932424184772115345
    print("待加密信息-->%s" % m)
    '''信息加密,m被加密的信息,c是加密后的信息'''
    c = encrypt(m, pubkey)
    print("被加密后的密文-->%s" % c)
    '''信息解密'''
    d = decrypt(c, selfkey)
    print("被解密后的明文-->%s" % d)

  代码就是这么简单,RSA算法就是这么任性。代码去除掉没用的注释或者引用,总长度不会超过25行,有疑问的我们掰扯掰扯。
  实测:秘钥长度在2048位的时候,我的thinkpad笔记本T440上面、python3.6.3环境的运行时间是0.038秒,1024位的时候是0.007秒。说明了RSA加密算法的算法复杂度应该是O(N^2),其中n是秘钥长度。不知道能不能优化到O(NlogN)


填充方式(Padding)

RSA非对称加解密算法填充方式(Padding)

三类常见填充方式

RSA加密常用的填充模式有三种:RSA_PKCS1_PADDING, RSA_PKCS1_OAEP_PADDING, RSA_NO_PADDING。

与对称加密算法DES,AES一样,RSA算法也是一个块加密算法( block cipher algorithm),总是在一个固定长度的块上进行操作。但跟AES等不同的是,block length是跟key length有关的。

每次RSA加密的明文的长度是受RSA填充模式限制的,但是RSA每次加密的块长度就是key length。

填充方式输入输出条件
RSA_PKCS1_PADDING

必须 比 RSA 钥模长(modulus) 短至少11个字节,

也就是 RSA_size(rsa) – 11

和modulus一样长 
RSA_PKCS1_OAEP_PADDINGRSA_size(rsa) – 41和modulus一样长 
RSA_NO_PADDING可以和RSA钥模长一样长,如果输入的明文过长,必须切割, 然后填充和modulus一样长 

不同模式下的加密的最大数据长度

  • 在不同的padding模式下,使用相同长度的密钥可以加密的数据最大长度不同;
  • 在不同密钥长度下,使用相同的padding模式可以加密的数据最大长度也不同;

因此,脱离了密钥长度而讨论padding模式可以加密的最大长度是不严谨的。

常用的密钥长度有1024bits,2048bits等,理论上1024bits的密钥可以加密的数据最大长度为1024bits(即1024/8 = 128bytes)。2048bits的密钥可以加密的数据最大长度为2048bits(2048/8 = 256bytes),但是RSA在实际应用中不可能使用这种“教科书式的RSA”系统。实际应用中RSA经常与填充技术(padding)一起使用,可以增加RSA的安全性。填充技术实现的不好,RSA也不会安全。原因如下:

  1. RSA加密是确定的,即给定一个密钥,特定明文总会映射到特定的密文。攻击者可以根据密文中统计信息获取明文的一些信息。
  2. 填充技术如果比较弱,那么较小的明文和小型公开指数e将易于受到攻击。
  3. RSA有个特性叫做延展性,如果攻击者可以将一种密文转换为另一种密文,儿这种新密文会导致对明文的转换变得可知,这种特性并没有解密明文,而是以一种可预测的方式操纵了明文,比如:银行交易系统中,攻击者根据新密文,直接去修改原密文中金额的数据,可以在用户和接受方无法感知的情况下进行修改。
    所以,填充技术关系到RSA的安全性的高低。最优非对称填充(OAEP)就是一种优秀的填充方式,对应上述表格中RSA_PKCS1_OAEP_PADDING填充方式。

密钥文件格式 (pkcs#7, pkcs#8, pkcs#12, pem)

FormatNameDescription
PKCS #7Cryptographic Message Syntax StandardA PKCS #7 file can be used to store certificates, which is a SignedData structure without data (just the certificates). The file name extension is usually .p7b.p7c
PKCS #8Private-Key Information Syntax Standard.Used to carry private certificate keypairs (encrypted or unencrypted).
PKCS #12Personal Information Exchange Syntax Standard.Defines a file format commonly used to store private keys with accompanying public key certificates, protected with a password-based symmetric key. It is the successor to PFX from Microsoft.
DERDistinguished Encoding RulesA binary format for keys or certificates. It is a message transfer syntax specified by the ITU in X.690.
PEMPrivacy Enhanced MailBase64 encoded DER certificates or keys, with additional header and footer lines. 

The PEM private key format uses the header and footer lines: 
-----BEGIN RSA PRIVATE KEY----- 
-----END RSA PRIVATE KEY----- 

The PEM public key format uses the header and footer lines: 
-----BEGIN PUBLIC KEY----- 
-----END PUBLIC KEY----- 

The PEM certificate uses the header and footer lines: 
-----BEGIN CERTIFICATE----- 
-----END CERTIFICATE----- 

 

 

 

RSA Public Key file (PKCS#1)

 

The RSA Public key PEM file is specific for RSA keys.

It starts and ends with the tags:

  1. -----BEGIN RSA PUBLIC KEY-----

  2. BASE64 ENCODED DATA

  3. -----END RSA PUBLIC KEY-----

Within the base64 encoded data the following DER structure is present:

  1. RSAPublicKey ::= SEQUENCE {

  2. modulus INTEGER, -- n

  3. publicExponent INTEGER -- e

  4. }

Public Key file (PKCS#8)

Because RSA is not used exclusively inside X509 and SSL/TLS, a more generic key format is available in the form of PKCS#8, that identifies the type of public key and contains the relevant data.

It starts and ends with the tags:

  1. -----BEGIN PUBLIC KEY-----

  2. BASE64 ENCODED DATA

  3. -----END PUBLIC KEY-----

Within the base64 encoded data the following DER structure is present:

  1. PublicKeyInfo ::= SEQUENCE {

  2. algorithm AlgorithmIdentifier,

  3. PublicKey BIT STRING

  4. }

  5.  
  6. AlgorithmIdentifier ::= SEQUENCE {

  7. algorithm OBJECT IDENTIFIER,

  8. parameters ANY DEFINED BY algorithm OPTIONAL

  9. }

So for an RSA public key, the OID is 1.2.840.113549.1.1.1 and there is a RSAPublicKey as the PublicKey key data bitstring.

RSA Private Key file (PKCS#1)

The RSA private key PEM file is specific for RSA keys.

It starts and ends with the tags:

  1. -----BEGIN RSA PRIVATE KEY-----

  2. BASE64 ENCODED DATA

  3. -----END RSA PRIVATE KEY-----

Within the base64 encoded data the following DER structure is present:

  1. RSAPrivateKey ::= SEQUENCE {

  2. version Version,

  3. modulus INTEGER, -- n

  4. publicExponent INTEGER, -- e

  5. privateExponent INTEGER, -- d

  6. prime1 INTEGER, -- p

  7. prime2 INTEGER, -- q

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

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

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

  11. otherPrimeInfos OtherPrimeInfos OPTIONAL

  12. }

Private Key file (PKCS#8)

Because RSA is not used exclusively inside X509 and SSL/TLS, a more generic key format is available in the form of PKCS#8, that identifies the type of private key and contains the relevant data.

The unencrypted PKCS#8 encoded data starts and ends with the tags:

  1. -----BEGIN PRIVATE KEY-----

  2. BASE64 ENCODED DATA

  3. -----END PRIVATE KEY-----

Within the base64 encoded data the following DER structure is present:

  1. PrivateKeyInfo ::= SEQUENCE {

  2. version Version,

  3. algorithm AlgorithmIdentifier,

  4. PrivateKey BIT STRING

  5. }

  6.  
  7. AlgorithmIdentifier ::= SEQUENCE {

  8. algorithm OBJECT IDENTIFIER,

  9. parameters ANY DEFINED BY algorithm OPTIONAL

  10. }

So for an RSA private key, the OID is 1.2.840.113549.1.1.1 and there is a RSAPrivateKey as the PrivateKey key data bitstring.

The encrypted PKCS#8 encoded data start and ends with the tags:

  1. -----BEGIN ENCRYPTED PRIVATE KEY-----

  2. BASE64 ENCODED DATA

  3. -----END ENCRYPTED PRIVATE KEY-----

Within the base64 encoded data the following DER structure is present:

  1. EncryptedPrivateKeyInfo ::= SEQUENCE {

  2. encryptionAlgorithm EncryptionAlgorithmIdentifier,

  3. encryptedData EncryptedData

  4. }

  5.  
  6. EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier

  7.  
  8. EncryptedData ::= OCTET STRING

The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo (see above).


对接第三方接口时,对方有时只给了公钥私钥,这就需要自己来生成pem文件,
OpenSSL在线生成RSA 公私钥,同时把私钥在线生成合成PEM文件,公钥直接放到txt,改后缀为.pem,
对于公钥,新建txt,将公钥内容保存成.pem后缀即可
1、网址:
https://www.myssl.cn/tools/merge-pem-cert.html
选择pem在线合成,将私钥复制过去,注意格式,到处pem文件即可
2、私钥格式
-----BEGIN RSA PRIVATE KEY-----
中间填写私钥
-----END RSA PRIVATE KEY-----
3、公钥格式
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCFSwKKJQ2hO5uaDAdWayCx5DFzBeqpgvCPxQno8+IcAXI+fR9627XMnARJhMTiUxsHsRZDYEWpIajPt7j91cm1rtRgWDZqlc4IFiis04bpfVTxN/jkzJcXhuB+t0bAjtf/ydDKFGr1zDJC97cZGQTuRLU6npNfNnnjzlfHwt2caQIDAQAB
-----END PUBLIC KEY-----
4、生成公钥私钥的网站
http://tool.chacuo.net/cryptrsaprikey


编码 (也用于扩展名)

  • .DER = 扩展名DER用于二进制DER编码的证书。这些证书也可以用CER或者CRT作为扩展名。比较合适的说法是“我有一个DER编码的证书”,而不是“我有一个DER证书”。
  • .PEM = 扩展名PEM用于ASCII(Base64)编码的各种X.509 v3 证书。文件开始由一行"—– BEGIN …“开始。

der类型的不用在编码解码,直接就是二进制的数据可以直接使用;

pem类型的数据要根据base64编码解码后,得到的数据需要进行增加或裁剪特殊字符-、\n、\r、begin信息、end信息等。

 

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值