diff options
Diffstat (limited to 'java/com/google/security/wycheproof/testcases/RsaSignatureTest.java')
-rw-r--r-- | java/com/google/security/wycheproof/testcases/RsaSignatureTest.java | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/java/com/google/security/wycheproof/testcases/RsaSignatureTest.java b/java/com/google/security/wycheproof/testcases/RsaSignatureTest.java new file mode 100644 index 0000000..5b33aa1 --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/RsaSignatureTest.java @@ -0,0 +1,140 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.MessageDigest; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.RSAPublicKeySpec; +import junit.framework.TestCase; + +/** Tests RSA signature schemes. */ +// TODO(bleichen): +// - maybe add tests with invalid keys. +// - So far only PKCS #1 signatures are tested. But RSA-PSS becomes more popular. +// - document stuff +// - Join other RSA tests +public class RsaSignatureTest extends TestCase { + static final RSAPublicKeySpec RSA_KEY1 = + new RSAPublicKeySpec( + new BigInteger( + "ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9" + + "8590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26" + + "c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6feb" + + "e1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f", + 16), + new BigInteger("65537")); + static final String ALGORITHM_KEY1 = "SHA256WithRSA"; + + public void testBasic() throws Exception { + String algorithm = "SHA256WithRSA"; + String hashAlgorithm = "SHA-256"; + String message = "Hello"; + int keysize = 2048; + + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(keysize); + KeyPair keyPair = keyGen.generateKeyPair(); + RSAPublicKey pub = (RSAPublicKey) keyPair.getPublic(); + RSAPrivateKey priv = (RSAPrivateKey) keyPair.getPrivate(); + + byte[] messageBytes = message.getBytes("UTF-8"); + Signature signer = Signature.getInstance(algorithm); + Signature verifier = Signature.getInstance(algorithm); + signer.initSign(priv); + signer.update(messageBytes); + byte[] signature = signer.sign(); + verifier.initVerify(pub); + verifier.update(messageBytes); + assertTrue(verifier.verify(signature)); + + // Extract some parameters. + byte[] rawHash = MessageDigest.getInstance(hashAlgorithm).digest(messageBytes); + + // Print keys and signature, so that it can be used to generate new test vectors. + System.out.println("Message:" + message); + System.out.println("Hash:" + TestUtil.bytesToHex(rawHash)); + System.out.println("Public key:"); + System.out.println("Modulus:" + pub.getModulus().toString()); + System.out.println("E:" + pub.getPublicExponent().toString()); + System.out.println("encoded:" + TestUtil.bytesToHex(pub.getEncoded())); + System.out.println("Private key:"); + System.out.println("D:" + priv.getPrivateExponent().toString()); + System.out.println("encoded:" + TestUtil.bytesToHex(priv.getEncoded())); + System.out.println("Signature:" + TestUtil.bytesToHex(signature)); + } + + /** + * Signatures with legacy encoding. Such signatures are sometimes accepted to be compatible with + * previously buggy implementations. + */ + static final String[] LEGACY_SIGNATURES_KEY1 = { + // A signature where the NULL parameter is missing in the ASN encoding. + // padding = 302f300b06096086480165030402010420532eaabd9574880dbf + // 76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25 + "253e1d19bbe91064f2364c1e7db3ba8eb6dc5b19202e440eab6fbdf28c8c6ec0" + + "5b812983713c338c72b6e99b8edf506a89ff9fc8e5c2c52362097a56dc228060" + + "eca01e1ff318c6c81617691438703411c1f953b21cd74331f87c9b8b189fdffd" + + "fe8550bd2bd1d47be915f8604a0f472199dd705e19b1b815f99b68d60bc257c7", + }; + + /** + * Tests legacy signatures. In this context we use the term legacy signatures for signatures that + * are not conforming to the PKCS #1 standard, but are sometimes generated by buggy signers. So + * far this test considers both accepting and rejecting such signatures as valid behavior. + * + * <p>Currently we check for just one type of legacy signatures: i.e., a missing NULL parameter in + * the ASN encoding of the hash. BouncyCastle and the SunJCE accept this signature, Conscrypt does + * not. + * + * <p>Some references that support accepting this signature: + * https://codereview.chromium.org/1690123002/ + * https://groups.google.com/a/chromium.org/forum/#!topic/chromium-reviews/Jo5S7HtEABI claims that + * 7% of the responses in the Online Certificate Status Protocol (OCSP) miss the NULL parameter + */ + public void testLegacySignatures() throws Exception { + RSAPublicKeySpec key = RSA_KEY1; + String algorithm = ALGORITHM_KEY1; + byte[] message = "Test".getBytes("UTF-8"); + Signature verifier = Signature.getInstance(algorithm); + KeyFactory kf = KeyFactory.getInstance("RSA"); + PublicKey pub = kf.generatePublic(key); + for (String signature : LEGACY_SIGNATURES_KEY1) { + byte[] signatureBytes = TestUtil.hexToBytes(signature); + verifier.initVerify(pub); + verifier.update(message); + boolean verified = false; + try { + verified = verifier.verify(signatureBytes); + } catch (SignatureException ex) { + verified = false; + } + if (verified) { + System.out.println("Verfied legacy signature:" + signature); + } else { + System.out.println("Rejected legacy signature:" + signature); + } + } + } +} |