RSA编码私钥获取RSA公钥原理解析

    本文目的在于在逆向破解过程中遇见一个RSA私钥字符串,以为仅仅含有私钥信息,无法获取公钥进行数据解密。但是经过后面的发现才知道自己理解错误。

先看java层的代码:

可以看出在这里私钥是一种叫PKCS8编码格式的,其实这里带入arg10编码串是能够导出公钥的。

但是刚开始很迷惑,私钥(d,n)对怎么可能能生成公钥(e,n)。为了搞清查看了一下公私钥的生成方式,网上找到如下步骤:

(1)选择一对不同的、足够大的素数p,q。
(2)计算n=pq。
(3)计算f(n)=(p-1)(q-1),同时对p, q严加保密,不让任何人知道。
(4)找一个与f(n)互质的数e,且1 (5)计算d,使得d*e≡1 mod f(n)。这个公式也可以表达为d ≡e-1 mod f(n)
这里要解释一下,≡是数论中表示同余的符号。公式中,≡符号的左边必须和符号右边同余,也就是两边模运算结果相同。显而易见,不管f(n)取什么值,符号右边1 mod f(n)的结果都等于1;符号的左边d与e的乘积做模运算后的结果也必须等于1。这就需要计算出d的值,让这个同余等式能够成立。
(6)公钥KU=(e,n),私钥KR=(d,n)。
(7)加密时,先将明文变换成0至n-1的一个整数M。若明文较长,可先分割成适当的组,然后再进行交换。设密文为C,则加密过程为:
(8)解密过程为:

从这个过程中可以看出:只道私钥(d,n),看似只要计算d mod f(n)就能得到唯一的e-1,从而获得公钥。虽然n=p*q,但是f(n)=(p-1)(q-1),无法通过n获取f(n)。如果只知道公钥对(e,n),也是需要f(n)。而只有n的情况下,唯一的做法就是对n进行质数分解,得到pq两个值,显然数学中对应大数的质数分解还没有好的方法。

经过上述分析发现,仅有私钥是不能获取公钥的。

那为什么上述java代码里面的私钥能够获取公钥呢,原因在于这种编码格式的数据中含有公钥。原因如下:

https://blog.csdn.net/zhymax/article/details/7683925#

这篇文章中给出了PKCS8编码格式的数据结构,我截图给大家看:

   0:d=0  hl=4 l= 710 cons: SEQUENCE
   4:d=1  hl=2 l=  64 cons: SEQUENCE
   6:d=2  hl=2 l=   9 prim:  OBJECT            :PBES2
  17:d=2  hl=2 l=  51 cons:  SEQUENCE
  19:d=3  hl=2 l=  27 cons:   SEQUENCE
  21:d=4  hl=2 l=   9 prim:    OBJECT            :PBKDF2
  32:d=4  hl=2 l=  14 cons:    SEQUENCE
  34:d=5  hl=2 l=   8 prim:     OCTET STRING      [HEX DUMP]:7A61B055165A89CA
  44:d=5  hl=2 l=   2 prim:     INTEGER           :0800
  48:d=3  hl=2 l=  20 cons:   SEQUENCE
  50:d=4  hl=2 l=   8 prim:    OBJECT            :des-ede3-cbc
  60:d=4  hl=2 l=   8 prim:    OCTET STRING      [HEX DUMP]:110E8A184EFEAB9C
  70:d=1  hl=4 l= 640 prim:  OCTET STRING      [HEX DUMP]:
C94F34F0CFF56B3E92D437C49559B1BD632BA2D8B22AF290B0E8EBB7F71C555115CED4DE87E3922A41436A20DA1DB01F1BD88EA3002E8AD4691C0B25F16AF4D196C2A96B99A1D49F704A21D3B81F8CC81C3F09412317B67F453151490D2573E1FD96D13BB55E7FCD4085ED0C4DD75EB1EFFC4ACE5431AFD708E6ECE5077BAB2B03965C6F2873C1DB5F475F861E9C04D61465C72A8A99DCF093190F746DD8959C0B0942E38A013B0FEC2D4A66F600EF75CE0326F3B4904C3128CB389204A1CC4F93EED7C8F2450603A42C6C16FB143FF4C9C01E714A43CC07B1F1B580A6C9DE4DC9B78CA0D5B874C75A0F56F6A55CFE4620F1AC639DCE4A8AF2BCBB69691DAF983BB26F6A6C859C371D1EBA7DA5C27FBDAC86C6529C48B32E3B89317FC7EBF03F9C105EAA1892437E9E789F0E2340979812A53CD1668EC07A45BBEAE088E7E27BB20B16C2D14280970BBF715D57005F194B97A1784E7BC563A0B84909A7EAB6C7E0BC6E2B467AA4009420D190617F93CD32FAEEE50003462DC8B26816040E891523E1375F339A3F05C43C9E90A4533BD4D3F75A2A33E60D91563542355D5ED1F46CF62594460694F459F0EC428BECE015F075895CFEB502EA22ECD9B53BF050B795074BE9A51194789F0B2970C21CCFE16284FB564F720C7899D5840362C48D248A50BAFA2720B0C1F7B417AD6EA183459BBB80679A85D96421C5AE3FA53A2135217F886759187123766914BB0169F6F9C3A36F1C46B6EB9300009A799D0F96C3E1FBE805F17A01FF2F5A9C941399E6130DBEE9825F4EB8937F2B8F0B3DE5F08644F3DC65028F2DE150D03D454AECFF9CAF26A00BB1B6D6D2C5255216E0A6769F14937618E31573811AAA464C3C42246A17DD70B1F77A87948FD5C7526D569BB8

因为本文目的在于为什么通过私钥可以获取公钥,所以在这里就不解析具体结构了。上述最后一个OCTEC STRING结构就是私钥数据。通过数据结构中指示的算法、密钥或者还有加密向量对该数据进行解密得到明文私钥。

该私钥数据可以按如下结构进行解析:

RSAPrivateKey ::= SEQUENCE {
versionVersion,
modulusINTEGER, -- n
publicExponentINTEGER, -- e
privateExponentINTEGER, -- d
prime1INTEGER, -- p
prime2INTEGER, -- q
exponent1INTEGER, -- d mod (p-1)
exponent2INTEGER, -- d mod (q-1)
coefficientINTEGER, -- (inverse of q) mod p
otherPrimeInfosOtherPrimeInfos OPTIONAL
}

其中,每一项的具体定义可以参考PKCS#1。

到这里我们发现一开始java代码中给的PKCS8的私钥其实是含有生成密钥对的p和q以及公私钥对。

所以,我们得出结论:

(1)在仅有公私钥对的情况下是难以获取另一个公私钥。

(2)如果私钥为PKCS编码格式的,则可以导出公私钥。

(3)通过私钥分析方法,您可以分析编码的公钥数据结构,一般编码的公钥数据结构仅有公钥情况,不然也起不到加密作用。

  这里有个在线工具可以从编码的私钥字符串中提取公钥:http://tool.chacuo.net/cryptgetpubkey

  若有误请大家指正,也参考了一些人的文章。

你可能感兴趣的:(加解密)