OpenSSL和Java产生不同的SHA256 RSA签名

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenSSL和Java产生不同的SHA256 RSA签名相关的知识,希望对你有一定的参考价值。

我用OpenSSL创建了一个RSA密钥对:

openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:4096
openssl rsa -pubout -in private_key.pem -out public_key.pem

这些是关键:

-----BEGIN PRIVATE KEY-----
MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQC7ZRktot/dOrNX
nyc8u1qtQM7Pb+OOLupSkqsVKeBaT1J/Yru9XF2EqlUo9aBSsjZLw1Q7TP8Ocj2s
Boj09otqgb9fjo/OPybhvr+z1FdmwRSShnZ5aGvNdM3eVklr98DrY+anYLPGE8GM
H3WL4tFKFtu2HK5E8NLLAuZx3SoNRnFJ2MZV4irf/vkdSOVRo9+u6f2Hj/0Swftq
SRfkF2gXJUUG0cesrFSPqYyFH5qbH6dDkwTAH27WcFt+X/YNkkzyC/wVtI/b0Ng1
Adjiqa84kxHADoeyPBmRNlCio3T4bx3hDYkSEhpRJQGMqEQdPTdU3lQBixCked3m
aOWW1+SGcqCvNnDAQsgdPa8PaQimYbefwQPDDT3fdKev/Vsip5/9B605QPONaRfO
IUg/Kfh/TL722t4ccFHZfXBKBF/JapMy0aY7e8U5CtkIu0Uh9Y2ZEHTaOMMxXCOK
UuO2rL4ki2MlnwC+zaduolKPPm8pI2tbVv2I9vtT3hSQOMrDFBeCtCVuv0lbu8Em
t+VhtPYvqbUvKlsoC0IzRhdnPhUjkJhZh6pnwxFBgkzpry+3mNQgTLAmHx86xROE
MqI7haMTXyakEKDEjM87Wl0fM8BqxxOILJ/1dp5iNAj7sn3F1EPhjwZHhswzlQQI
r68NPNvuGhYr0ch7ufezybKOlbKGJwIDAQABAoICAHKHiWng350gITfuJ1bw0qyM
rVkOcy8U8VViGnmmzF2lmTANsdw7tVQ9niqYZFHmZVTMnpBXsJKts4+NtuqwO+ju
P34xbSaKZkMWB6fqoThFzUL4NzRgY3KAbsnyRpFcLGYw+mlVqsnmjSYMnBTQnUUA
z2tv//pWjR5SOXFh0C+o29hcSmt2/OlFtg713GGXHECU9cSCdhOexv/giF95Br8O
oi9Wywh3kn7zCtTZye4A3INqOT8Kdv1MUj7ce080GR7dwEWrwzh/XYSYCmwNdO/I
wtJ0ju6Z2K5tWb7s07J6hvJjCWEn+zmYumey914/aa/O6dy/l35OlRYbCia08A9H
6udkJIOJrB/LX+GRFibHOEROLFGc58IDA0Pfty6BnQ19oPy2yFOVcN9IgnAzlYCk
8B/uwT234E3Eyp0sJ64okuo4w12G3myRzz9Lnt0KruC9pYCO0tFW1kgxO9OVdYbM
Tc1v8uU9Ho6/ajVDjXJGftXb1o2nHWKzS4rew2nOxdIOn83p8TO2Paheasf2x9D/
wP/rOua46TRuwIaIp3RS9E0PGACoRCBKUgydtf8TJL9ns92AYK4Yk2wsyGou5hmj
ImNv9C0KLHDmJSIu7EFhGh16teLA2885HpU1ayPeIRYkyl5Q8I4Js3zhYx36EYdb
BZEQR+NZliLMZ9DjcYDxAoIBAQDhm8qyQnLEjHCMGAOazBbRvfLMdBOLJ0mmueRp
sb5RGB5k+84wROjg8Dmhv5BkG13EXwbzaL2vwfCLl3ABOt4daPETQjaQBxwBDjR0
IZTGH5iqkn9s1giz9Yr+0iAl39+1PfcsiAupax2o88KerJxC8BkMlXasiNCaef4N
GEA4+JxKGO1TJV5xkHXXzSvl1HxBZbZn9Bgq/UnLNzyTpC8bkxEPXecc8orBr4kp
MOgHhU731CYMtMs1OegnBxjr40pYfBEKkXL7iXtnfhoNDetYdmYrfd5vCzHh1FzS
BXubutHwJL341i98oQyVCuMLKCfu8+h7IJ09WmYMRRNjmqGFAoIBAQDUo34YJEh3
4dqJLE3fmOq+6CdLz/IfvefJul1VCEOYqJ/x0K7AUr7GvGruwiL3yEShnaJE13mD
GkKE6PvRVlKLx+a7jjnaS2RTfGmtUrcxOEQ+1NRIHV/REvfT+QOroxiO4/Choz71
h11ZFNWCdRaFls2x5+Bm4d1J4OnR7BtGs+CsBX9Gy4j4bEr/FdsRNQEQvGH96e6a
kLsNp11eDTe65l/T7nlpgxFQtmMLDAkynUzcbM7rtV196z60VZ3OF7ojl+70eSdE
YzhOqfGuxEoYA5HswvOQxL82pa6PrkNjAaBIoe+kVohBINfYu8QNbY/qPiRDvnVj
8nJy0tpXpYK7AoIBAHiW41NA/UNdpdLcCyE0sYXOt/bcnI2mpFF/zz1HimiiMazc
gyt9ydRh0wxH7o/zqL0L5hU5CRrm2QJkIbQmmQ6zRxh6LdvyUN+njhX81R7JSLrz
rzSneuNl/bOS8SgNb+/afUHKPiGCZcom8QILVULaPylgwpwaTRYk2sx5B+rrx+47
QK9OrBqbksGUo0AnwXrbORJ7gGeKF2WN0s0/1wYwJ9BE6wGoCs7YWsIvp/ZNJRaG
yQfFo1CB8TrbKlD7noOJXTp+4CzfIZ0B5D7SD9erAZWBo+FK5JDHCA4ibB2jUA/C
M+DL63n8Q1NvDEisYBvzN3KIzkM7DIzGZ0S4JFkCggEAZd289ovLO8MzEivrUobL
TpGg4azI7XPoqrdhJu9CksuVdB7o2LHLOyHgiGjwn4uNdW8y4Y/oYmoeG9YRbQPR
n60wWAGWrYEYmvYrGiFaKXYvG3qSB8oqsNpJZ38PxxXnGe0Qxh6SdsVWbuqQLmMx
WuYXvHa9BgyGGnJpEWvu1TwvEbnAc4XmJDyc4P7zZ5bg38efmiiLafiT48Kd9ASZ
AiyDE+BWwblMfkIhyJUHgvvgamil6D2GgGBGNdYeNzEetxZ+Hxg7O4Pc4bKAWZ0n
ccGkEqyCSoQ2plNRAPwWxENvKdyKFUxvEeROA0JQda5bF3iVnu6LBkqLkX55oytj
KQKCAQEA2mm6ZBf63is/N0Z/fVYkeUE4K2MD1AVOUisNzXvkxDiw7RxrsQO9KA/9
AudcftN1STNoCSmDilm/4L4YTbKUrl0wj2kFZGOm8bH/RSWBHeI9ZrYpXBMBvh90
ZxhuRzYp7dynppH1QFijDt3kPMJq2Dw0ErCPds90JfztFLfZK2BikTcFkbUQia+z
hwhHs75o7RnLOse+kxHP0nci2lhxJD7MwZR8HKsLqZuv7VNPIigWSC9pFYWr/TM1
eYTR9iGpRLGN+MBwpZIr94z02nrl0GhNNoyq+skDjtJ2Bi66YIe/IJu86mIZu5Ma
FxHiQ4CS5eVAn5hotPLcR/0B56rCZw==
-----END PRIVATE KEY-----

-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAu2UZLaLf3TqzV58nPLta
rUDOz2/jji7qUpKrFSngWk9Sf2K7vVxdhKpVKPWgUrI2S8NUO0z/DnI9rAaI9PaL
aoG/X46Pzj8m4b6/s9RXZsEUkoZ2eWhrzXTN3lZJa/fA62Pmp2CzxhPBjB91i+LR
ShbbthyuRPDSywLmcd0qDUZxSdjGVeIq3/75HUjlUaPfrun9h4/9EsH7akkX5Bdo
FyVFBtHHrKxUj6mMhR+amx+nQ5MEwB9u1nBbfl/2DZJM8gv8FbSP29DYNQHY4qmv
OJMRwA6HsjwZkTZQoqN0+G8d4Q2JEhIaUSUBjKhEHT03VN5UAYsQpHnd5mjlltfk
hnKgrzZwwELIHT2vD2kIpmG3n8EDww0933Snr/1bIqef/QetOUDzjWkXziFIPyn4
f0y+9treHHBR2X1wSgRfyWqTMtGmO3vFOQrZCLtFIfWNmRB02jjDMVwjilLjtqy+
JItjJZ8Avs2nbqJSjz5vKSNrW1b9iPb7U94UkDjKwxQXgrQlbr9JW7vBJrflYbT2
L6m1LypbKAtCM0YXZz4VI5CYWYeqZ8MRQYJM6a8vt5jUIEywJh8fOsUThDKiO4Wj
E18mpBCgxIzPO1pdHzPAascTiCyf9XaeYjQI+7J9xdRD4Y8GR4bMM5UECK+vDTzb
7hoWK9HIe7n3s8myjpWyhicCAwEAAQ==
-----END PUBLIC KEY-----

接下来,我创建了包含我的消息的文件:

echo "Hello, World" > message.txt

然后我用我的私钥签名邮件,并将签名存储在base64中的文件中:

openssl dgst -sha256 -sign private_key.pem -out signature message.txt
base64 signature > signature.txt

这是消息的签名:

huMEGAIfj+RQ4XHLVYEkGlgbcz5Wv62QBWk6MsxbiDBIX1ZgjhjKY3zr8livAs3x4QjfOmxqs+hOGDo9einXlNWWinslD9q+0ScoJPauK2UuIbAzLsOFoUGJBlFvCALClDlP+oIkT8qLzVPL2gONln3G68p/yZdKIQldaVMDA3mQEBJgHLKxShW1iveqhXF9P6SijE6PstTZ21KEOgMKXVjqbA8EdYucWZv1IwllFXfWJuk36MrgcfGTDesjK95LgCaZ0MjQqsiQQFA3tmZSntE8oRs7UK2fBkx/RCoFIHut4szdaUUvvxLNXVq5hgEjxysvw8Pls86iC/kfu84fJL6Xc3z9vcw4j4H2u5iJS+XGCcW4Jk+2UNprkyLtTu3uWvz21ruIZTlPhDNXdMexr9DNf7WyIsIZ3zeM1/O/Jgx6j890jN7Tth+wIIqawWuSBjd5PT3WyAqOJNtc5u0EhKlNWkoMorHuf4hWjf07XMJuS3F7PMsOGYaEwHXpc1JNN2U94TKyyPBfEpecvlo84FjKW6cpb+PINQcOVh3UeXCInk32/T4/rv4Ro6DCFlNKGobOozRSTt9a8vnQ2zOgc8omZiQzpvU8o8i92tgYtY9bIrOmIBgD+Lm/eJctjcm/qFOcNwVqj6s9Zth/pMuW+/tLxV/bsdK0XNCjGV+zAqM=

这是在Java中创建相同签名的方式:

Signature signature = Signature.getInstance("SHA256withRSA");
String privateKeyString = "-----BEGIN PRIVATE KEY-----" + paste the key from above +"-----END PRIVATE KEY-----";
privateKeyString = privateKeyString.replaceAll("\n", "").replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "");

PKCS8EncodedKeySpec encodedPrivateKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(encodedPrivateKeySpec);
signature.initSign(privateKey);

signature.update("Hello, World".getBytes("UTF-8"));
byte[] signatureValue = signature.sign();
System.out.println(Base64.encodeBase64String(signatureValue));

最后是Java输出:

DYGB6T1QAKMjgyU++rh5Ee41ED0PtvOcU1Bz+WWUM82ONC42y0VSR3a2dyxsay0YL0U8UXHF7l5F51vxxayif1F8h3tsMsyV4PKVCgOYaJooTloOJT+R5oh7mywg1lCd/u9KYHYIc7x+MopDEfiCGWETMFHt7GUqRViV3PdTtYWzKy87GN74bnzQQMqmY+BH+IZhdpdt4IC7RFh9FCwLf7RBhfX3t/dhfFhdee34r/N8aQfxos9d23IDsvudtc0zlP2uluejDqUei4FQGdKuiLCBNQJGwK6yUDXIQ0N3sm19hmysqevsj/hmLPu1BC0Uj9ryxpdL8ViYE4Sj7fLZqUD/LyMbdO4a6WbLSlLbWnd4BYfzFND6919QcUGrcqb1W1Vz5Tso3mceNT8LUb0A69F6yVnbJX1zoQaUDbHnlStsKOopfVlmLgniOXOLlzoqTUzxwRUi8+Iv4EHTLZKP//CO4iAxXR+w/LihFuUTXtTZ+Fcxj1eRbeifyqmOqsGCvPHxjqvr5FvmadusyvgkM18UQvN8f/ohReokQqlr7iW0uUPtefSuffYgNxBjm1bE6kl+/xYE21A/annfdi3dDIeif9+/NM95NQOOD3/YEFaw+H2sbBnskdMmpu5P3QKms4ppJTkZjSPn+Meg5ZAW68Pu74WNFed6qs9SjvW0nQU=

我的问题:为什么两个签名不同?我尝试分别使用OpenSSL和Java进行验证,并且在两种情况下都成功。但是,当然,验证Java中的OpenSSL签名失败了。

答案

如果我添加一个 n:

        signature.update("Hello, World
".getBytes("UTF-8"));

我明白了:

huMEGAIfj+RQ4XHLVYEkGlgbcz5Wv62QBWk6MsxbiDBIX1ZgjhjKY3zr8livAs3x4QjfOmxqs+hOGDo9einXlNWWinslD9q+0ScoJPauK2UuIbAzLsOFoUGJBlFvCALClDlP+oIkT8qLzVPL2gONln3G68p/yZdKIQldaVMDA3mQEBJgHLKxShW1iveqhXF9P6SijE6PstTZ21KEOgMKXVjqbA8EdYucWZv1IwllFXfWJuk36MrgcfGTDesjK95LgCaZ0MjQqsiQQFA3tmZSntE8oRs7UK2fBkx/RCoFIHut4szdaUUvvxLNXVq5hgEjxysvw8Pls86iC/kfu84fJL6Xc3z9vcw4j4H2u5iJS+XGCcW4Jk+2UNprkyLtTu3uWvz21ruIZTlPhDNXdMexr9DNf7WyIsIZ3zeM1/O/Jgx6j890jN7Tth+wIIqawWuSBjd5PT3WyAqOJNtc5u0EhKlNWkoMorHuf4hWjf07XMJuS3F7PMsOGYaEwHXpc1JNN2U94TKyyPBfEpecvlo84FjKW6cpb+PINQcOVh3UeXCInk32/T4/rv4Ro6DCFlNKGobOozRSTt9a8vnQ2zOgc8omZiQzpvU8o8i92tgYtY9bIrOmIBgD+Lm/eJctjcm/qFOcNwVqj6s9Zth/pMuW+/tLxV/bsdK0XNCjGV+zAqM=

以上是关于OpenSSL和Java产生不同的SHA256 RSA签名的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 OpenSSL 计算 SHA512/224 和 SHA512/256 哈希?

sha256WithRSA 签名

什么是equivelant openssl命令在Java代码中执行以下操作

使用OpenSSL计算并打印文件的SHA256哈希值

可以用 sha256 证书 openssl smime -verify

openssl evp 哈希算法(md5,sha1,sha256)