/* * Copyright (c) 2011, 2012, 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. */ /** * @see SignUsingNONEwithRSA.sh */ import java.security.*; import java.util.*; public class SignUsingNONEwithRSA { private static final List precomputedHashes = Arrays.asList( // A MD5 hash new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 }, // A SHA-1 hash new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20 }, // A concatenation of SHA-1 and MD5 hashes (used during SSL handshake) new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 }, // A SHA-224 hash new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28 }, // A SHA-256 hash new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31, 0x32 }, // A SHA-384 hash new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, // A SHA-512 hash new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x60, 0x61, 0x62, 0x63, 0x64 }); private static List generatedSignatures = new ArrayList<>(); public static void main(String[] args) throws Exception { Provider[] providers = Security.getProviders("Signature.NONEwithRSA"); if (providers == null) { System.out.println("No JCE providers support the " + "'Signature.NONEwithRSA' algorithm"); System.out.println("Skipping this test..."); return; } else { System.out.println("The following JCE providers support the " + "'Signature.NONEwithRSA' algorithm: "); for (Provider provider : providers) { System.out.println(" " + provider.getName()); } } System.out.println("-------------------------------------------------"); KeyPair keys = getKeysFromKeyStore(); signAllUsing("SunMSCAPI", keys.getPrivate()); System.out.println("-------------------------------------------------"); verifyAllUsing("SunMSCAPI", keys.getPublic()); System.out.println("-------------------------------------------------"); verifyAllUsing("SunJCE", keys.getPublic()); System.out.println("-------------------------------------------------"); keys = generateKeys(); signAllUsing("SunJCE", keys.getPrivate()); System.out.println("-------------------------------------------------"); verifyAllUsing("SunMSCAPI", keys.getPublic()); System.out.println("-------------------------------------------------"); } private static KeyPair getKeysFromKeyStore() throws Exception { KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI"); ks.load(null, null); System.out.println("Loaded keystore: Windows-MY"); Enumeration e = ks.aliases(); PrivateKey privateKey = null; PublicKey publicKey = null; while (e.hasMoreElements()) { String alias = (String) e.nextElement(); if (alias.equals("6578658")) { System.out.println("Loaded entry: " + alias); privateKey = (PrivateKey) ks.getKey(alias, null); publicKey = (PublicKey) ks.getCertificate(alias).getPublicKey(); } } if (privateKey == null || publicKey == null) { throw new Exception("Cannot load the keys need to run this test"); } return new KeyPair(publicKey, privateKey); } private static KeyPair generateKeys() throws Exception { KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); keyGen.initialize(1024, null); KeyPair pair = keyGen.generateKeyPair(); PrivateKey privateKey = pair.getPrivate(); PublicKey publicKey = pair.getPublic(); if (privateKey == null || publicKey == null) { throw new Exception("Cannot load the keys need to run this test"); } return new KeyPair(publicKey, privateKey); } private static void signAllUsing(String providerName, PrivateKey privateKey) throws Exception { Signature sig1 = Signature.getInstance("NONEwithRSA", providerName); if (sig1 == null) { throw new Exception("'NONEwithRSA' is not supported"); } if (sig1.getProvider() != null) { System.out.println("Using NONEwithRSA signer from the " + sig1.getProvider().getName() + " JCE provider"); } else { System.out.println( "Using NONEwithRSA signer from the internal JCE provider"); } System.out.println("Using key: " + privateKey); generatedSignatures.clear(); for (byte[] hash : precomputedHashes) { sig1.initSign(privateKey); sig1.update(hash); try { byte [] sigBytes = sig1.sign(); System.out.println("\nGenerated RSA signature over a " + hash.length + "-byte hash (signature length: " + sigBytes.length * 8 + " bits)"); System.out.println(String.format("0x%0" + (sigBytes.length * 2) + "x", new java.math.BigInteger(1, sigBytes))); generatedSignatures.add(sigBytes); } catch (SignatureException se) { System.out.println("Error generating RSA signature: " + se); } } } private static void verifyAllUsing(String providerName, PublicKey publicKey) throws Exception { Signature sig1 = Signature.getInstance("NONEwithRSA", providerName); if (sig1.getProvider() != null) { System.out.println("\nUsing NONEwithRSA verifier from the " + sig1.getProvider().getName() + " JCE provider"); } else { System.out.println( "\nUsing NONEwithRSA verifier from the internal JCE provider"); } System.out.println("Using key: " + publicKey); int i = 0; for (byte[] hash : precomputedHashes) { byte[] sigBytes = generatedSignatures.get(i++); System.out.println("\nVerifying RSA Signature over a " + hash.length + "-byte hash (signature length: " + sigBytes.length * 8 + " bits)"); System.out.println(String.format("0x%0" + (sigBytes.length * 2) + "x", new java.math.BigInteger(1, sigBytes))); sig1.initVerify(publicKey); sig1.update(hash); if (sig1.verify(sigBytes)) { System.out.println("Verify PASSED"); } else { throw new Exception("Verify FAILED"); } } } }