1fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro/* 2874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. 3fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * 5fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * This code is free software; you can redistribute it and/or modify it 6fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * under the terms of the GNU General Public License version 2 only, as 7fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * published by the Free Software Foundation. Oracle designates this 8fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * particular file as subject to the "Classpath" exception as provided 9fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * by Oracle in the LICENSE file that accompanied this code. 10fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * 11fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * This code is distributed in the hope that it will be useful, but WITHOUT 12fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * version 2 for more details (a copy is included in the LICENSE file that 15fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * accompanied this code). 16fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * 17fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * You should have received a copy of the GNU General Public License version 18fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * 2 along with this work; if not, write to the Free Software Foundation, 19fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * 21fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * or visit www.oracle.com if you need additional information or have any 23fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * questions. 24fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro */ 25fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 26fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giropackage sun.security.util; 27fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 28fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giroimport java.util.HashSet; 29fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giroimport java.util.Set; 30fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giroimport java.util.regex.Pattern; 31fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 32fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro/** 33fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro * The class decomposes standard algorithms into sub-elements. 34fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro */ 35fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giropublic class AlgorithmDecomposer { 36fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 37fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro private static final Pattern transPattern = Pattern.compile("/"); 38fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro private static final Pattern pattern = 39fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro Pattern.compile("with|and", Pattern.CASE_INSENSITIVE); 40fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 41874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak private static Set<String> decomposeImpl(String algorithm) { 42fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 43fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro // algorithm/mode/padding 44fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro String[] transTockens = transPattern.split(algorithm); 45fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 46fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro Set<String> elements = new HashSet<>(); 47fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro for (String transTocken : transTockens) { 48fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro if (transTocken == null || transTocken.length() == 0) { 49fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro continue; 50fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro } 51fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 52fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro // PBEWith<digest>And<encryption> 53fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro // PBEWith<prf>And<encryption> 54fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro // OAEPWith<digest>And<mgf>Padding 55fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro // <digest>with<encryption> 56fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro // <digest>with<encryption>and<mgf> 57fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro String[] tokens = pattern.split(transTocken); 58fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 59fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro for (String token : tokens) { 60fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro if (token == null || token.length() == 0) { 61fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro continue; 62fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro } 63fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 64fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro elements.add(token); 65fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro } 66fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro } 67874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak return elements; 68874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak } 69874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak 70874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak /** 71874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak * Decompose the standard algorithm name into sub-elements. 72874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak * <p> 73874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA" 74874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak * so that we can check the "SHA1" and "RSA" algorithm constraints 75874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak * separately. 76874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak * <p> 77874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak * Please override the method if need to support more name pattern. 78874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak */ 79874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak public Set<String> decompose(String algorithm) { 80874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak if (algorithm == null || algorithm.length() == 0) { 81874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak return new HashSet<>(); 82874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak } 83874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak 84874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak Set<String> elements = decomposeImpl(algorithm); 85fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 86fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro // In Java standard algorithm name specification, for different 87fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro // purpose, the SHA-1 and SHA-2 algorithm names are different. For 88fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro // example, for MessageDigest, the standard name is "SHA-256", while 89fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro // for Signature, the digest algorithm component is "SHA256" for 90fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro // signature algorithm "SHA256withRSA". So we need to check both 91fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro // "SHA-256" and "SHA256" to make the right constraint checking. 92fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 93fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro // handle special name: SHA-1 and SHA1 94fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro if (elements.contains("SHA1") && !elements.contains("SHA-1")) { 95fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro elements.add("SHA-1"); 96fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro } 97fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro if (elements.contains("SHA-1") && !elements.contains("SHA1")) { 98fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro elements.add("SHA1"); 99fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro } 100fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 101fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro // handle special name: SHA-224 and SHA224 102fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro if (elements.contains("SHA224") && !elements.contains("SHA-224")) { 103fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro elements.add("SHA-224"); 104fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro } 105fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro if (elements.contains("SHA-224") && !elements.contains("SHA224")) { 106fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro elements.add("SHA224"); 107fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro } 108fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 109fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro // handle special name: SHA-256 and SHA256 110fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro if (elements.contains("SHA256") && !elements.contains("SHA-256")) { 111fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro elements.add("SHA-256"); 112fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro } 113fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro if (elements.contains("SHA-256") && !elements.contains("SHA256")) { 114fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro elements.add("SHA256"); 115fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro } 116fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 117fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro // handle special name: SHA-384 and SHA384 118fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro if (elements.contains("SHA384") && !elements.contains("SHA-384")) { 119fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro elements.add("SHA-384"); 120fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro } 121fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro if (elements.contains("SHA-384") && !elements.contains("SHA384")) { 122fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro elements.add("SHA384"); 123fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro } 124fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 125fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro // handle special name: SHA-512 and SHA512 126fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro if (elements.contains("SHA512") && !elements.contains("SHA-512")) { 127fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro elements.add("SHA-512"); 128fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro } 129fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro if (elements.contains("SHA-512") && !elements.contains("SHA512")) { 130fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro elements.add("SHA512"); 131fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro } 132fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 133fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro return elements; 134fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro } 135fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro 136874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak private static void hasLoop(Set<String> elements, String find, String replace) { 137874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak if (elements.contains(find)) { 138874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak if (!elements.contains(replace)) { 139874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak elements.add(replace); 140874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak} 141874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak elements.remove(find); 142874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak } 143874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak } 144874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak 145874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak /* 146874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak * This decomposes a standard name into sub-elements with a consistent 147874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak * message digest algorithm name to avoid overly complicated checking. 148874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak */ 149874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak public static Set<String> decomposeOneHash(String algorithm) { 150874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak if (algorithm == null || algorithm.length() == 0) { 151874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak return new HashSet<>(); 152874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak } 153874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak 154874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak Set<String> elements = decomposeImpl(algorithm); 155874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak 156874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak hasLoop(elements, "SHA-1", "SHA1"); 157874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak hasLoop(elements, "SHA-224", "SHA224"); 158874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak hasLoop(elements, "SHA-256", "SHA256"); 159874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak hasLoop(elements, "SHA-384", "SHA384"); 160874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak hasLoop(elements, "SHA-512", "SHA512"); 161874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak 162874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak return elements; 163874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak } 164874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak 165874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak /* 166874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak * The provided message digest algorithm name will return a consistent 167874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak * naming scheme. 168874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak */ 169874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak public static String hashName(String algorithm) { 170874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak return algorithm.replace("-", ""); 171874c25b3bc5831e286885d08a60cf0f4c75d36dcPrzemyslaw Szczepaniak } 172fb4c7d4fd77a0e37a3414b7199e0020c19acc5e5Sergio Giro} 173