J'ai généré cette clé publique de test à l'aide de 1024 RSA, puis je l'ai encodée en DER et Base64 dans une autre plate-forme de codage. J'ai copié la clé dans une chaîne sous Android/Eclipse et j'essaie de la transformer en clé publique à l'aide de KeyFactory. Il me donne juste une exception InvalidKeySpecException, peu importe ce que j'essaie. Tout conseil serait apprécié.
private void prepKeys() {
String AppKeyPub = "MIGHAoGBAOX+TFdFVIKYyCVxWlnbGYbmgkkmHmEv2qStZzAFt6NVqKPLK989Ow0RcqcDTZaZBfO5" +
"5JSVHNIKoqULELruACfqtGoATfgwBp4Owfww8M891gKNSlI/M0yzDQHns5CKwPE01jD6qGZ8/2IZ" +
"OjLJNH6qC9At8iMCbPe9GeXIPFWRAgER";
// create the key factory
try {
KeyFactory kFactory = KeyFactory.getInstance("RSA");
// decode base64 of your key
byte yourKey[] = Base64.decode(AppKeyPub,0);
// generate the public key
X509EncodedKeySpec spec = new X509EncodedKeySpec(yourKey);
PublicKey publicKey = (PublicKey) kFactory.generatePublic(spec);
System.out.println("Public Key: " + publicKey);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
La clé que vous avez est au format PKCS # 1 au lieu de la structure SubjectPublicKeyInfo qui Java accepte. PKCS # 1 est le codage des paramètres RSA uniquement et il manque des éléments tels qu'un identifiant d'algorithme. SubjectPublicKeyInfo utilise PKCS # 1 en interne - pour les clés publiques RSA de toute façon.
La clé publique PKCS # 1 étant à la fin de la structure SubjectPublicKeyInfo, il est possible de simplement préfixer les octets afin qu'ils deviennent un RSA SubjectPublicKeyInfo. Cette solution est plus facile à réaliser sans bibliothèques supplémentaires telles que Bouncy Castle. Donc, si vous devez vous passer d'une bibliothèque externe, vous pouvez consulter ma réponse ici .
Alternativement, un simple décodeur BER pourrait être écrit pour décoder la structure en deux valeurs BigInteger. La structure elle-même ce n'est pas si compliqué mais le codage de longueur BER/DER prend un certain temps pour s'y habituer.
Cependant, vous pouvez également utiliser Bouncy Castle (API légère) pour résoudre vos problèmes:
String publicKeyB64 = "MIGHAoGBAOX+TFdFVIKYyCVxWlnbGYbmgkkmHmEv2qStZzAFt6NVqKPLK989Ow0RcqcDTZaZBfO5"
+ "5JSVHNIKoqULELruACfqtGoATfgwBp4Owfww8M891gKNSlI/M0yzDQHns5CKwPE01jD6qGZ8/2IZ"
+ "OjLJNH6qC9At8iMCbPe9GeXIPFWRAgER";
// ok, you may need to use the Base64 decoder of bouncy or Android instead
byte[] decoded = Base64.getDecoder().decode(publicKeyB64);
org.bouncycastle.asn1.pkcs.RSAPublicKey pkcs1PublicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey.getInstance(decoded);
BigInteger modulus = pkcs1PublicKey.getModulus();
BigInteger publicExponent = pkcs1PublicKey.getPublicExponent();
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, publicExponent);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey generatedPublic = kf.generatePublic(keySpec);
System.out.printf("Modulus: %X%n", modulus);
System.out.printf("Public exponent: %d ... 17? Why?%n", publicExponent); // 17? OK.
System.out.printf("See, Java class result: %s, is RSAPublicKey: %b%n", generatedPublic.getClass().getName(), generatedPublic instanceof RSAPublicKey);
Comme vous pouvez le voir, il ne nécessite en fait qu'une seule classe en tant qu'interface, bien que cela soit bien sûr sauvegardé avec l'ensemble des fonctionnalités du décodeur ASN.1/BER dans Bouncy Castle.
Notez qu'il peut être nécessaire de changer le décodeur Base 64 en le Android spécifique) (Android.util.Base64
) . Ce code a été testé sur un équivalent Java runtime.