aboutsummaryrefslogtreecommitdiff
path: root/java/com/google/security/wycheproof/testcases/RsaSignatureTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/google/security/wycheproof/testcases/RsaSignatureTest.java')
-rw-r--r--java/com/google/security/wycheproof/testcases/RsaSignatureTest.java140
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);
+ }
+ }
+ }
+}