web-dev-qa-db-fra.com

Chiffrement RSA avec clé publique donnée (en Java)

Je recherche un Java échantillon comment faire le chiffrement RSA avec un clé publique donnée (je l'ai au format base64, il semble qu'il ait une longueur de 1024 bits).

Ci-dessous mon code, mais j'ai l'exception InvalidKeySpec.

String publicKey = "AJOnAeTfeU4K+do5QdBM2BQUhfrRI2rYf/Gk4a3jZJB2ewekgq2VgLNislBdql/glA39w0NjXZyTg0mW917JdUlHqKoQ9765pJc4aTjvX+3IxdFhteyO2jE3vKX1GgA3i3n6+sMBAJiT3ax57i68mbT+KAeP1AX9199aj2W4JZeP";
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] res = new Base64Encoder().decode(publicKey.getBytes());
X509EncodedKeySpec KeySpec = new X509EncodedKeySpec(res);
RSAPublicKey pubKey = (RSAPublicKey)keyFactory.generatePublic(KeySpec);

// here the exception occurs..

Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] cipherData = cipher.doFinal(input.getBytes());
return cipherData;

Veuillez me donner l'échantillon,

30
david.papirov

Voici comment je parviens à chiffrer une chaîne avec uniquement une clé publique RSA.

Enregistrez d'abord la clé publique au format PEM dans le nom de fichier pubkey.pem

-----BEGIN PUBLIC KEY-----
AJOnAeTfeU4K+do5QdBM2BQUhfrRI2rYf/Gk4...
-----END PUBLIC KEY-----

Trouver le module de clé RSA public

$ openssl rsa -pubin -in pubkey.pem -modulus -noout
Modulus=F56D...

Trouver l'exposant de clé RSA publique

$ openssl rsa -pubin -in pubkey.pem -text -noout
...
Exponent: 65537 (0x10001)

Insérez-les ensuite dans le code suivant.

BigInteger modulus = new BigInteger("F56D...", 16);
BigInteger pubExp = new BigInteger("010001", 16);

KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(modulus, pubExp);
RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(pubKeySpec);

Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);

byte[] cipherData = cipher.doFinal(text.getBytes());
42
nevcx

Votre "clé" n'est pas une clé publique valide. Il s'agit d'une chaîne Base64 qui, lorsqu'elle est décodée, produit une séquence de 129 octets, le premier étant 0x00, suivi de 0x93. Ce n'est pas un format valide pour une clé publique RSA, mais il ressemble étrangement au codage signé big-endian d'un entier de 1024 bits (c'est-à-dire le type de codage renvoyé par BigInteger.toByteArray() et utilisé dans ASN.1 "INTEGER"). Une clé publique RSA se compose nominalement de deux entiers, l'un étant le module et l'autre le exposant public. Un module RSA typique a une longueur de 1024 bits, il est donc probable que vous ayez ici le module. Vous avez toujours besoin de l'exposant public pour compléter la clé.

X509EncodedKeySpec Attend le codage DER d'une structure ASN.1 qui identifie l'algorithme comme étant RSA, et contient une structure codée imbriquée qui elle-même contient les deux entiers pour la clé publique RSA. Assembler une telle structure à la main pourrait s'avérer difficile (c'est faisable, mais nécessite une compréhension approfondie de l'ASN.1). Une méthode plus simple serait d'utiliser RSAPublicKeySpec:

String modulusBase64 = "..."; // your Base64 string here
BigInteger modulus = new BigInteger(1,
        new Base64Encoder.decode(modulusBase64.getBytes("UTF-8")));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKeySpec ks = new RSAPublicKeySpec(modulus, pubExp);
RSAPublicKey pubKey = (RSAPublicKey)keyFactory.generatePublic(KeySpec);

Dans ce qui précède, "pubExp" doit être un BigInteger contenant l'exposant public, que vous ne donnez pas. 3 et 65537 sont les valeurs traditionnelles pour l'exposant public, mais d'autres sont possibles, et vous ne donnez pas suffisamment d'informations pour faire la distinction entre les exposants publics (c'est-à-dire que votre code semblera fonctionner même si vous n'utilisez pas le bon). Fondamentalement, vous n'avez que la moitié de la clé publique; vous devriez demander à celui qui vous a donné cette moitié de vous envoyer également l'autre moitié.

Remarque: String.getBytes() utilise le codage par défaut de la plateforme, qui n'est pas toujours le même. Si vous insistez pour convertir une chaîne en une séquence d'octets, vous devez utiliser un nom de jeu de caractères explicite, tel que "UTF-8", Sinon vous risquez de rencontrer des problèmes si votre code fonctionne sur, disons, un système russe ou chinois. . De plus, je ne sais pas d'où vient votre classe Base64Encoder (Elle ne fait pas partie de l'API standard Java) mais il est probable qu'elle puisse également fonctionner directement sur un String ou StringReader, rendant l'étape de conversion inutile.

14
Thomas Pornin

Votre clé publique est-elle vraiment codée X509? Sinon, un Keyspec non codé devrait vous aider.

0
dunni

Votre clé publique ne ressemble pas à une valeur 1024 bits encodée en Base64. Une valeur de 1024 bits nécessiterait 172 caractères (le dernier étant un remplisseur =) et nous avons ici 175 caractères.

Pour un test, remplacez le quatre derniers caractères dans votre chaîne par n seul= et testez si cela élimine l'exception. Cela ne résoudra pas le problème mais peut pointer dans la bonne direction.

0
Andreas_D