Je souhaite générer une signature RSA-SHA256 en Java, mais je ne parviens pas à obtenir la même signature qu'avec OpenSSL sur la console.
C'est ce que j'ai fait avec OpenSSL (suivant ce tutoriel ):
Générer une paire de clés:
openssl genrsa -out private.pem 1024
Extraire la clé publique:
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
Créez un hachage de données:
echo 'data to sign' > data.txt
openssl dgst -sha256 < data.txt > hash
Le fichier de hachage généré commence par (stdin)=
ce que j'ai enlevé à la main (d'abord oublié de le mentionner, merci mata).
Hachage de signe:
openssl rsautl -sign -inkey private.pem -keyform PEM -in hash > signature
Pour reproduire les résultats en Java j'ai d'abord converti la clé privée de PEM en DER:
openssl pkcs8 -topk8 -inform PEM -outform DER -in private.pem -nocrypt > private.der
Maintenant, j'ai écrit cette classe Java pour générer la même signature:
public class RSATest {
public static void main(String[] args) throws IOException,
NoSuchAlgorithmException, InvalidKeySpecException,
InvalidKeyException, SignatureException {
byte[] encodedPrivateKey = readFile("private.der");
byte[] content = readFile("data.txt");
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory
.generatePrivate(keySpec);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(content);
byte[] signatureBytes = signature.sign();
FileOutputStream fos = new FileOutputStream("signature-Java");
fos.write(signatureBytes);
fos.close();
}
private static byte[] readFile(String filename) throws IOException {
File file = new File(filename);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
file));
byte[] bytes = new byte[(int) file.length()];
bis.read(bytes);
bis.close();
return bytes;
}
}
Malheureusement, les résultats ne sont pas les mêmes, donc je pense que j'ai dû faire quelque chose de mal, mais je ne sais pas quoi. Quelqu'un parmi vous peut-il m'aider à trouver le bug?
openssl dgst -sha256 < data.txt
produit quelque chose comme:
(stdin) = b39eaeb437e33087132f01c2abc60c6a16904ee3771cd7b0d622d01061b40729
remarquez le (stdin)=
'? vous ne voulez pas que cela fasse partie de votre hachage, si vous devez créer un résumé, utilisez le -binary
option.
essayez de l'utiliser pour signer vos données:
openssl sha -sha256 -sign private.pem < data.txt
Cela fait tout ce dont vous avez besoin.
modifier - un peu plus d'explications:
créons un résumé et montrons-le
$ openssl dgst -sha256 -binary < data.txt > digest
$ hd digest
00000000 26 3b 0a a1 2e b9 32 db b8 dc d3 6f 37 94 0b 05 |&;....2....o7...|
00000010 71 9c ba 79 46 34 28 9f 5c 5b 98 9a 64 61 c9 ec |q..yF4(.\[..da..|
maintenant, nous prenons ce résumé et nous nous connectons avec rsautl
:
$ openssl rsautl -sign -inkey private.pem < digest > sign1
$ hd sign1
00000000 1b 7a cf a4 8d 41 8e 04 ed 3a bb ba 86 f1 f8 e0 |.z...A...:......|
00000010 df f7 47 3e d7 a7 f4 90 7a 05 f8 7f 45 e5 29 e7 |..G>....z...E.).|
00000020 9f f4 2c 91 97 2f e7 26 69 9f 6a 07 a3 48 1b 85 |..,../.&i.j..H..|
00000030 2e f8 ee 44 4d 25 9f ae 05 95 81 c9 e3 07 68 ad |...DM%........h.|
signons maintenant le même fichier en utilisant dgst
directement:
$ openssl dgst -sha256 -sign private.pem < data.txt > sign2
$ hd sign2
00000000 15 c2 94 87 eb e6 cb 45 c8 63 0c 97 60 d3 07 f3 |.......E.c..`...|
00000010 dc 65 32 ad 44 1c c2 2a 7f a3 e1 fc dd 84 27 8c |.e2.D..*......'.|
00000020 77 a6 97 2b 33 6b c6 d7 7d e1 1d 39 5c 48 b6 48 |w..+3k..}..9\H.H|
00000030 cb 18 be bf 6a 66 90 d3 88 89 52 6c dd d1 b9 99 |....jf....Rl....|
Alors qu'est-ce qui est différent ici? Pour voir cela, nous pouvons vérifier la signature et afficher la sortie brute. Les deux fichiers contiennent le résumé, mais les métadonnées et le remplissage sont différents:
$ openssl rsautl -raw -verify -inkey private.pem < sign1 | hd
00000000 00 01 ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
00000010 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 |................|
00000020 26 3b 0a a1 2e b9 32 db b8 dc d3 6f 37 94 0b 05 |&;....2....o7...|
00000030 71 9c ba 79 46 34 28 9f 5c 5b 98 9a 64 61 c9 ec |q..yF4(.\[..da..|
$ openssl rsautl -raw -verify -inkey private.pem < sign2 | hd
00000000 00 01 ff ff ff ff ff ff ff ff ff ff 00 30 31 30 |.............010|
00000010 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 |...`.H.e....... |
00000020 26 3b 0a a1 2e b9 32 db b8 dc d3 6f 37 94 0b 05 |&;....2....o7...|
00000030 71 9c ba 79 46 34 28 9f 5c 5b 98 9a 64 61 c9 ec |q..yF4(.\[..da..|
Pour voir cela plus clairement, nous pouvons essayer d'utiliser le -asn1parse
flag, qui ne fonctionnera pas pour la première signature, mais pour la seconde il montre la structure correcte de la signature:
$ openssl rsautl -verify -inkey private.pem -asn1parse < sign1
Error in encoding
139931349546656:error:0D07209B:asn1 encoding routines:ASN1_get_object:too long:asn1_lib.c:142:
$ openssl rsautl -verify -inkey private.pem -asn1parse < sign2
0:d=0 hl=2 l= 49 cons: SEQUENCE
2:d=1 hl=2 l= 13 cons: SEQUENCE
4:d=2 hl=2 l= 9 prim: OBJECT :sha256
15:d=2 hl=2 l= 0 prim: NULL
17:d=1 hl=2 l= 32 prim: OCTET STRING
0000 - 26 3b 0a a1 2e b9 32 db-b8 dc d3 6f 37 94 0b 05 &;....2....o7...
0010 - 71 9c ba 79 46 34 28 9f-5c 5b 98 9a 64 61 c9 ec q..yF4(.\[..da..