Openssl之enc、dgst和RSA

作者: 分类: CTF,Security 时间: 2016-11-11 评论: 1条评论

这次最主要探究的rsa相关,encdgst会稍微过一下。

说来这次初探Openssl也是一直想做的一件事,虽然之前已经把《图解密码学》看完了,但是也一直没有去实践一下。这次刚好有这个契机,就直接搞上了。

如果你也是刚刚接触Openssl,那么建议你在看这篇文章的同时,把官方文档打开放在一边,并且打开一个终端,实践出真知。

enc和dgst

enc

稍微过一下这些命令,首先看下官方文档(Openssl 1.0.1)中给出的enc支持的加密方式:

##### SYNOPSIS #####
openssl enc -ciphername [-in filename] [-out filename] [-pass arg] [-e] [-d] [-a/-base64] [-A] [-k password] [-kfile filename] [-K key] [-iv IV] [-S salt] [-salt] [-nosalt] [-z] [-md] [-p] [-P] [-bufsize number] [-nopad] [-debug] [-none] [-engine id]

##### SUPPORTED CIPHERS #####
 base64             Base 64
 bf-cbc             Blowfish in CBC mode
 bf                 Alias for bf-cbc
 bf-cfb             Blowfish in CFB mode
 bf-ecb             Blowfish in ECB mode
 bf-ofb             Blowfish in OFB mode

 cast-cbc           CAST in CBC mode
 cast               Alias for cast-cbc
 cast5-cbc          CAST5 in CBC mode
 cast5-cfb          CAST5 in CFB mode
 cast5-ecb          CAST5 in ECB mode
 cast5-ofb          CAST5 in OFB mode

 des-cbc            DES in CBC mode
 des                Alias for des-cbc
 des-cfb            DES in CBC mode
 des-ofb            DES in OFB mode
 des-ecb            DES in ECB mode

 des-ede-cbc        Two key triple DES EDE in CBC mode
 des-ede            Two key triple DES EDE in ECB mode
 des-ede-cfb        Two key triple DES EDE in CFB mode
 des-ede-ofb        Two key triple DES EDE in OFB mode

 des-ede3-cbc       Three key triple DES EDE in CBC mode
 des-ede3           Three key triple DES EDE in ECB mode
 des3               Alias for des-ede3-cbc
 des-ede3-cfb       Three key triple DES EDE CFB mode
 des-ede3-ofb       Three key triple DES EDE in OFB mode

 desx               DESX algorithm.

 gost89             GOST 28147-89 in CFB mode (provided by ccgost engine)
 gost89-cnt        `GOST 28147-89 in CNT mode (provided by ccgost engine) 

 idea-cbc           IDEA algorithm in CBC mode
 idea               same as idea-cbc
 idea-cfb           IDEA in CFB mode
 idea-ecb           IDEA in ECB mode
 idea-ofb           IDEA in OFB mode

 rc2-cbc            128 bit RC2 in CBC mode
 rc2                Alias for rc2-cbc
 rc2-cfb            128 bit RC2 in CFB mode
 rc2-ecb            128 bit RC2 in ECB mode
 rc2-ofb            128 bit RC2 in OFB mode
 rc2-64-cbc         64 bit RC2 in CBC mode
 rc2-40-cbc         40 bit RC2 in CBC mode

 rc4                128 bit RC4
 rc4-64             64 bit RC4
 rc4-40             40 bit RC4

 rc5-cbc            RC5 cipher in CBC mode
 rc5                Alias for rc5-cbc
 rc5-cfb            RC5 cipher in CFB mode
 rc5-ecb            RC5 cipher in ECB mode
 rc5-ofb            RC5 cipher in OFB mode

 aes-[128|192|256]-cbc  128/192/256 bit AES in CBC mode
 aes-[128|192|256]      Alias for aes-[128|192|256]-cbc
 aes-[128|192|256]-cfb  128/192/256 bit AES in 128 bit CFB mode
 aes-[128|192|256]-cfb1 128/192/256 bit AES in 1 bit CFB mode
 aes-[128|192|256]-cfb8 128/192/256 bit AES in 8 bit CFB mode
 aes-[128|192|256]-ecb  128/192/256 bit AES in ECB mode
 aes-[128|192|256]-ofb  128/192/256 bit AES in OFB mode

关于enc参数详解看这篇文章:openssl enc 加解密,解释的很清楚。

$ echo "iFurySt" > plaintext
$ openssl enc -S deadbeef -in plaintext -k 123 -aes128 -out cipher
$ xxd cipher
0000000: 5361 6c74 6564 5f5f dead beef 0000 0000  Salted__........
0000010: 360f e342 4320 a5ec a2d6 66c2 4556 1151  6..BC ....f.EV.Q
$ openssl enc -in cipher -d -aes128
enter aes-128-cbc decryption password:
iFurySt

大概是这么一个过程,差别基本就是各种选项的使用,有没有加盐,加密算法的选取等等。加盐了前面的标识都一样,对称加密格式相对来说比较类似。

dgst

Message Digest commands,摘要的命令相对来说就少很多了:

Message Digest commands (see the `dgst' command for more details)
md4               md5               mdc2              rmd160
sha               sha1

基本用法:

$ openssl dgst -md5 plaintext
MD5(plaintext)= 08266f83ef778110334aef20ae50df00
$ openssl dgst -sha1 plaintext
SHA1(plaintext)= eac18264a75791eaa59bfc88c0324d4970bf56d4

RSA

RSA简介

RSA主要用于数字签名、密钥交换和数据加密,但是加密速度比对称密码慢,故前两者使用的多。

RSA的精髓在于这句话“公钥加密,私钥签名”,私钥永远只能掌握在自己手上,公钥则可以随意发布。具体这边不想展开,自己去看书。

先看下下面一个RSA主要计算公式:

RSA

Openssl中RSA相关指令主要的有三个:

1. genrsa       //生成私钥
2. rsa          //处理rsa密钥的格式转换等问题
3. rsautl       //使用rsa密钥进行加解密、签名和验证等运算

genrsa生成密钥

下面先来看看genrsa主要参数

$ openssl genrsa -h
usage: genrsa [args] [numbits]
 -des            encrypt the generated key with DES in cbc mode
 -des3           encrypt the generated key with DES in ede cbc mode (168 bit key)
 -seed
                 encrypt PEM output with cbc seed
 -aes128, -aes192, -aes256
                 encrypt PEM output with cbc aes
 -camellia128, -camellia192, -camellia256
                 encrypt PEM output with cbc camellia
 -out file       output the key to 'file
 -passout arg    output file pass phrase source
 -f4             use F4 (0x10001) for the E value
 -3              use 3 for the E value
 -engine e       use engine e, possibly a hardware device.
 -rand file:file:...
                 load the file (or the files in the directory) into
                 the random number generator

参数很少,就是指定加密算法,还有输出文件,E的值等。

简单的生成密钥命令如下:

$ openssl genrsa -out priv.key 1024
Generating RSA private key, 1024 bit long modulus
....................................................++++++
............++++++
e is 65537 (0x10001)
$ cat priv.key
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDiuXsJoubcv2qnt56CPZks4HGO6/6nb52WmSgn39RFTJ5zonCl
llRm2on3iWsisuZj7GCqRAZbpjRqmm14X4PNwz6MvkoWCnLCUF0o7c4HEzKWfUKU
dKQ1SG0AJPSfqaCXIFzUkj4wKrlp6Hvjvvi6DsoSroh3qZhDQcoHkoDZiwIDAQAB
AoGAeXWOMWJgtR+inoji1Lj1JzJyA3Pv73j+/l+8QGhLinh6Zk4+dKbtPlCTGtY2
W9dlT2ChhHV+xnhqmjVyscrRi1Yehjb5hc+nO8IoTlSPlt5zFqgN7Lah4NQ/q4uN
ZaiwCBWtJIE2Kl/lpNDXktZc+bcERk5gEt91qwbrUM4pOnkCQQD/RRRPA3apMeSY
cg/m7XFXvF0wCyKzC2dFMI3XQ+YYn06BrKNWlom/WsdFK6W2zgAUseEwPIRMUatO
UMXkw7//AkEA419/wlJR4F38U1wXfyFs/nMpHQAcOrDsAl9ALfcQr4IIYDv2l3GU
KS01MfLNlsUHv7uYYUuZTVyRG3comXXmdQJBAIJUDo5YwliX9JIwihXo3JlivmEt
DkZDaDJXG9PwAqZHj5l9PteSfDmKa3rRUgYHHttyBfrOqu0cNU4Cx0aI+pkCQFoV
IvvtO20mL2sjaFfA+XrSS26m9Yg3QjoqXLYZVa4DWagu+aLEqAusUpAIf3WFeG15
OIULu6AP1ZnJGve542UCQQDE2r2xKCUSoabjpR+kH+PjVQ7kLlbYE1cIMCQc5kbV
2qbWMC3aNvhinUn98cyTY92pu6hOA+RxLVmc4k4nJnId
-----END RSA PRIVATE KEY-----

1024是密钥的长度(也就是N的长度)。

rsa转换密钥

接下来是rsa,可以进行格式转换或者生成公钥,参数如下:

$ openssl rsa -h
unknown option -h
rsa [options] <infile >outfile
where options are
 -inform arg     input format - one of DER NET PEM
 -outform arg    output format - one of DER NET PEM
 -in arg         input file
 -sgckey         Use IIS SGC key format
 -passin arg     input file pass phrase source
 -out arg        output file
 -passout arg    output file pass phrase source
 -des            encrypt PEM output with cbc des
 -des3           encrypt PEM output with ede cbc des using 168 bit key
 -seed           encrypt PEM output with cbc seed
 -aes128, -aes192, -aes256
                 encrypt PEM output with cbc aes
 -camellia128, -camellia192, -camellia256
                 encrypt PEM output with cbc camellia
 -text           print the key in text
 -noout          don't print key out
 -modulus        print the RSA key modulus
 -check          verify key consistency
 -pubin          expect a public key in input file
 -pubout         output a public key
 -engine e       use engine e, possibly a hardware device.

公钥的生成就是用rsa

$ openssl rsa -in priv.key -out pub.key -pubout
writing RSA key
$ ls
priv.key  pub.key
$ cat pub.key
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDiuXsJoubcv2qnt56CPZks4HGO
6/6nb52WmSgn39RFTJ5zonClllRm2on3iWsisuZj7GCqRAZbpjRqmm14X4PNwz6M
vkoWCnLCUF0o7c4HEzKWfUKUdKQ1SG0AJPSfqaCXIFzUkj4wKrlp6Hvjvvi6DsoS
roh3qZhDQcoHkoDZiwIDAQAB
-----END PUBLIC KEY-----

格式转换的是主要是-informoutform,有这些格式DER NET PEM(默认),关于这个格式,下面会说到。这边看下PEMDER

$ openssl rsa -in priv.key -out priv.der -outform der
writing RSA key

rsautl

上面两个指令主要是密钥的生成及管理的作用,rsautl则是真正用于密钥交换和数字签名。实质上就是使用RSA公钥或者私钥加密。

无论是使用公钥加密还是私钥加密,RSA每次能够加密的数据长度不能超过RSA密钥长度,并且根据具体的补齐方式不同输入的加密数据最大长度也不一样,而输出长度则总是跟RSA密钥长度相等。RSA不同的补齐方法对应的输入输出长度如下表(默认对齐方式为PKCS):

Padding

签名暂且不说了,看下加解密,具体如下:

$ echo "iFurySt" > plaintext
$ ls
plaintext  priv.key  pub.key
/* 加密:-encrypt指定为加密 -in要加密的文件 -inkey公钥或私钥(其实会抽取公钥部分,等价的)都行 -pubin指明使用公钥 -out输出文件 */
$ openssl rsautl -encrypt -in plaintext -inkey priv.key -out cipher1
$ openssl rsautl -encrypt -in plaintext -inkey pub.key -pubin -out cipher2
$ ls
cipher1  cipher2  plaintext  priv.key  pub.key
/* 解密:-decrypt指定为解密 */
$ openssl rsautl -decrypt -in cipher1 -inkey priv.key
iFurySt
$ openssl rsautl -decrypt -in cipher2 -inkey priv.key
iFurySt

RSA密钥文件格式

Openssl生成的密钥默认是PEM格式,私钥默认是PKCS#1,而用私钥生成的公钥默认是PKCS#8PKCS#8PKCS#1之间是可以相互转化的,具体的请看这篇文章,总结的很好:OpenSSL 操作筆記 - 檔案格式轉換

我们可以使用asn1parse命令读取私钥ASN.1结构(ASN.1相关知识可以看openssl ans.1编码规则分析及证书密钥编码方式

openssl asn1parse -in priv.key

我们找个私钥来看看,如下所示,这个是PKCS#1的格式:

$ openssl asn1parse -in priv.key
    0:d=0  hl=4 l= 603 cons: SEQUENCE
    4:d=1  hl=2 l=   1 prim: INTEGER           :00
    7:d=1  hl=3 l= 129 prim: INTEGER           :B0C422BDECC2567A4F06AB3C769E3D7ED80330F3F0F062DDE7FF2B37D8C3DC849AA6ED236C5FCB489220E8FCC68DD9C77674C2254A97D66520087CBBD5E9BF65D6BA521DC25E2E7EAB927E26FF7EEE988E153C937D3FA71548141EA6AD626292F44C6D7D23D61761DBCF9A27425BB25D4E0F80741C737E015F332369D19AB735
  139:d=1  hl=2 l=   3 prim: INTEGER           :010001
  144:d=1  hl=3 l= 128 prim: INTEGER           :0272F538446B7CDF3CF10EB64BBE6D83B0627AEF264B6E533CBFA04DA9C72CEAF9698EA78AFCD8C82C9E201C4073FEAC70CBB554E6EFAB9CC310DB098F3129E1AD68B0B6634F52169F9A08E7B6BA830BE4A02866BDF7BBE8605B95DEA42EB534510D382C723F09D23714768E94B60D41CD3DC7BD6D18EBCFF4A106B6B5870081
  275:d=1  hl=2 l=  65 prim: INTEGER           :E8F15788F32F2FB48C2147BC537115192AFA62F16753F561DAA878F73A57F7C63E7ACCDB662D6A1CE935B3D5FD1879A9889CE48CC0BC232FD7C4DCC12D0F5AC9
  342:d=1  hl=2 l=  65 prim: INTEGER           :C2434E4B7FC25634C86B6E4FB5938D4294B630C7C2E586D0AC95DFB361BE777AE03D8BDCD45BF879B2B11EF9831C52AE8E4E3E8622AAB1688606B540D24CC30D
  409:d=1  hl=2 l=  64 prim: INTEGER           :5A4C7C0F559DDC135422EE88FD9B9F7F231EEECDFFAD173938A70845663385942ED231A9772171BA055950FE49DF7C021138288CBB85F2E9EFED9B59B31AF9A9
  475:d=1  hl=2 l=  64 prim: INTEGER           :6BCF549D5BDAEB62C1B3B575B12CA121C94C4F481DA6AA2A170DDA274060A7085F7868AD76815025A200E052D2EB9E0B57D89EA46C8AD48850915A780DFE21E5
  541:d=1  hl=2 l=  64 prim: INTEGER           :15C0F747D7DFFF1CE5D6C6A3F16B48627A71ED58414149C653CDEF060074C27C39376EB80E5981CB8C117EF5E36913457610AABB3EED3C60A80E2671C4342660

PKCS#1中私钥文件和公钥文件格式定义如下:

//------------------------------
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
}
其中otherPrimeInfos 按顺序包含了其它素数r3, …, ru的信息。如果version是0 ,它应该被忽略;而如果version是1,它应该至少包含OtherPrimeInfo的一个实例。
OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
OtherPrimeInfo ::= SEQUENCE {
    prime INTEGER, -- ri
    exponent INTEGER, -- di
    coefficient INTEGER -- ti
}
OtherPrimeInfo的各域具有以下意义:
• prime 是n的一个素数因子ri ,其中i ≥ 3。
• exponent 是di = d mod (ri − 1)。
• coefficient 是CRT系数 ti = (r1 · r2 · … · ri–1)–1 mod ri。

//------------------------------

RSAPublicKey ::= SEQUENCE {
    modulus INTEGER, -- n
    publicExponent INTEGER -- e
}

格式中每种类型基本都有固定的大小,可以base64解码后xxd看一下十六进制慢慢切割分析,这边偷懒就不去分析了,这边这篇文章OPENSSL中RSA私钥文件(PEM格式)解析【一】有分析,可以看一下。

在Openssl里可以直接用以下命令自动把参数值提取出来:

$ openssl rsa -in priv.key -out priv.txt -text
writing RSA key
$ cat priv.txt
Private-Key: (1024 bit)
modulus:
    00:b0:c4:22:bd:ec:c2:56:7a:4f:06:ab:3c:76:9e:
    3d:7e:d8:03:30:f3:f0:f0:62:dd:e7:ff:2b:37:d8:
    c3:dc:84:9a:a6:ed:23:6c:5f:cb:48:92:20:e8:fc:
    c6:8d:d9:c7:76:74:c2:25:4a:97:d6:65:20:08:7c:
    bb:d5:e9:bf:65:d6:ba:52:1d:c2:5e:2e:7e:ab:92:
    7e:26:ff:7e:ee:98:8e:15:3c:93:7d:3f:a7:15:48:
    14:1e:a6:ad:62:62:92:f4:4c:6d:7d:23:d6:17:61:
    db:cf:9a:27:42:5b:b2:5d:4e:0f:80:74:1c:73:7e:
    01:5f:33:23:69:d1:9a:b7:35
publicExponent: 65537 (0x10001)
privateExponent:
    02:72:f5:38:44:6b:7c:df:3c:f1:0e:b6:4b:be:6d:
    83:b0:62:7a:ef:26:4b:6e:53:3c:bf:a0:4d:a9:c7:
    2c:ea:f9:69:8e:a7:8a:fc:d8:c8:2c:9e:20:1c:40:
    73:fe:ac:70:cb:b5:54:e6:ef:ab:9c:c3:10:db:09:
    8f:31:29:e1:ad:68:b0:b6:63:4f:52:16:9f:9a:08:
    e7:b6:ba:83:0b:e4:a0:28:66:bd:f7:bb:e8:60:5b:
    95:de:a4:2e:b5:34:51:0d:38:2c:72:3f:09:d2:37:
    14:76:8e:94:b6:0d:41:cd:3d:c7:bd:6d:18:eb:cf:
    f4:a1:06:b6:b5:87:00:81
prime1:
    00:e8:f1:57:88:f3:2f:2f:b4:8c:21:47:bc:53:71:
    15:19:2a:fa:62:f1:67:53:f5:61:da:a8:78:f7:3a:
    57:f7:c6:3e:7a:cc:db:66:2d:6a:1c:e9:35:b3:d5:
    fd:18:79:a9:88:9c:e4:8c:c0:bc:23:2f:d7:c4:dc:
    c1:2d:0f:5a:c9
prime2:
    00:c2:43:4e:4b:7f:c2:56:34:c8:6b:6e:4f:b5:93:
    8d:42:94:b6:30:c7:c2:e5:86:d0:ac:95:df:b3:61:
    be:77:7a:e0:3d:8b:dc:d4:5b:f8:79:b2:b1:1e:f9:
    83:1c:52:ae:8e:4e:3e:86:22:aa:b1:68:86:06:b5:
    40:d2:4c:c3:0d
exponent1:
    5a:4c:7c:0f:55:9d:dc:13:54:22:ee:88:fd:9b:9f:
    7f:23:1e:ee:cd:ff:ad:17:39:38:a7:08:45:66:33:
    85:94:2e:d2:31:a9:77:21:71:ba:05:59:50:fe:49:
    df:7c:02:11:38:28:8c:bb:85:f2:e9:ef:ed:9b:59:
    b3:1a:f9:a9
exponent2:
    6b:cf:54:9d:5b:da:eb:62:c1:b3:b5:75:b1:2c:a1:
    21:c9:4c:4f:48:1d:a6:aa:2a:17:0d:da:27:40:60:
    a7:08:5f:78:68:ad:76:81:50:25:a2:00:e0:52:d2:
    eb:9e:0b:57:d8:9e:a4:6c:8a:d4:88:50:91:5a:78:
    0d:fe:21:e5
coefficient:
    15:c0:f7:47:d7:df:ff:1c:e5:d6:c6:a3:f1:6b:48:
    62:7a:71:ed:58:41:41:49:c6:53:cd:ef:06:00:74:
    c2:7c:39:37:6e:b8:0e:59:81:cb:8c:11:7e:f5:e3:
    69:13:45:76:10:aa:bb:3e:ed:3c:60:a8:0e:26:71:
    c4:34:26:60
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCwxCK97MJWek8Gqzx2nj1+2AMw8/DwYt3n/ys32MPchJqm7SNs
X8tIkiDo/MaN2cd2dMIlSpfWZSAIfLvV6b9l1rpSHcJeLn6rkn4m/37umI4VPJN9
P6cVSBQepq1iYpL0TG19I9YXYdvPmidCW7JdTg+AdBxzfgFfMyNp0Zq3NQIDAQAB
AoGAAnL1OERrfN888Q62S75tg7Bieu8mS25TPL+gTanHLOr5aY6nivzYyCyeIBxA
c/6scMu1VObvq5zDENsJjzEp4a1osLZjT1IWn5oI57a6gwvkoChmvfe76GBbld6k
LrU0UQ04LHI/CdI3FHaOlLYNQc09x71tGOvP9KEGtrWHAIECQQDo8VeI8y8vtIwh
R7xTcRUZKvpi8WdT9WHaqHj3Olf3xj56zNtmLWoc6TWz1f0YeamInOSMwLwjL9fE
3MEtD1rJAkEAwkNOS3/CVjTIa25PtZONQpS2MMfC5YbQrJXfs2G+d3rgPYvc1Fv4
ebKxHvmDHFKujk4+hiKqsWiGBrVA0kzDDQJAWkx8D1Wd3BNUIu6I/ZuffyMe7s3/
rRc5OKcIRWYzhZQu0jGpdyFxugVZUP5J33wCETgojLuF8unv7ZtZsxr5qQJAa89U
nVva62LBs7V1sSyhIclMT0gdpqoqFw3aJ0BgpwhfeGitdoFQJaIA4FLS654LV9ie
pGyK1IhQkVp4Df4h5QJAFcD3R9ff/xzl1saj8WtIYnpx7VhBQUnGU83vBgB0wnw5
N264DlmBy4wRfvXjaRNFdhCquz7tPGCoDiZxxDQmYA==
-----END RSA PRIVATE KEY-----

公钥就简单了,主要就是NE,因为生成的公钥默认是PKCS#8的格式,下面我们看下PKCS#8中私钥文件和公钥文件格式定义:

//------------------------------
PrivateKeyInfo ::= SEQUENCE {  
    version                   Version,  
    privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,  
    privateKey                PrivateKey,  
    attributes           [0]  IMPLICIT Attributes OPTIONAL }
//------------------------------
RSAPublicKey ::= SEQUENCE  {  
    modulus INTEGER, -- n  
    publicExponentINTEGER -- e  
}

私钥的话要先转换下格式:

$ openssl pkcs8 -in priv.key -topk8 -nocrypt -out priv.pkcs8
$ openssl asn1parse -in priv.pkcs8
    0:d=0  hl=4 l= 629 cons: SEQUENCE
    4:d=1  hl=2 l=   1 prim: INTEGER           :00
    7:d=1  hl=2 l=  13 cons: SEQUENCE
    9:d=2  hl=2 l=   9 prim: OBJECT            :rsaEncryption
   20:d=2  hl=2 l=   0 prim: NULL
   22:d=1  hl=4 l= 607 prim: OCTET STRING      [HEX DUMP]:3082025B02010002818100B0C422BDECC2567A4F06AB3C769E3D7ED80330F3F0F062DDE7FF2B37D8C3DC849AA6ED236C5FCB489220E8FCC68DD9C77674C2254A97D66520087CBBD5E9BF65D6BA521DC25E2E7EAB927E26FF7EEE988E153C937D3FA71548141EA6AD626292F44C6D7D23D61761DBCF9A27425BB25D4E0F80741C737E015F332369D19AB73502030100010281800272F538446B7CDF3CF10EB64BBE6D83B0627AEF264B6E533CBFA04DA9C72CEAF9698EA78AFCD8C82C9E201C4073FEAC70CBB554E6EFAB9CC310DB098F3129E1AD68B0B6634F52169F9A08E7B6BA830BE4A02866BDF7BBE8605B95DEA42EB534510D382C723F09D23714768E94B60D41CD3DC7BD6D18EBCFF4A106B6B5870081024100E8F15788F32F2FB48C2147BC537115192AFA62F16753F561DAA878F73A57F7C63E7ACCDB662D6A1CE935B3D5FD1879A9889CE48CC0BC232FD7C4DCC12D0F5AC9024100C2434E4B7FC25634C86B6E4FB5938D4294B630C7C2E586D0AC95DFB361BE777AE03D8BDCD45BF879B2B11EF9831C52AE8E4E3E8622AAB1688606B540D24CC30D02405A4C7C0F559DDC135422EE88FD9B9F7F231EEECDFFAD173938A70845663385942ED231A9772171BA055950FE49DF7C021138288CBB85F2E9EFED9B59B31AF9A902406BCF549D5BDAEB62C1B3B575B12CA121C94C4F481DA6AA2A170DDA274060A7085F7868AD76815025A200E052D2EB9E0B57D89EA46C8AD48850915A780DFE21E5024015C0F747D7DFFF1CE5D6C6A3F16B48627A71ED58414149C653CDEF060074C27C39376EB80E5981CB8C117EF5E36913457610AABB3EED3C60A80E2671C4342660

ASN.1结构输出格式说明:

0:d=0  hl=4 l= 629 cons: SEQUENCE

0 表示节点在整个文件中的偏移长度
d=0 表示节点深度
hl=4 表示节点头字节长度
l=629 表示节点数据字节长度
cons 表示该节点为结构节点,表示包含子节点或者子结构数据
prim 表示该节点为原始节点,包含数据
SEQUENCE、OCTETSTRING等都是ASN.1中定义的数据类型,具体可以参考ASN.1格式说明。
最后一个节点OCTET STRING[HEX DUMP],就是加密后的私钥数据。

找个公钥来看看:

$ openssl asn1parse -in pub.key
0:d=0  hl=3 l= 159 cons: SEQUENCE
3:d=1  hl=2 l=  13 cons: SEQUENCE
5:d=2  hl=2 l=   9 prim: OBJECT            :rsaEncryption
16:d=2  hl=2 l=   0 prim: NULL
18:d=1  hl=3 l= 141 prim: BIT STRING

其中BIT STRING的内容就是PKCS#1格式的公钥数据,这边rsaEncryption是公钥的算法。我们可以用asn1parse解析出BIT STRING的内容:

$ openssl asn1parse -in pub.key -strparse 18
    0:d=0  hl=3 l= 137 cons: SEQUENCE
    3:d=1  hl=3 l= 129 prim: INTEGER           :B0C422BDECC2567A4F06AB3C769E3D7ED80330F3F0F062DDE7FF2B37D8C3DC849AA6ED236C5FCB489220E8FCC68DD9C77674C2254A97D66520087CBBD5E9BF65D6BA521DC25E2E7EAB927E26FF7EEE988E153C937D3FA71548141EA6AD626292F44C6D7D23D61761DBCF9A27425BB25D4E0F80741C737E015F332369D19AB735
  135:d=1  hl=2 l=   3 prim: INTEGER           :010001

E常常使用的是65537,也就是0x010001。

总结

这次初探Openssl也差不多了,关于证书以及进一步的探究留待以后吧。有时候就是要多想想有什么是自己想要学的,比如我现在想研究waf,Linux内核等等,但是迫于很多因素,并不可能马上去学习,但是因为有想法,等到某一天一个合适的机会到来就会开始展开。

下面以一道CTF题来收尾。

$ cat sexy_rsa.txt
I recovered some RSA parameters. Can you decrypt the message?

c = 293430917376708381243824815247228063605104303548720758108780880727974339086036691092136736806182713047603694090694712685069524383098129303183298249981051498714383399595430658107400768559066065231114145553134453396428041946588586604081230659780431638898871362957635105901091871385165354213544323931410599944377781013715195511539451275610913318909140275602013631077670399937733517949344579963174235423101450272762052806595645694091546721802246723616268373048438591
n = 1209143407476550975641959824312993703149920344437422193042293131572745298662696284279928622412441255652391493241414170537319784298367821654726781089600780498369402167443363862621886943970468819656731959468058528787895569936536904387979815183897568006750131879851263753496120098205966442010445601534305483783759226510120860633770814540166419495817666312474484061885435295870436055727722073738662516644186716532891328742452198364825809508602208516407566578212780807
e = 65537

给出一个文件,包含NE还有cipher。对于这个我们要做的只有是把N拿去分解质因素,CTF给出的N基本都是能分解的,我们去RSA大数分解网站直接在线分解,得到pq

1099610570827941329700237866432657027914359798062896153406865588143725813368448278118977438921370935678732434831141304899886705498243884638860011461262640420256594271701812607875254999146529955445651530660964259381322198377196122393

1099610570827941329700237866432657027914359798062896153406865588143725813368448278118977438921370935678732434831141304899886705498243884638860011461262640420256594271701812607875254999146529955445651530660964259381322198377196122399

rsatool.py生成私钥:

./rsatools.py -p num1 -q num2 -o priv.key

再进行解密即可得到明文,此处的cipher要以二进制写入文件

import binascii
c = 293430917376708381243824815247228063605104303548720758108780880727974339086036691092136736806182713047603694090694712685069524383098129303183298249981051498714383399595430658107400768559066065231114145553134453396428041946588586604081230659780431638898871362957635105901091871385165354213544323931410599944377781013715195511539451275610913318909140275602013631077670399937733517949344579963174235423101450272762052806595645694091546721802246723616268373048438591
open("cipher","w").write(binascii.unhexlify("%x"%c))

且这题经过尝试发现需要指定-raw对齐方式:

$ openssl rsautl -decrypt -in cipher -inkey priv.key -raw
ABCTF{i_h4ve_an_RSA_fetish_;)}

相关资料:

使用openssl命令剖析RSA私钥文件格式

OPENSSL中RSA私钥文件(PEM格式)解析

OpenSSL 操作筆記 - 檔案格式轉換

声明:文章基本原创,允许转载,但转载时必须以超链接的形式标明文章原始出处及作者信息。

仅有 1 条评论

  1. 阿满
    阿满

    RSA算法有个fai(n) = (p-1)(q-1)。lcm(p-1,q-1)不等于fai(n),图里面的lcm不应当是fai(n)吗?

    时间: 2017-05-26 at 11:48 回复
    1. 阿满
      阿满

      两种都对。
      φ(n)满足m^φ(n) ≡ 1 (mod n)。lcm满足m^lcm(p-1,q-1) ≡ 1 (mod n)。
      类似于这样的场景:两个互相咬合的齿轮,一个较大一个较小,周期分别为 p-1 和 q-1,要隔多久才会同时回到最初的状态?显然 r=(p−1)⋅(q−1)r=(p−1)⋅(q−1) 是一个周期,但更准确的周期是 p-1 和 q-1 的最小公倍数。

      时间: 2017-05-26 at 14:53 回复

添加新评论