Проверка подписи в Java с использованием открытого ключа сертификатов - PullRequest
0 голосов
/ 11 августа 2009

Я хочу преобразовать некоторый код C # в эквивалент в Java.

Код C # принимает некоторое строковое содержимое и подпись (генерируемую с использованием закрытого ключа на отдельном компьютере) и в сочетании с открытым ключом проверяет совпадения подписи, обеспечивая уровень гарантии того, что запрос не был подделан с.

  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);
  }

Открытый ключ сам по себе является сертификатом X509, созданным из файла .cer, который хранится как ресурс сборки, т. Е.

byte[] data; // data is read from a resource stream.
var publicKey = new X509Certificate2(data, "", X509KeyStorageFlags.MachineKeySet).PublicKey.Key

Я хочу эмулировать эту функциональность в Java, чтобы я мог проверить сигнатуру, сгенерированную некоторым кодом в C # ... Я начал исследовать криптографическую функциональность Java, но немного Ява нуб. Вот что я придумала до сих пор:

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)

Может ли кто-нибудь предоставить какое-либо представление о том, как я могу проверить подпись, или предоставить ссылки на некоторые ресурсы, которые могли бы объяснить использование java.crypto и java.security.cert лучше, чем запуск обычной документации Java.

1 Ответ

2 голосов
/ 11 августа 2009

Этот код на C # кажется мне очень запутанным. Он использует SHA1CryptoServiceProvider, но использует хеш MD5, поэтому я не могу сказать, какой алгоритм хэширования он использует. Я полагаю, это MD5.

Процесс проверки подписи включает заполнение, чтобы ваш код не работал. Ниже приведен фрагмент моего кода, и вы можете использовать его для проверки подписи. данные - это байты для подписи, а sigBytes содержит подпись.

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);
}
...