💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] 在非对称加密体系中,最常用的就是RSA密钥体系。如果想了解RSA的相关原理,可以自行google或查看文章末尾的引用。本文主要介绍openssl工具中关于RSA的一些命令。 **注意:RSA的私钥文件中包含了公钥的全部信息,但公钥文件没有私钥的信息** ## **生成私钥** 执行如下命令,生成一个1024位的rsa私钥 ``` $ openssl genrsa 1024 -out rsa.private ``` 以明文形式查看私钥的内容,其中每个字段的含义与RSA的原理有关。 ``` $ openssl rsa -in rsa.private -text Private-Key: (1024 bit) modulus: 00:c3:a2:ad:26:01:24:39:57:0a:02:56:6a:16:dc: 18:f1:36:a2:76:a6:4f:9e:b8:74:99:cb:9c:95:71: d8:da:73:d5:74:bd:ed:da:9b:17:db:4f:03:8a:a8: b0:4b:38:5e:dc:03:82:da:8c:be:da:2f:8b:93:62: 76:4f:23:c8:5b:c9:a2:73:3d:b4:af:90:96:bf:0c: 9c:0f:44:bc:4c:31:0d:d6:8f:04:9c:37:91:d1:3a: 5d:9f:b1:d9:e4:15:b5:ac:08:d9:e8:cc:1d:ce:a6: 97:31:57:31:ef:37:f4:b0:23:cc:ee:4e:f6:c1:18: e5:ae:19:3e:a6:7e:fd:94:f5 publicExponent: 65537 (0x10001) privateExponent: 3a:00:32:e1:7f:99:23:be:e0:62:cd:07:ea:fb:1a: 11:f9:a6:b5:12:9d:ac:6a:f7:76:d9:5c:f5:19:a9: b7:2a:7c:70:7e:16:d4:a7:02:ad:ac:81:5a:4c:a4: e7:c8:30:a7:7e:0a:ff:8c:96:d0:cd:23:ce:70:74: af:05:e6:d2:7b:04:46:17:3b:06:e5:0d:40:f7:87: d2:1a:d5:9b:3a:52:2a:d3:fc:9e:0c:1b:62:a0:63: 38:fe:b8:2f:4e:04:1f:74:03:56:73:c3:47:76:64: 94:8e:e8:20:79:b4:9b:10:8c:e1:a7:6e:11:9a:0f: 29:22:2e:a4:cb:97:ba:41 prime1: 00:e0:69:91:34:33:de:25:7b:dc:ea:09:95:7d:fd: 09:ab:e2:5b:de:e3:bb:52:43:1c:6f:39:c0:a1:e5: 80:ab:dc:67:d4:7b:d4:e5:46:b7:b0:c6:28:eb:1a: 25:a9:64:69:1e:f5:a3:e3:84:47:20:4f:0c:59:7b: 42:c6:21:b8:89 prime2: 00:df:2c:2a:cc:7c:63:b1:17:60:df:7f:9c:f9:00: 95:4a:26:cc:cb:b2:ea:51:e1:8c:fa:ea:9e:65:d1: 28:1e:fe:37:af:a0:87:62:38:19:12:97:5d:47:7b: 7b:37:b2:49:52:93:c0:19:64:d0:23:1b:df:86:44: ae:58:54:06:0d exponent1: 00:8a:50:66:9f:9f:2c:57:3c:0d:7f:ee:22:46:81: d4:19:2d:ad:e4:25:c6:89:c0:35:61:54:5e:27:2a: b5:f0:b7:2b:03:aa:c3:20:01:43:2c:60:26:4e:29: 52:77:22:1d:2c:68:c7:f7:6d:cb:0c:dd:cb:c5:c7: 13:f3:dc:4a:c9 exponent2: 66:fa:b9:71:0c:40:f0:39:aa:70:d7:30:f6:d1:67: 12:05:5f:60:eb:59:26:99:5e:75:76:07:cb:51:bd: 22:b8:09:b8:17:ea:00:cf:83:fa:49:30:38:c8:e8: ed:a5:6e:22:15:9d:81:da:3c:14:c7:4a:d8:69:1e: ce:11:4f:8d coefficient: 1a:ab:d3:fc:f3:dc:ef:15:c1:84:d1:ef:4f:85:2b: 61:54:a9:d6:9f:cb:2e:0c:f1:5c:e1:f9:dd:ad:da: 97:a3:75:90:6b:02:c7:8d:a5:49:60:7e:e5:45:f3: 11:99:e6:b3:6a:1c:bf:77:61:a1:0b:9a:25:25:f1: 27:ab:cf:f2 writing RSA key -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDDoq0mASQ5VwoCVmoW3BjxNqJ2pk+euHSZy5yVcdjac9V0ve3a mxfbTwOKqLBLOF7cA4LajL7aL4uTYnZPI8hbyaJzPbSvkJa/DJwPRLxMMQ3WjwSc N5HROl2fsdnkFbWsCNnozB3OppcxVzHvN/SwI8zuTvbBGOWuGT6mfv2U9QIDAQAB AoGAOgAy4X+ZI77gYs0H6vsaEfmmtRKdrGr3dtlc9Rmptyp8cH4W1KcCrayBWkyk 58gwp34K/4yW0M0jznB0rwXm0nsERhc7BuUNQPeH0hrVmzpSKtP8ngwbYqBjOP64 L04EH3QDVnPDR3ZklI7oIHm0mxCM4aduEZoPKSIupMuXukECQQDgaZE0M94le9zq CZV9/Qmr4lve47tSQxxvOcCh5YCr3GfUe9TlRrewxijrGiWpZGke9aPjhEcgTwxZ e0LGIbiJAkEA3ywqzHxjsRdg33+c+QCVSibMy7LqUeGM+uqeZdEoHv43r6CHYjgZ EpddR3t7N7JJUpPAGWTQIxvfhkSuWFQGDQJBAIpQZp+fLFc8DX/uIkaB1BktreQl xonANWFUXicqtfC3KwOqwyABQyxgJk4pUnciHSxox/dtywzdy8XHE/PcSskCQGb6 uXEMQPA5qnDXMPbRZxIFX2DrWSaZXnV2B8tRvSK4CbgX6gDPg/pJMDjI6O2lbiIV nYHaPBTHSthpHs4RT40CQBqr0/zz3O8VwYTR70+FK2FUqdafyy4M8Vzh+d2t2pej dZBrAseNpUlgfuVF8xGZ5rNqHL93YaELmiUl8Serz/I= -----END RSA PRIVATE KEY----- ``` ## **提取公钥** 执行以下命令从私钥中提取公钥 ``` $ openssl rsa -in rsa.private -out rsa.public -pubout ``` 然后以明文形式查看公钥内容,可以看到,公钥的信息在私钥里面都有 ``` $ openssl rsa -in rsa.public -text -pubin Public-Key: (1024 bit) Modulus: 00:c3:a2:ad:26:01:24:39:57:0a:02:56:6a:16:dc: 18:f1:36:a2:76:a6:4f:9e:b8:74:99:cb:9c:95:71: d8:da:73:d5:74:bd:ed:da:9b:17:db:4f:03:8a:a8: b0:4b:38:5e:dc:03:82:da:8c:be:da:2f:8b:93:62: 76:4f:23:c8:5b:c9:a2:73:3d:b4:af:90:96:bf:0c: 9c:0f:44:bc:4c:31:0d:d6:8f:04:9c:37:91:d1:3a: 5d:9f:b1:d9:e4:15:b5:ac:08:d9:e8:cc:1d:ce:a6: 97:31:57:31:ef:37:f4:b0:23:cc:ee:4e:f6:c1:18: e5:ae:19:3e:a6:7e:fd:94:f5 Exponent: 65537 (0x10001) writing RSA key -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDoq0mASQ5VwoCVmoW3BjxNqJ2 pk+euHSZy5yVcdjac9V0ve3amxfbTwOKqLBLOF7cA4LajL7aL4uTYnZPI8hbyaJz PbSvkJa/DJwPRLxMMQ3WjwScN5HROl2fsdnkFbWsCNnozB3OppcxVzHvN/SwI8zu TvbBGOWuGT6mfv2U9QIDAQAB -----END PUBLIC KEY----- ``` ## **加密与解密** #### **公钥加密私钥解密** 首先我们编辑一个文件original.txt,文件内容为`my name is peng shizhu` ``` $ echo "my name is peng shizhu" > original.txt ``` 然后,我们使用公钥进行加密 ``` $ openssl rsautl -encrypt -in original.txt -out encryptbypub.txt -inkey rsa.public -pubin ``` 查看加密后的内容,发现加密后内容明文查看不了 ``` $ cat encryptbypub.txt ѝ6]h`؍Փń¶]¾l_>ҟůXɺ{C§�MK牉tOºEݿ¬ ڛ¿`p翢 b ``` 没关系,我们用私钥进行解密,发现解密后的内容与原文一致 ``` $ openssl rsautl -decrypt -in encryptbypub.txt -inkey rsa.private my name is peng shizhu ``` 公钥加密的内容,公钥是没办法解密的,我们尝试一下用公钥来解密,结果报错 ``` $ openssl rsautl -decrypt -in encryptbypub.txt -inkey rsa.public unable to load Private Key ``` #### **私钥加密公钥解密** 首先,用私钥对原文进行加密;注意,用私钥加密的命令和公钥不一样,从命令看以为是签名,但实际是加密 ``` $ openssl rsautl -sign -in original.txt -out signbypri.txt -inkey rsa.private ``` 然后我们使用公钥解密,输出原文内容 ``` $ openssl rsautl -verify -in signbypri.txt -inkey rsa.public -pubin my name is peng shizhu ``` 当然,因为私钥中包含了公钥的内容,所以我们同样可以使用私钥文件解密。注意,是使用私钥文件解密,而不是使用私钥解密,实际上使用的还是私钥文件里的公钥 ``` $ openssl rsautl -verify -in signbypri.txt -inkey rsa.private my name is peng shizhu ``` ## **摘要** 一条信息的摘要(digest)就是指对这条信息使用hash函数计算其哈希值。常用的hash函数有md5、sha1、sha256等等。openssl dgst命令提供了摘要计算及加密的功能,在证书的签名过程中,就有对证书的内容进行摘要计算。 用md5算法计算原文的摘要 ``` $ openssl dgst -md5 original.txt -out digest.txt $ cat digest.txt MD5(original.txt)= f481fb15f33752d3267c3195b6757b90 ``` #### **私钥加密公钥解密** 用md5计算原文摘要,并用私钥对摘要进行签名(签名实际为加密) ``` $ openssl dgst -sign rsa.private -md5 -out signbypriwithmd5.txt original.txt ``` 然后,用公钥对密文进行验证(实际上公钥会先解密密文,然后对原文进行md5计算得到摘要,将解密结果与计算出的摘要进行比较) ``` $ openssl dgst -verify rsa.public -md5 -signature signbypriwithmd5.txt original.txt Verified OK ``` 当然,私钥文件中包含了公钥内容,也可以使用私钥文件进行验证 ``` $ openssl dgst -prverify rsa.private -md5 -signature signbypriwithmd5.txt original.txt Verified OK ``` #### **公钥加密私钥解密** 用md5计算出摘要并用公钥对摘要进行签名(签名实为加密) ``` $ openssl dgst -sign rsa.public -md5 -out signbypubwithmd5.txt original.txt ``` 然后,用私钥进行验证 ``` $ openssl dgst -prverify rsa.private -md5 -signature signbypubwithmd5.txt original.txt Verified OK ``` 我们尝试用公钥自已去验证,结果不行(为什么是行的?????为什么用私钥加密的内容与公钥加密后的一致,肯定是用私钥加密的命令有误,没有用真正的私钥加密) ``` $ openssl dgst -verify rsa.public -md5 -signature signbypubwithmd5.txt original.txt Verified OK ``` ## **命令汇总** ``` openssl genrsa 1024 -out rsa.private # 生成rsa私钥,1024位 openssl rsa -in rsa.private -out rsa.public -pubout # 从私钥中提取公钥 openssl rsa -in rsa.private -text # 以明文形式查看私钥内容 openssl rsa -in rsa.public -text -pubin # 以明文形式查看公钥内容 openssl rsautl -encrypt -in original.txt -out encryptbypub.txt -inkey rsa.public -pubin # 用公钥加密 openssl rsautl -decrypt -in encryptbypub.txt -inkey rsa.private # 用私钥解密 openssl rsautl -encrypt -in original.txt -out encryptbypri.txt -inkey rsa.private # 用私钥加密(实际上是用里面的公钥加密) openssl rsautl -sign -in original.txt -out signbypri.txt -inkey rsa.private # 用私钥签名(本质上是加密,且用的是私钥) openssl rsautl -verify -in signbypri.txt -inkey rsa.public -pubin # 用公钥验证(本质上是解密,输出的是original.txt的内容) openssl rsautl -verify -in signbypri.txt -inkey rsa.private # 用私钥验证(实际上是用里面的公钥解密) openssl dgst -md5 original.txt -out digest.txt # 用md5算法计算摘要 openssl dgst -sign rsa.private -md5 -out signbypriwithmd5.txt original.txt # 用md5计算出摘要并用私钥对摘要进行签名(签名实际为加密) openssl dgst -verify rsa.public -md5 -signature signbypriwithmd5.txt original.txt # 用公钥验证(先用公钥解密摘要得到,再用md5哈希原文,然后比较) openssl dgst -prverify rsa.private -md5 -signature signbypriwithmd5.txt original.txt # 用私钥验证签名文件(实际用的是公钥) openssl dgst -sign rsa.public -md5 -out signbypubwithmd5.txt original.txt # 用md5计算出摘要并用公钥对摘要进行签名(签名即加密) openssl dgst -prverify rsa.private -md5 -signature signbypubwithmd5.txt original.txt # 用私钥验证 ``` ## **参考** [1] http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html