本文主要介绍如何使用 OpenSSL 来进行非对称加解密,使用的算法为 RSA,DSA 算法的使用方法类似;文中所使用到的软件版本:OpenSSL 1.1.1s、CentOS7.9.2009。

1、非对称加密算法

非对称加密算法需要两个密钥:公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥)。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。 非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将公钥公开,需要向甲方发送信息的其他角色(乙方)使用该密钥(甲方的公钥)对机密信息进行加密后再发送给甲方;甲方再用自己私钥对加密后的信息进行解密。甲方想要回复乙方时正好相反,使用乙方的公钥对数据进行加密,同理,乙方使用自己的私钥来进行解密。

另一方面,甲方可以使用自己的私钥对机密信息进行签名后再发送给乙方;乙方再用甲方的公钥对甲方发送回来的数据进行验签。

甲方只能用其私钥解密由其公钥加密后的任何信息。 非对称加密算法的保密性比较好,它消除了最终用户交换密钥的需要。

非对称密码体制的特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。这样安全性就大了很多。

非对称加密算法主要有:RSA、DSA、DH(Diffie-Hellman密钥交换算法) 和 ECC(椭圆曲线加密算法)。

2、用法2.1、生成 RSA 私钥

通过 openssl genrsa -help 命令查看用法:

shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl genrsa -helpUsage: genrsa [options]Valid options are: -help               Display this summary -3                  Use 3 for the E value -F4                 Use F4 (0x10001) for the E value -f4                 Use F4 (0x10001) for the E value -out outfile        Output the key to specified file -rand val           Load the file(s) into the random number generator -writerand outfile  Write random data to the specified file -passout val        Output file pass phrase source -*                  Encrypt the output with any supported cipher -engine val         Use engine, possibly a hardware device -primes +int        Specify number of primes

参数说明:

参数说明
-out outfile指定私钥输出文件
-*指定对私钥进行加密的对称加密算法

2.2、RSA 密钥操作

OpenSSL 中可以通过 openssl rsa 命令进行密钥的相关操作,包括从公钥提取私钥;通过 openssl rsa -help 命令查看用法:

shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl rsa -helpUsage: rsa [options]Valid options are: -help              Display this summary -inform format     Input format, one of DER PEM -outform format    Output format, one of DER PEM PVK -in val            Input file -out outfile       Output file -pubin             Expect a public key in input file -pubout            Output a public key -passout val       Output file pass phrase source -passin val        Input file pass phrase source -RSAPublicKey_in   Input is an RSAPublicKey -RSAPublicKey_out  Output is an RSAPublicKey -noout             Don't print key out -text              Print the key in text -modulus           Print the RSA key modulus -check             Verify key consistency -*                 Any supported cipher -pvk-strong        Enable 'Strong' PVK encoding level (default) -pvk-weak          Enable 'Weak' PVK encoding level -pvk-none          Don't enforce PVK encoding -engine val        Use engine, possibly a hardware device

参数说明:

参数说明
-inform format指定输入格式:DER,PEM
-outform format指定输出格式:DER,PEM,PVK
-in val指定密钥输入文件
-out outfile指定密钥输出文件
-pubout输出公钥
-noout不输出私钥信息
-text以文本格式打印私钥信息
-*对私钥进行加密的对称加密算法

2.3、RSA 加解操作

通过 openssl genrsa -help 命令查看用法:

shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl rsautl -helpUsage: rsautl [options]Valid options are: -help                    Display this summary -in infile               Input file -out outfile             Output file -inkey val               Input key -keyform PEM|DER|ENGINE  Private key format - default PEM -pubin                   Input is an RSA public -certin                  Input is a cert carrying an RSA public key -ssl                     Use SSL v2 padding -raw                     Use no padding -pkcs                    Use PKCS#1 v1.5 padding (default) -oaep                    Use PKCS#1 OAEP -sign                    Sign with private key -verify                  Verify with public key -asn1parse               Run output through asn1parse; useful with -verify -hexdump                 Hex dump output -x931                    Use ANSI X9.31 padding -rev                     Reverse the order of the input buffer -encrypt                 Encrypt with public key -decrypt                 Decrypt with private key -passin val              Input file pass phrase source -rand val                Load the file(s) into the random number generator -writerand outfile       Write random data to the specified file -engine val              Use engine, possibly a hardware device

参数说明:

参数说明
-in infile指定待加解密的文件
-out outfile指定输出文件
-inkey val指定密钥输入文件
-pubin输入密钥为公钥
-encrypt使用公钥加密
-decrypt使用私钥解密

3、具体使用3.1、生成私钥

shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl genrsa -out test.key 2048

生成一个 2048 位的私钥并保存到 test.key 文件中,文件内容如下:

-----BEGIN RSA PRIVATE KEY-----MIIEpAIBAAKCAQEAwyPpByJekg7LbQge8qORTPl72llYxlpMvXqCGO7VN2xuOdxwzXTQ9/B/3MOTmS7rOVU0IpcYTt6C0SMTzoKjRCR1FdM81YFecL8litilC85GIktpdWralQawIvMkZ4pv3sGth4PHiYqsTMlx984/TDOFXQ5vgT9VceXJ3KXZ8mVzyptwegIRN/OzBjY9KgrbIf7qgyuzjX1zXQMqgBl9LmUdWaETBYfDfSzuxBooeOYRXTYzvqm7GJzmnWGBskc3pytai1G7TopRNjuWBroIQqP11nUPyMVpGJ5U5WYGZg95rqw6zsNaAmauN6xqiEmvCENdvAixW6j8P36h0MIfNwIDAQABAoIBAFlsC00Jouyreuzr28K00dDEQs08REIg/ymVCikCyRIszhYVvltoPJphyzYPKYP4zDHpqYpwUuNRdAECYgEwPEDts/ncYvQz5GMmNL37qSZP0DPG+vyjiqbf+bcKVJReDAW4Gx0OdlHBClPlvCQijz8MHQEXrGE99JnNA0PpfIZmyLvbq3mj+npDvMWq3aDPy0swdbjMUDJnCdUJ3X/RajtPgZYSQuJDflfh6GbYk6fUSMP+FDF+SbH7MwNZe86A92poSFc8HzaGPwwU66UmFYr6EXAMKZ816IpYNIRhgLPKPLJ/3PboES0D8PuB+VUfAvxCEelC4UJCs6k5gHuPs4ECgYEA/am2cOhOBJyWCpmeFRTCQDp9aJbwwTpUtPKesnmFcLXgkqTqWH90YCY8OC9ola5kJXH1nPFRy3s3u/eXyvJbRZVmhTrTBXWt5fwcGfCAnT2P2HlJBXkafZhSaLNcSOurDFrz/8AOLLhLMv2XiS3kwjNcUm3EPL6115oTR8pRABMCgYEAxPAqoUemPS0LFVFjWKyPSYYGV21fSRQWFzzOsX+zMiRIjsAATT0Nynz9h/96HEQ78xOzfoda+kAzV6sAI8q5S5RLbLWFM7XmMPg2vb1ryliNHwz/FhR6tX1KKMfggffGn0XWYIGjyWkGFeU5HkILy3T6kC/yzk/+RschnpXIsM0CgYA4b6rkofrBsej8AMOYIx841QqT24lDJGw2Ogiu4rSaqAyH8+Mjv2+v+LHLOlkFfGBRqHIh8drl78stqd9+yr8d0yiVGcpbW5xOH/JMnyKuWUUIv6tMaW5IZTxoiQdOPgi3XgENdLhyoKoydRNi9PABeRXgTQWtEi05A9GoVk4BOwKBgQClBCCUVzcCV7XLvRCjgqPllXnG1AxdbYk9G2SN8lSylRh/FH6sOZZOrwC5beZhvQMGoOFsCfq/agAbW1uYogs1OyMgCdF9DNO/AJzNy+R//kbxV7B+TdasMDlthl2mSXmSh7Aj2TzmTSweOJ3trqW3a2NwYdzv5rNHlx+ihBtPmQKBgQCbFZQs2DSyULaoh9HJTh+xsU9MZkoTD8J0JAR026IjcltgFHGXI7QHCtHttO6POMYK+krOcsc5JPfiB6yfDjWnCqQ+bw/kMH5C/2CuhYC4aZRdmJJ4d0dsr0BsH5zhRzPRP2OyMuOUNK+YLwfHfTv2yEJM5KBPguKyfHrr4SjHfw==-----END RSA PRIVATE KEY-----

3.2、打印私钥

/home/mongo/soft/openssl-1.1.1s/bin/openssl rsa -in test.key -noout -text

3.3、根据私钥生成公钥

shell> /home/mongo/soft/openssl-1.1.1s/bin/openssl rsa -in test.key -pubout -out test.pem

生成的公钥保存到 test.pem 文件中,文件内容如下:

-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwyPpByJekg7LbQge8qORTPl72llYxlpMvXqCGO7VN2xuOdxwzXTQ9/B/3MOTmS7rOVU0IpcYTt6C0SMTzoKjRCR1FdM81YFecL8litilC85GIktpdWralQawIvMkZ4pv3sGth4PHiYqsTMlx984/TDOFXQ5vgT9VceXJ3KXZ8mVzyptwegIRN/OzBjY9KgrbIf7qgyuzjX1zXQMqgBl9LmUdWaETBYfDfSzuxBooeOYRXTYzvqm7GJzmnWGBskc3pytai1G7TopRNjuWBroIQqP11nUPyMVpGJ5U5WYGZg95rqw6zsNaAmauN6xqiEmvCENdvAixW6j8P36h0MIfNwIDAQAB-----END PUBLIC KEY-----

3.4、使用公钥加密

A、通过管道符指定输入

echo -n 123456 | /home/mongo/soft/openssl-1.1.1s/bin/openssl rsautl -encrypt -inkey test.pem -pubin -out test.encrypt

使用公钥加密 “123456”,结果保存到test.encrypt 文件中。

B、输入为文件

新建文件 a.txt,在文件中输入内容:

123456

使用 a.txt 作为输入:

/home/mongo/soft/openssl-1.1.1s/bin/openssl rsautl -encrypt -inkey test.pem -pubin -in a.txt -out test.encrypt

注:标准输入(结束方法:先输入回车,然后输入 ctrl+D)会把换行符也带入计算;使用文件输入时,也会在文件内容最后增加换行作为 OpenSSL 的计算输入;这会导致加密的结果用其他加密工具(如:Java)解密后会多出一个换行,所以使用 echo -n 来去除换行。

3.5、使用私钥解密

/home/mongo/soft/openssl-1.1.1s/bin/openssl rsautl -decrypt -inkey test.key -in test.encrypt

3.5、私钥转为 PKCS8 格式

OpenSSL 生成的私钥默认为 PKCS1 格式,如果需要使用 Java 来加解密,则需要转成 PKCS8 格式;使用openssl pkcs8 命令来进行转换:

/home/mongo/soft/openssl-1.1.1s/bin/openssl pkcs8 -topk8 -in test.key -nocrypt -out test_pkcs8.key

转换后的结果保存到test_pkcs8.key 中。