| /* |
| * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /* |
| * @test |
| * @bug 8161571 8178370 |
| * @summary Reject signatures presented for verification that contain extra |
| * bytes. |
| * @modules jdk.crypto.ec |
| * @run main SignatureLength |
| */ |
| |
| import java.security.KeyPair; |
| import java.security.KeyPairGenerator; |
| import java.security.NoSuchAlgorithmException; |
| import java.security.Provider; |
| import java.security.Security; |
| import java.security.Signature; |
| import java.security.SignatureException; |
| |
| public class SignatureLength { |
| |
| public static void main(String[] args) throws Exception { |
| for (Provider p0 : Security.getProviders()) { |
| for (Provider p1 : Security.getProviders()) { |
| for (Provider p2 : Security.getProviders()) { |
| // SunMSCAPI signer can only be initialized with |
| // a key generated with SunMSCAPI |
| if (!p0.getName().equals("SunMSCAPI") |
| && p1.getName().equals("SunMSCAPI")) continue; |
| |
| // SunMSCAPI generated key can only be signed |
| // with SunMSCAPI signer |
| if (p0.getName().equals("SunMSCAPI") |
| && !p1.getName().equals("SunMSCAPI")) continue; |
| |
| // SunMSCAPI and SunPKCS11 verifiers may return false |
| // instead of throwing SignatureException |
| boolean mayNotThrow = p2.getName().equals("SunMSCAPI") |
| || p2.getName().startsWith("SunPKCS11"); |
| |
| main0("EC", 256, "SHA256withECDSA", p0, p1, p2, mayNotThrow); |
| main0("RSA", 2048, "SHA256withRSA", p0, p1, p2, mayNotThrow); |
| main0("DSA", 2048, "SHA256withDSA", p0, p1, p2, mayNotThrow); |
| } |
| } |
| } |
| } |
| |
| private static void main0(String keyAlgorithm, int keysize, |
| String signatureAlgorithm, Provider generatorProvider, |
| Provider signerProvider, Provider verifierProvider, |
| boolean mayNotThrow) throws Exception { |
| |
| KeyPairGenerator generator; |
| Signature signer; |
| Signature verifier; |
| |
| try { |
| generator = KeyPairGenerator.getInstance(keyAlgorithm, |
| generatorProvider); |
| signer = Signature.getInstance(signatureAlgorithm, |
| signerProvider); |
| verifier = Signature.getInstance(signatureAlgorithm, |
| verifierProvider); |
| } catch (NoSuchAlgorithmException nsae) { |
| // ignore this set of providers |
| return; |
| } |
| |
| byte[] plaintext = "aaa".getBytes("UTF-8"); |
| |
| // Generate |
| generator.initialize(keysize); |
| System.out.println("Generating " + keyAlgorithm + " keypair using " + |
| generator.getProvider().getName() + " JCE provider"); |
| KeyPair keypair = generator.generateKeyPair(); |
| |
| // Sign |
| signer.initSign(keypair.getPrivate()); |
| signer.update(plaintext); |
| System.out.println("Signing using " + signer.getProvider().getName() + |
| " JCE provider"); |
| byte[] signature = signer.sign(); |
| |
| // Invalidate |
| System.out.println("Invalidating signature ..."); |
| byte[] badSignature = new byte[signature.length + 5]; |
| System.arraycopy(signature, 0, badSignature, 0, signature.length); |
| badSignature[signature.length] = 0x01; |
| badSignature[signature.length + 1] = 0x01; |
| badSignature[signature.length + 2] = 0x01; |
| badSignature[signature.length + 3] = 0x01; |
| badSignature[signature.length + 4] = 0x01; |
| |
| // Verify |
| verifier.initVerify(keypair.getPublic()); |
| verifier.update(plaintext); |
| System.out.println("Verifying using " + |
| verifier.getProvider().getName() + " JCE provider"); |
| |
| try { |
| boolean valid = verifier.verify(badSignature); |
| System.out.println("Valid? " + valid); |
| if (mayNotThrow) { |
| if (valid) { |
| throw new Exception( |
| "ERROR: expected a SignatureException but none was thrown" |
| + " and invalid signature was verified"); |
| } else { |
| System.out.println("OK: verification failed as expected"); |
| } |
| } else { |
| throw new Exception( |
| "ERROR: expected a SignatureException but none was thrown"); |
| } |
| } catch (SignatureException e) { |
| System.out.println("OK: caught expected exception: " + e); |
| } |
| System.out.println(); |
| } |
| } |