pem file
Files in pem format are usually used by digital certificate authorities (Certificate Authorities, CA). The file format is mainly base64 encoded file, with a header and tail similar to -----BEGIN PUBLIC The head and tail tags of KEY-----
and -----END PUBLIC KEY-----
.
Generate public and private keys
In python, you can generate the desired public and private key files by installing the package from Crypto.PublicKey import RSA
public key
from Crypto.PublicKey import RSA from Crypto.Util.number import * p,q = getPrime(512),getPrime(512) n=p*q e = 0x10001 pub = RSA.construct((n,e)) with open('out.pem','wb') as f: f.write(pub.exportKey('PEM')) with open('out.pem','rb') as f: print(f.read().decode()) ''' -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCuRPouMRTcLWPBEUlhjCrZ6MNQ rSy29BrHjH4 + lGMykB23azPtT9fk7IsEFXoodm6tsPL8kheJ6cP + 0WPldlQOw/K3 c9LUGzeCCAhNJuBjUoeW32ruE2HS7RoIF6vkP36zLs167ZZMK7Fg0cqW6VNXoJHT zaKdqysBe + 3W1VHl6QIDAQAB -----END PUBLIC KEY----- '''
private key
from Crypto.PublicKey import RSA from Crypto.Util.number import * p,q = getPrime(512),getPrime(512) n=p*q e = 0x10001 d = inverse(e,(p - 1) * (q - 1)) pub = RSA.construct((n,e,d,p,q)) with open('out.pem','wb') as f: f.write(pub.exportKey('PEM')) with open('out.pem','rb') as f: print(f.read().decode()) ''' -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQCnHIvLP0IERPVRaED + 71dlCRBcm3be4jlHgqVqIIXyIvrzc8ZC IIbIDqlBybNgq32i6PVlzBCsWiiTfBYS6J24qCjYVTywKk + yieNshieNNohmvQRF bZOZITJiP99URkhtGWo3trQfoAZEQ7NfMoS1N3PDvPet1lMfFK81AyWt1wIDAQAB AoGAIq74DK0KZJxzVfwPUVoXh27EKJRTrZrCTKc + 8bHiWwkLkK + 8vEjH8Imqc28L fcrZ/o/fLsuVwk/MECA27KG + 6hiRPJDWZmFgCInCABuhd + xitSBciMSGrO5ITjoq YdgMsR5xJTI8vhXIJ1iCkkCz6fD6Di7s + 3n/ + Ti3iuK87jECQQDOY/pLyH0ppOk0 49pieQRshckQMXqsKhahEDZmWMu70JqDLF0U3aIfup1R87uogB8hJj8 + K5RQavG4 4l0W5ghTAkEAz0eTNEWTe2iJ/Dq + 8JKTN/MA/a8MiG7wvAkXqjx + B + Eow77IdoN8 D5ehD0x6ou73yaorTddidDAplNmvyq0D7QJAJbcPXhndBWclVozss2H59Prdqx/f kuZ + DCCyUDGZyVBta9sHh3CY18N6TCeF + 1yuU5hxpiLAj5F7apWy/SQ8EQJBAMtv AxGda6cGLc8o1PeF1AlobUONxy4sPAdAoUJKRqNzH7AmEdcHKv6eoctDE2XQRc9e PUwTpSRFlLnrgLXZYu0CQBKKT + oY4ssnwKDQqGPsh9MtPyilySL9sWJilk1cSXmQ Xm7gjDq5S/x4k1gJyQFXbUnxTfsbLWs6BljHHlKSRes= -----END RSA PRIVATE KEY----- '''
If you are generating a set of random public and private key files, you can directly use RSA.generate(bits)
, where the bits parameter is the number of binary digits n in the generated public key file, and bits>= 1024, the default is 1024.
from Crypto.PublicKey import RSA from Crypto.Util.number import * key = RSA.generate(1024) print(key.publickey) with open('out.pem','wb') as f: f.write(key.exportKey('PEM')) with open('out.pem','rb') as f: print(f.read().decode()) ''' <bound method RsaKey.public_key of RsaKey(n=999296751311461078180477909710497038031616773326009848008311170216375974714372715997193840351809823264702 494570010830052246263565720099012558413919666165649842425889135927893830873265111965854438342164723847702248102551539223759 44881215835774119177009570247468911673932973239275741131654695253944455708641727, e=65537, d=2750174078006190050902877736010 708428285892844056727745182401455911571367004254618319939377985781753408579358730488172518934301662131401473978032662779619 625147062667755009612068973236647371719389503654892610099054845380271499357725927311722309888896695722509220423031786624304 9867167880710514827901086931493, p=99591457194550534143487296557713128614607263968900011105367884525715911542775373257540676 18769136991544158484849077735057792084414015625760536769751415507, q=100339605369901225175807695028524561186419219459202557 59007869111269242067226468943041901092934902353013133963062909073461567977701122665256982872188799461, u=2111771661302217183 343493746406805348965531581492223651147849337466575464897027597797323383307376291792334461891498947953036261381547003770335 520720819326)> -----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQCOTfkFWAc5UsCT07Y4bU9jKfpT5pt + ScHFIk/39jsE8yDHSFAo pcQMlJ6GKRYfU7F/3xbY2udbvXBj9jJVLBmh3ORbZT06xwYDeqhvE2kJB + QfGk + J POqzjCkFiDorxMUzWEq4us8nXmkv6WsrJMGSQZ0SQ7c29N9M0/8K622JvwIDAQAB AoGAJyntaVuXLV8JcgW3piLrUNLKOpICZEi/Q9ZUJN2G069n64CK0wz//ihe0nR3 SqrZdGQ84PSp7LUfu9sTch5fdSQLH/OAQtVf/rwWuwulm8wS0njrU9xxQQWrwZoe L9W7DlBWf5 + PbmYdgyoLIwL3 + wskvxiWswlvVcSR7RkXGiUCQQC + J0pN + 1W2U3qe a8rhAwX7XMSXoblFuqfBfH/duLZvseEEjtuTcj0ISlJgts2aZT1J8yHnllUoiqAu WQPUK/rTAkEAv5T6OwPHj + 4J/4WzQgJTN89Xj9ihR45wpr8Rr6WPXUCgXTe82UFz ny68nIzALvKrLTf58yu8/E5wy2 + SejBJ5QJASNUnwsK3y8QhvTgwVwsfaW3Y5vNM 0YZy5stW9offaNzLAUHunIUvF1PQRbb + /Vo1pXN40wljyMmAHQB/VO8bfQJBAIGQ nVKAEdyzHavjngHMVL9vyEYOObSNDn6Wxb1GeJiWdl3UrjE35JwJHaG6Rtb5Yu7n 5nCgaeUwn3PV9vgP5EkCQQCWIiD5b8Qb5Mma8/iDNhchmRkosUug/iCBeqNh3nJc txZnUy1fjc0toXxJY3ZBzTl3TNsk8p8x4H9y/NXoDtvu -----END RSA PRIVATE KEY----- '''
There are n, e, d, p, q, u
6 parameters, among which $u=p^{-1} \bmod q$.
Encrypt or decrypt files using public and private keys
In python, encryption and decryption can be achieved by using the public and private key files and filling them with the PKCS1_OAEP algorithm, for example
from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_OAEP from Crypto.Util.number import * flag = b'This_is_a_message_qwer' ? key = RSA.generate(1024) pub = key.publickey().exportKey() public_key = RSA.importKey(pub) pk = PKCS1_OAEP.new(public_key) enc = pk.encrypt(flag) print(enc) ? priv = key.exportKey() priv_key = RSA.importKey(priv) sk = PKCS1_OAEP.new(priv_key) msg = sk.decrypt(enc) print(msg) b'\xd1/Ou\xae\xba]z\xc0\t\xc6\xd7\xc4f\x13\x96\x9a\xeb5\xdb8\x92\xc7\x19\x12y\x9c\x18\xf7A\x9d\xe9 \ & amp;=<\x16\x07\xefz\xad2-\x983\xec\x932\xcb\xf0\x87~\xdf\xc1\xd2\x9f\xd7@\H\x1f\x87#\xf3 \x84\xa0\xfc\xd9\xcfV$>\xd7Of\xe6G\x06\xcb\x91\xa1\xcc\x0c\xad\xc2\x9a\xad\xe46\x91x\xad\xa51\xbb\xfb\xc1E \x93~e%\xd1~\xf8l\x19n\x88\xff\xac^\xca\x8fs*}\xb9c0\xc0N\xf2\xfa\xa4\xd8\x18g' b'This_is_a_message_qwer'
Resolve public and private keys
openssl
openssl is an open source software package in the Linux system. Applications encrypt communication through openssl to avoid eavesdropping. The main library is written in C language. openssl also supports many encryption algorithms, such as RSA, DSA, ECDSA, ECDHE, Diffie–Hellman key exchange, etc. This article mainly introduces how openssl is used to encrypt and decrypt pem files in RSA.
Read public key pem
openssl rsa -pubin -text -modulus -in 1.pem ┌──(root?kali)-[/tmp] └─# openssl rsa -pubin -text -modulus -in 1.pem RSA Public-Key: (1024 bit) Modulus: 00:8f:36:54:4b:9c:ac:89:f9:76:b1:3c:16:8c:10: db:99:4c:e9:95:92:ab:03:e9:31:d3:41:6f:a3:52: da:fe:66:fc:9a:4e:22:37:98:73:b3:c2:97:e6:42: ee:9b:04:ae:2d:5d:d0:3d:6f:09:9f:e7:44:35:b0: 2f:3b:b2:41:8a:b1:3c:2b:d5:97:c1:8e:77:df:8b: d1:06:02:c3:35:42:d3:f0:fb:ec:a7:af:13:5c:1b: 96:97:92:15:7b:35:a9:b3:58:d7:ba:f0:d1:45:9f: c8:d5:05:59:e7:ff:4d:8a:97:93:29:a0:7e:50:ab: 6d:2e:e6:45:7e:74:b0:4b:3d Exponent: 65537 (0x10001) Modulus=8F36544B9CAC89F976B13C168C10DB994CE99592AB03E931D3416FA352DAFE66FC9A4E22379873B3C297E642EE9B04AE2D5DD03D6F099FE74435B02F3BB2418AB13C 2BD597C18E77DF8BD10602C33542D3F0FBECA7AF135C1B969792157B35A9B358D7BAF0D1459FC8D50559E7FF4D8A979329A07E50AB6D2EE6457E74B04B3D writing RSA key -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCPNlRLnKyJ + XaxPBaMENuZTOmV kqsD6THTQW + jUtr + ZvyaTiI3mHOzwpfmQu6bBK4tXdA9bwmf50Q1sC87skGKsTwr 1ZfBjnffi9EGAsM1QtPw + + ynrxNcG5aXkhV7NamzWNe68NFFn8jVBVnn/02Kl5Mp oH5Qq20u5kV + dLBLPQIDAQAB -----END PUBLIC KEY-----
Among them, Modulus
is the hexadecimal value of modulus n
, and Exponent
is the encryption exponent e
.
Read private key pem
openssl rsa -in 1.pem -text ┌──(root?kali)-[/tmp] └─# openssl rsa -in 1.pem -text RSA Private-Key: (1024 bit, 2 primes) modulus: 00:8f:36:54:4b:9c:ac:89:f9:76:b1:3c:16:8c:10: db:99:4c:e9:95:92:ab:03:e9:31:d3:41:6f:a3:52: da:fe:66:fc:9a:4e:22:37:98:73:b3:c2:97:e6:42: ee:9b:04:ae:2d:5d:d0:3d:6f:09:9f:e7:44:35:b0: 2f:3b:b2:41:8a:b1:3c:2b:d5:97:c1:8e:77:df:8b: d1:06:02:c3:35:42:d3:f0:fb:ec:a7:af:13:5c:1b: 96:97:92:15:7b:35:a9:b3:58:d7:ba:f0:d1:45:9f: c8:d5:05:59:e7:ff:4d:8a:97:93:29:a0:7e:50:ab: 6d:2e:e6:45:7e:74:b0:4b:3d publicExponent: 65537 (0x10001) privateExponent: 1b:5b:06:de:0c:96:de:a2:22:bc:77:1c:5d:73:e8: e6:8f:0c:fd:4f:af:50:07:6e:c7:8a:33:cf:70:47: b9:99:a5:7d:ba:18:0a:23:9a:52:47:84:e9:6c:76: 94:70:df:ee:75:81:8e:02:94:45:91:90:f3:6a:6c: 93:4c:18:fd:a2:75:d5:18:9a:81:1d:38:ec:85:c3: 33:f6:1e:69:0a:27:d5:ba:12:5d:1d:86:ac:4e:14: dc:e1:ad:f7:0b:64:ac:6a:3c:58:f7:c1:1c:5c:4f: d9:91:9a:05:c3:de:a0:2f:4c:43:28:da:33:9b:fe: 60:a5:31:83:2f:ce:d8:51 prime1: 00:bc:a4:41:8f:de:bc:c4:cc:c3:4b:ac:7e:65:da: f9:53:0b:53:d7:e9:f2:11:8b:fd:03:96:27:ca:f6: cb:02:ba:fd:60:51:56:78:64:7d:37:b5:b8:ee:92: 12:57:ce:5f:be:96:32:40:48:47:fb:ea:8f:75:bb: 60:c1:90:c1:e9 prime2: 00:c2:59:5e:53:6e:a6:17:33:ea:00:72:87:da:0b: 55:36:0f:cd:40:25:c6:e3:2c:b8:a3:4f:e5:13:9d: 80:b2:76:78:66:04:88:51:13:fa:3e:7e:fc:08:f7: 06:6b:3b:ce:09:bd:cc:46:91:e7:b7:74:8a:52:e4: f7:66:a9:36:35 exponent1: 4e:a6:3d:1f:7a:c2:41:5b:0d:e1:b3:1d:4f:e2:28: 29:53:83:b5:75:b8:93:50:46:41:04:8d:ba:b5:82: 96:b4:d7:87:1c:e2:6c:77:99:2d:6c:fa:99:9d:15: 40:be:ae:74:8b:b2:8f:d2:93:10:99:0f:0f:0a:fc: a0:37:76:61 exponent2: 22:2f:a6:2f:f6:de:b0:66:29:5b:3a:ca:3a:c8:93: 8c:96:ea:fb:c5:a9:5e:7c:97:5d:e2:c7:e0:d3:6b: b7:f8:ae:e5:03:17:17:6b:f4:30:da:15:6b:5e:48: 7a:c4:62:51:c4:59:12:70:c7:d9:b5:5e:3f:86:97: 1e:2f:d5:a1 coefficient: 00:83:55:17:ad:1a:fe:bb:ac:04:d5:f7:92:ee:1a: b4:37:a9:28:e2:e9:73:3f:14:b3:d0:2d:8f:56:28: d5:55:22:9d:56:27:de:18:67:e5:b4:96:42:ca:8f: b0:b9:60:fb:23:9f:ab:62:3b:19:92:2c:0c:6a:31: b9:ad:09:0b:3c writing RSA key -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQCPNlRLnKyJ + XaxPBaMENuZTOmVkqsD6THTQW + jUtr + ZvyaTiI3 mHOzwpfmQu6bBK4tXdA9bwmf50Q1sC87skGKsTwr1ZfBjnffi9EGAsM1QtPw + + yn rxNcG5aXkhV7NamzWNe68NFFn8jVBVnn/02Kl5MpoH5Qq20u5kV + dLBLPQIDAQAB AoGAG1sG3gyW3qIivHccXXPo5o8M/U + vUAdux4ozz3BHuZmlfboYCiOaUkeE6Wx2 lHDf7nWBjgKURZGQ82psk0wY/aJ11RiagR047IXDM/YeaQon1boSXR2GrE4U3OGt 9wtkrGo8WPfBHFxP2ZGaBcPeoC9MQyjaM5v + YKUxgy/O2FECQQC8pEGP3rzEzMNL rH5l2vlTC1PX6fIRi/0DlifK9ssCuv1gUVZ4ZH03tbjukhJXzl + + ljJASEf76o91 u2DBkMHpAkEAwlleU26mFzPqAHKH2gtVNg/NQCXG4yy4o0/lE52AsnZ4ZgSIURP6 Pn78CPcGazvOCb3MRpHnt3SKUuT3Zqk2NQJATqY9H3rCQVsN4bMdT + IoKVODtXW4 k1BGQQSNurWClrTXhxzibHeZLWz6mZ0VQL6udIuyj9KTEJkPDwr8oDd2YQJAIi + m L/besGYpWzrKOsiTjJbq + 8WpXnyXXeLH4NNrt/iu5QMXF2v0MNoVa15IesRiUcRZ EnDH2bVeP4aXHi/VoQJBAINVF60a/rusBNX3ku4atDepKOLpcz8Us9Atj1Yo1VUi nVYn3hhn5bSWQsqPsLlg + yOfq2I7GZIsDGoxua0JCzw= -----END RSA PRIVATE KEY-----
There are a total of 8 parameters, namely:
modulus
: modulus n
publicExponent
: encryption exponent e
privateExponent
: Decryption exponent d
prime1 & amp;2
: two large factors p and q of modulus n
exponent1 & amp;2
:dp and dq, d mod (p – 1) and d mod (q – 1)
coefficient
:$q^{-1} \bmod p$
Raw data reading
Read public key pem
For example, a pem public key file
-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXrGq02sFKE5Znv2GljNLThSWB P6N2NfV41vaADS/ZEZB6JPo0RLTg4UYZOGg5SLYQkr5IvO6thXQJ + xFduuOYl8oe p4BeLZLIwFnxZQIjSDe5GD/Id6wPLTDTGFB4y7aVK/D0v + y12uW44HrYAUeTCNU8 renYB8YQwZIwuO2qZwIDAQAB -----END PUBLIC KEY-----
Read the base64 encoding and convert it to hex to get
30819f300d06092a864886f70d010101050003818d0030818902818100d7ac6ab4dac14a139667bf61a58cd2d38525813fa37635f578d6f6800d2fd9119 07a24fa3444b4e0e1461938683948b61092be48bceead857409fb115dbae39897ca1ea7805e2d92c8c059f16502234837b9183fc877ac0f2d30d3185078cbb6952bf 0f4bfecb5dae5b8e07ad801479308d53cade9d807c610c19230b8edaa670203010001
in
Content | Analysis |
---|---|
3081 | Tag header, 81 means followed by 1bytes, 82 means followed by 2bytes means length |
9f | followed by 0xdf (159) bytes content |
9f | td> |
300d06092a864886f70d010101050003 | Fixed sequence (the specific content is unknown) |
81 | Followed by 1bytes, if it is 82, it means followed by 2bytes indicating the length |
8d | Followed by the content of 0x8d (141) bytes |
0030 | Fixed sequence |
81 | followed by 1bytes, 82 means Followed by 2 bytes to indicate the length |
89 | Followed by the content of 0x89 (137) bytes |
0281 | 81 means followed by 1bytes, 82 means followed by 2bytes means the length |
81 | The modulus n length behind is 0x81bytes, but 1bytes is 00, so the generated modulo binary digits are 1024 |
00d7-67 | The hexadecimal number of modulus n Form |
0203010001 | 02 followed by the length 03 of the encryption index e is the content 010001 |
Read private key pem
Reading the private key is similar to the public key, but the content of the private key will be more than the public key. Compared with the public key, the private key also has p, q, dp, dq, qinvp
.
In the test example, after generating a 1024-bit RSA object, read out each value in the variable.
from Crypto.PublicKey import RSA key = RSA.generate(1024) with open('1.pem','wb') as f: f.write(b'n = ' + str(hex(key.n)[2:]).encode() + b'\ ') f.write(b'e = ' + str(hex(key.e)[2:]).encode() + b'\ ') f.write(b'p = ' + str(hex(key.p)[2:]).encode() + b'\ ') f.write(b'q = ' + str(hex(key.q)[2:]).encode() + b'\ ') f.write(b'd = ' + str(hex(key.d)[2:]).encode() + b'\ ') f.write(b'dp = ' + str(hex((key.d) % ((key.p) - 1))[2:]).encode() + b'\ ') f.write(b'dq = ' + str(hex((key.d) % ((key.q) - 1))[2:]).encode() + b'\ ') f.write(b'p_q = ' + str(hex(pow(key.p,-1,key.q))[2:]).encode() + b'\ ') f.write(b'q_p = ' + str(hex(pow(key.q, -1, key.p))[2:]).encode() + b'\ ') f.write(key.exportKey('PEM')) ? with open('1.pem','rb') as f: print(f.read().decode())
For example, a private key file
-----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQCw/aHmn + xs4OCJbVu1U0JhR/M4h42TYeVyR02wdtV + Dwt + CrE7 JlZyKBCM + jOXx + tgoxZ6e/U + voP9iU4Fpdmyi/HE8U5ZZ6YH8Bzx8Qh8vM3QM8XU W4NGfg6N9VG7uVdwioOBbZ9AoOBYHjMdxoZ8O5AxO3Lp0rzkfQTUe9CQFwIDAQAB AoGAE + puYeOj + HpzebNXCvfT89tjSHykVy3AYlQYr18n1df + jI/KcqP1PUI53os2 7ADggQ7I9D5nkchhVNGy + Fq5vLgdTRYZ859iT1h9i + bTwt7Uq2OfJR/NRkVcvaSv 7UKHmF3AyzNOpSf2NunvYUSJ5n92jUuXdXkvqmeS3/FOWA0CQQDJbCjac + mVzCzZ U84s + 7JXviTHPoN9GXZY3vr1tIBogwyftCa1 + pVIYu7WTwwHzcKe9KU4GPbLCTYU 45FJ0ejjAkEA4PK + h3cB65Oahwmxza1w7tugGNTXcLhMpJ8PCO65pG0wRIpp3doC TRLKdUUAcVromiiU8m/Mt8jwyhVxFMpGPQJAN6/uj47yapbbY253FxqzUOzh8DAJ XGHYxXNIgPvZcIuixtigxzkzYqLvk1KhadrqTtYmg57rRHEUgav09CrTrwJANTc3 + 7QbsC9rDycr + Qxe + yLZ7QXtMa1n9EnstKBFKrDqCkz0XpeEk9cuLi/0utxWyqFv Gyt3ssLGtAf + iHyRwQJAIWcJAM/jTFTMXNUrYK0fa0MMpNMrwnlDb6uyMn/4Q41g f3RB/34 + gFrCRZEhMtasgaOkoHYP3VZQvqkXzyaycg== -----END RSA PRIVATE KEY-----
Read base64 and convert to hex (after manual typesetting and line wrapping)
3082025b02010002818100 b0fda1e69fec6ce0e0896d5bb553426147f338878d9361e572474db076d57e0f0b7e0ab13b26567228108cfa3397c7eb60a3167a7bf53ebe83fd894e05a5d9b28b f1c4f14e5967a607f01cf1f1087cbccdd033c5d45b83467e0e8df551bbb957708a83816d9f40a0e0581e331dc6867c3b90313b72e9d2bce47d04d47bd09017 0203010001 028180 13ea6e61e3a3f87a7379b3570af7d3f3db63487ca4572dc0625418af5f27d5d7fe8c8fca72a3f53d4239de8b36ec00e0810ec8f43e6791c86154d1b2f85 ab9bcb81d4d1619f39f624f587d8be6d3c2ded4ab639f251fcd46455cbda4afed4287985dc0cb334ea527f636e9ef614489e67f768d4b9775792faa6792dff14e580d 024100 c96c28da73e995cc2cd953ce2cfbb257be24c73e837d197658defaf5b48068830c9fb426b5fa954862eed64f0c07cdc29ef4a53818f6cb093614e39149d1e8e 3 024100 e0f2be877701eb939a8709b1cdad70eedba018d4d770b84ca49f0f08eeb9a46d30448a69ddda024d12ca754500715ae89a2894f26fccb7c8f0ca157114ca463d 0240 37afee8f8ef26a96db636e77171ab350ece1f030095c61d8c5734880fbd9708ba2c6d8a0c7393362a2ef9352a169daea4ed626839eeb44711481abf4f42ad3af 0240 353737fbb41bb02f6b0f272bf90c5efb22d9ed05ed31ad67f449ecb4a0452ab0ea0a4cf45e978493d72e2e2ff4badc56caa16f1b2b77b2c2c6b407fe887c91c1 0240 21670900cfe34c54cc5cd52b60ad1f6b430ca4d32bc279436fabb2327ff8438d607f7441ff7e3e805ac245912132d6ac81a3a4a0760fdd5650bea917cf26b272</ pre> <p>The parsing process is as follows</p> <table><thead><tr><th>Content</th><th>Analysis</th></tr></thead><tbody><tr><td>3082</td><td> Tag header, 81 means followed by 1bytes, 82 means followed by 2bytes indicating the length. </td></tr><tr><td>025e</td><td> followed by the content of 0x25e (606) bytes. </td></tr><tr><td>02010002</td><td>Fixed sequence</td></tr><tr><td>81</td><td>81 means followed by 1bytes, 82 means followed by 2bytes means the length. </td></tr><tr><td>81</td><td>The length of the modulus n following is 0x81bytes, but 1bytes is 00, so the generated modulus binary digits are 1024</td></tr><tr><td>b0fd-9017</td><td>Hexadecimal modulus n</td></tr><tr><td>0203010001</td><td> 02 followed by the length of the encryption index e 03 is the content 010001</td></tr><tr><td>028180</td><td>81 means followed by 1bytes of length information, 80 means followed by 0x80 (128 )bytes length information</td></tr><tr><td>13ea-580d</td><td>Hexadecimal of private key index d</td></tr><tr><td >024100</td><td>Start sequence</td></tr><tr><td>c96c-e8e3</td><td>Hexadecimal of p</td></tr><tr><td>024100</td><td>Start sequence</td></tr><tr><td>e0f2-463d</td><td>Hexadecimal of q</td></tr><tr><td>0240</td><td>Start sequence</td></tr><tr><td>37af-d3af</td><td>Hexadecimal of dp</td></tr><tr><td>0240</td><td>Start sequence</td></tr><tr><td>3537-91c1</td><td>dq Hexadecimal</td></tr><tr><td>0240</td><td>Start sequence</td></tr><tr><td>2167-b272</td><td>q inv p</td></tr></tbody></table> <p>It can be roughly distinguished by 0x02:</p> <pre>for i in k.split('02'): print('02', i)
Example 1 2022ACTF impossible RSA
appendix
from Crypto.Util.number import * from Crypto.PublicKey import RSA ? e=65537 flag = b'ACTF{...}' ? while True: p = getPrime(1024) q = inverse(e, p) if not isPrime(q): continue n=p*q public = RSA.construct((n, e)) with open("public.pem", "wb") as file: file.write(public.exportKey('PEM')) with open("flag", "wb") as file: file.write(long_to_bytes(pow(bytes_to_long(flag), e, n))) break
The public key in this question is read in the form of a file. The code for reading the public key is
from Crypto.PublicKey import RSA with open(r'public.pem', "r") as f: key = f.read() rsakey = RSA.importKey(key) n = rsakey.n e = rsakey.e
Back to this question, the question gives the relationship between p, q, e
$q\equiv e^{-1} \bmod p$, and writing it as an equation gives $eq=1 + kp$, It can be seen that the size of k is similar to e. You can try to blast k and then combine the two sets of equations $n=p\times q$ to solve pq.
Simultaneous simplification of the two equations yields $kp^{2} + p-en=0$. You only need to determine whether its discriminant can be raised to a whole power. The complete answer is
from Crypto.Util.number import * import gmpy2 from Crypto.PublicKey import RSA from tqdm import tqdm with open(r'public.pem', "r") as f: key = f.read() rsakey = RSA.importKey(key) n = rsakey.n e = rsakey.e with open('flag','rb') as f: c = f.read() c = bytes_to_long(c) print(c) ? for k in tqdm(range(1,1 << 16)): root = gmpy2.iroot(1 + 4 * k * n * e,2) if root[1] == True: p = (1 + root[0]) // (2 * k) assert n % p == 0 q = n // p phi = (p - 1) * (q - 1) d = gmpy2.invert(e,phi) m = pow(c,d,n) print(long_to_bytes(m)) break
Example 2 2022 Blue Hat Cup Preliminary Round corrupted_key
This question mainly tests the reading and understanding of the private key file pem. The attachment is as follows
from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_OAEP from secret import flag ? key = RSA.generate(1024) open("flag.enc",'wb').write(PKCS1_OAEP.new(key.publickey()).encrypt(flag)) open('priv.pem','wb').write(key.exportKey('PEM'))
An ordinary attachment, the key lies in the private key
-----BEGIN RSA PRIVATE KEY----- MIICXgIBAAKBgQDXFSUGqpzsBeUzXWtG9UkUB8MZn9UQkfH2Aw03YrngP0nJ3NwH UFTgzBSLl0tBhUvZO07haiqHbuYgBegO + Aa3qjtksb + bH6dz41PQzbn/l4Pd1fXm dJmtEPNh6TjQC4KmpMQqBTXF52cheY6GtFzUuNA7DX51wr6HZqHoQ73GQQIDAQAB ? ? ? ? ? ? ? ? yQvOzxy6szWFheigQdGxAkEA4wFss2CcHWQ8FnQ5w7k4uIH0I38khg07HLhaYm1c zUcmlk4PgnDWxN + ev + vMU45O5eGntzaO3lHsaukX9461mA== -----END RSA PRIVATE KEY-----
It can be seen that there are a lot of missing parts in the private key file. First, read the original data and convert the base64 encoding into hex.
First paragraph: 3082025e02010002818100d7152506aa9cec05e5335d6b46f5491407c3199fd51091f1f6030d3762b9e03f49c9dcdc075054e0cc148b974b41854bd93b4 ee16a2a876ee62005e80ef806b7aa3b64b1bf9b1fa773e353d0cdb9ff9783ddd5f5e67499ad10f361e938d00b82a6a4c42a0535c5e76721798e86b45cd4b8d03b0 d7e75c2be8766a1e843bdc6410203010001 Second paragraph: c90bcecf1cbab3358585e8a041d1b1024100e3016cb3609c1d643c167439c3b938b881f4237f24860d3b1cb85a626d5ccd4726964e0f8270d6c4df9ebfebcc538 e4ee5e1a7b7368ede51ec6ae917f78eb598
Data can be extracted from the first paragraph
n = 0xd7152506aa9cec05e5335d6b46f5491407c3199fd51091f1f6030d3762b9e03f49c9dcdc075054e0cc148b974b41854bd93b4ee16a2a876ee62005 e80ef806b7aa3b64b1bf9b1fa773e353d0cdb9ff9783ddd5f5e67499ad10f361e938d00b82a6a4c42a0535c5e76721798e86b45cd4b8d03b0d7e75c2be8766a1e 843bdc641 e = 0x10001
Data can be extracted from the second paragraph
_dq = 0xc90bcecf1cbab3358585e8a041d1b1 qinvp = 0xe3016cb3609c1d643c167439c3b938b881f4237f24860d3b1cb85a626d5ccd4726964e0f8270d6c4df9ebfebcc538e4ee5e1a7b7368ede51ec6ae917f 78eb598
The question gives a hint to establish a system of equations and use coppersmith to recover dq. The modulus n is 1024 bits. The last 120 bits of dq are known, and 392 bits are missing. If the equation can be constructed, the missing 392 bits can be successfully recovered through coppersmith attack. Write the known equations into equations and list them
Exploding k, dq low position is known, and the construction equation can be solved
A problem is found here. When constructing, dq must be written as dq = (2 ** 120 * x) + _dq
but cannot be written as dq = (x << 120) + _dq
, because x is unknown, implementing multiplication through shift operations may cause problems.
from Crypto.Util.number import * import gmpy2 from tqdm import tqdm from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_OAEP n = 0xd7152506aa9cec05e5335d6b46f5491407c3199fd51091f1f6030d3762b9e03f49c9dcdc075054e0cc148b974b41854bd93b4ee16a2a876ee62005e80 ef806b7aa3b64b1bf9b1fa773e353d0cdb9ff9783ddd5f5e67499ad10f361e938d00b82a6a4c42a0535c5e76721798e86b45cd4b8d03b0d7e75c2be8766a1e843 bdc641 e = 0x10001 _dq = 0xc90bcecf1cbab3358585e8a041d1b1 t = 0xe3016cb3609c1d643c167439c3b938b881f4237f24860d3b1cb85a626d5ccd4726964e0f8270d6c4df9ebfebcc538e4ee5e1a7b7368ede51ec6ae917f78eb 598 with open('flag.enc','rb') as f: c = f.read() PR.<x> = PolynomialRing(Zmod(n)) dq = (2 ** 120 * x) + _dq for k in tqdm(range(65537,55000,-1)): f = t * (e * dq - 1) ** 2 + k * (2 * t - 1) * (e * dq - 1) + t * k * k - k * k f = f.monic() root = f.small_roots(X=2^392,beta=0.4) if len(root) > 0: print(int(root[0]) * 2 ** 120 + _dq) break #dq = 112632691003218434183403090335840577682460469531153250208964919437937591942495586973340951316842793046572250641566960 57310019203890620314290203835007881649 #k = 59199
After obtaining dq and coefficient k, directly calculate the flag, but it should be noted here that the original question is encrypted and decrypted through the PKCS1_OAEP algorithm. After obtaining the private key, it must be decrypted in the original way.
from Crypto.Util.number import * from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_OAEP import base64 import gmpy2 with open("flag.enc","rb")as f: c = f.read() dq = 112632691003218434183403090335840577682460469531153250208964919437937591942495586973340951316842793046572250641566960 57310019203890620314290203835007881649 k=59199 n = 0xd7152506aa9cec05e5335d6b46f5491407c3199fd51091f1f6030d3762b9e03f49c9dcdc075054e0cc148b974b41854bd93b4ee16a2a876ee62005e80 ef806b7aa3b64b1bf9b1fa773e353d0cdb9ff9783ddd5f5e67499ad10f361e938d00b82a6a4c42a0535c5e76721798e86b45cd4b8d03b0d7e75c2be8766a1e843 bdc641 e = 0x10001 q = int((e * dq - 1) // k + 1) assert n % q == 0 p = int(n // q) phi = (p - 1) * (q - 1) d = int(gmpy2.invert(e,phi)) key = RSA.construct((n,e,d,p,q)) flag = PKCS1_OAEP.new(key) flag = flag.decrypt(c) print(flag)
2023 Yangcheng Cup XOR is implemented throughout
wp:
x = "C0ngr4tulati0n5_y0u_fou^d_m3" import base64 import gmpy2 from Crypto.Util.number import * a = [b'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALmtMy + 2uH1ZtbIL', b'SuiAukFthyQRH5mp7UmLyzZQkdg9zEP9/5tgffikQ7ytx5kHySHnazgAO1sOzmYE', b'N4Axlev6uafiP8B1Eij97v5VkYJ1I9e3mtBNheTbXKoT8op + ASQ1fQaF4A8UzLuW', b'eZeZI8JTH/SH + bolAK3kiZXDFdkTAgMBAAECgYEAl067LaC7Cvs2A5cMPhfYsESv', b'IgcKN1CwW4Sd3u8dSphhgu7TgyzIuvwxbuo2g1BC6WwKhaI6vGN + csfw6nh98GEn', b'/p3D0huNroAYvf/DRRB9UnHdttX7wB + Mv3P0RBDWHgBiCDVvHFuFUV78cIs0tnbn', b'jxjU07aPV2XRC3AfA2ECQQDqWUNPVg3i6vTyHCL7EGkbeUheYpAAfcKCQrxjc5 + 5', b'X6A + XtgHAA1JHwykPlCpHUOmlA85DJF1ejuoImzlgRLJAkEAytTCnQF + MN2r1gaA', b'UETZyj5qMYT7Th8zKEVVVJjDawLnuX4usJ2FyRnjCkk86U75QSJhw5mMc0QnG25u', b'Gz3 + + w=='] k = '' for i in range(len(a)): k + = hex(bytes_to_long(base64.b64decode(a[i])))[2:] for i in k.split('02'): print('02', i) n = 0xb9ad332fb6b87d59b5b20b4ae880ba416d8724111f99a9ed498bcb365091d83dcc43fdff9b607df8a443bcadc79907c921e76b38003b5b0ece660437803195 ebfab9a7e23fc0751228fdeefe5591827523d7b79ad04d85e4db5caa13f28a7e0124357d0685e00f14ccbb9679979923c2531ff487f9ba2500ade48995c315d913 e = 0x10001 p = 0xea59434f560de2eaf4f21c22fb10691b79485e6290007dc28242bc63739fb95fa03e5ed807000d491f0ca43e50a91d43a6940f390c91757a3ba8226ce5811 2c9 q = n//p d = gmpy2.invert(e,(p-1)*(q-1)) c = 91817924748361493215143897386603397612753451291462468066632608541316135642691873237492166541761504834463859351830616117 238028454453831120079998631107520871612398404926417683282285787231775479511469825932022611941912754602165499500350038397852 503264709127650106856760043956604644700201911063515109074933378818 m = pow(c,d,n) x = b'C0ngr4tulati0n5_y0u_fou^d_m3' print(long_to_bytes(m^bytes_to_long(x))) # print(k)
?Reference link
[CTF-RSA] RSA key generation and reading - Bilibili
https://zh.m.wikipedia.org/zh-cn/OpenSSL
Analysis of RSA private key file (PEM format) in OPENSSL_openssl pem format_PTYX's blog-CSDN blog