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

本文目的在于在逆向破解过程中遇见一个RSA私钥字符串,以为仅仅含有私钥信息,无法获取公钥进行数据解密。但是经过后面的发现才知道自己理解错误。
【RSA编码私钥获取RSA公钥原理解析】先看java层的代码:
RSA编码私钥获取RSA公钥原理解析
文章图片

可以看出在这里私钥是一种叫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,则加密过程为:RSA编码私钥获取RSA公钥原理解析
文章图片

(8)解密过程为:RSA编码私钥获取RSA公钥原理解析
文章图片

从这个过程中可以看出:只道私钥(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=0hl=4 l= 710 cons: SEQUENCE 4:d=1hl=2 l=64 cons: SEQUENCE 6:d=2hl=2 l=9 prim:OBJECT:PBES2 17:d=2hl=2 l=51 cons:SEQUENCE 19:d=3hl=2 l=27 cons:SEQUENCE 21:d=4hl=2 l=9 prim:OBJECT:PBKDF2 32:d=4hl=2 l=14 cons:SEQUENCE 34:d=5hl=2 l=8 prim:OCTET STRING[HEX DUMP]:7A61B055165A89CA 44:d=5hl=2 l=2 prim:INTEGER:0800 48:d=3hl=2 l=20 cons:SEQUENCE 50:d=4hl=2 l=8 prim:OBJECT:des-ede3-cbc 60:d=4hl=2 l=8 prim:OCTET STRING[HEX DUMP]:110E8A184EFEAB9C 70:d=1hl=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
若有误请大家指正,也参考了一些人的文章。

    推荐阅读