Vérification d'une signature en Java en utilisant un certificat de clé publique
-
12-09-2019 - |
Question
Je cherche à convertir un code C # pour l'équivalent en Java.
Le code C # prend un certain contenu de la chaîne, et une signature (générée à l'aide de la clé privée, sur une machine séparée) et combinée avec la clé publique, il vérifie la signature correspond, en fournissant un niveau d'assurance que la demande n'a pas été falsifié avec.
public bool VerifySignature(string content, byte[] signatureBytes, AsymmetricAlgorithm publicKey)
{
var hash = new MD5CryptoServiceProvider();
byte[] dataBuffer = Encoding.ASCII.GetBytes(content);
var cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write);
cs.Write(dataBuffer, 0, dataBuffer.Length);
cs.Close();
var deformatter = new RSAPKCS1SignatureDeformatter(publicKey);
deformatter.SetHashAlgorithm("MD5");
return deformatter.VerifySignature(hash, signatureBytes);
}
La clé publique est elle-même un certificat X509 - construit à partir d'un fichier .cer, stocké sous forme de montage i.e. des ressources
.byte[] data; // data is read from a resource stream.
var publicKey = new X509Certificate2(data, "", X509KeyStorageFlags.MachineKeySet).PublicKey.Key
Qu'est-ce que je cherche à faire est de reproduire cette fonctionnalité en Java, donc je peux vérifier la signature générée par un code en C # ... J'ai commencé à étudier la fonctionnalité de Crypto de Java, mais je suis un peu un noob java. Voici ce que je suis venu avec à ce jour:
byte[] certContents=null;
byte[] signature=null;
String contents = "abc";
// load cert
CertificateFactory factory = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certContents));
// grab public key
RSAPublicKey publicKey = (RSAPublicKey)cert.getPublicKey();
// get sha1 hash for contents
Mac mac = Mac.getInstance("HmacSHA1");
mac.update(contents.getBytes());
byte[] hash = mac.doFinal();
// get cipher
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
// verify signature of contents matches signature passed to method somehow (and this is where I'm stuck)
Quelqu'un peut-il fournir une idée de la façon dont je peux vérifier la signature -. Ou de fournir des liens vers des ressources qui pourraient expliquer l'utilisation de java.crypto et java.security.cert mieux que la course de la documentation java moulin
La solution
Ce code C # ressemble vraiment déroutant pour moi. Il utilise SHA1CryptoServiceProvider mais utilise hachage MD5 donc je ne peux pas dire que l'algorithme de hachage qu'il utilise. Je suppose que c'est MD5.
Le processus de vérification de signature implique un rembourrage si votre code ne fonctionnerait pas. Voici quelques-uns extrait de mon code et vous pouvez l'utiliser pour vérifier la signature. les données sont les octets à signer et sigBytes détient la signature.
String algorithm = "MD5withRSA";
// Initialize JCE provider
Signature verifier = Signature.getInstance(algorithm);
// Do the verification
boolean result=false;
try {
verifier.initVerify(cert); // This one checks key usage in the cert
verifier.update(data);
result = verifier.verify(sigBytes);
}
catch (Exception e) {
throw new VerificationException("Verification error: "+e, e);
}