1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tools.build.apkzlib.sign; 18 19 import java.security.NoSuchAlgorithmException; 20 import javax.annotation.Nonnull; 21 22 /** 23 * Signature algorithm. 24 */ 25 public enum SignatureAlgorithm { 26 /** RSA algorithm. */ 27 RSA("RSA", 1, "withRSA"), 28 29 /** ECDSA algorithm. */ 30 ECDSA("EC", 18, "withECDSA"), 31 32 /** DSA algorithm. */ 33 DSA("DSA", 1, "withDSA"); 34 35 /** Name of the private key as reported by {@code PrivateKey}. */ 36 @Nonnull public final String keyAlgorithm; 37 38 /** 39 * Minimum SDK version that allows this signature. 40 */ 41 public final int minSdkVersion; 42 43 /** 44 * Suffix appended to digest algorithm to obtain signature algorithm. 45 */ 46 @Nonnull 47 public final String signatureAlgorithmSuffix; 48 49 /** 50 * Creates a new signature algorithm. 51 * 52 * @param keyAlgorithm the name as reported by {@code PrivateKey} 53 * @param minSdkVersion minimum SDK version that allows this signature 54 * @param signatureAlgorithmSuffix suffix for signature name with used with a digest 55 */ 56 SignatureAlgorithm( 57 @Nonnull String keyAlgorithm, int minSdkVersion, @Nonnull String signatureAlgorithmSuffix) { 58 this.keyAlgorithm = keyAlgorithm; 59 this.minSdkVersion = minSdkVersion; 60 this.signatureAlgorithmSuffix = signatureAlgorithmSuffix; 61 } 62 63 /** 64 * Obtains the signature algorithm that corresponds to a private key name applicable to a 65 * SDK version. 66 * 67 * @param keyAlgorithm the named referred in the {@code PrivateKey} 68 * @param minSdkVersion minimum SDK version to run 69 * @return the algorithm that has {@link #keyAlgorithm} equal to {@code keyAlgorithm} 70 * @throws NoSuchAlgorithmException if no algorithm was found for the given private key; an 71 * algorithm was found but is not applicable to the given SDK version 72 */ 73 @Nonnull 74 public static SignatureAlgorithm fromKeyAlgorithm(@Nonnull String keyAlgorithm, 75 int minSdkVersion) throws NoSuchAlgorithmException { 76 for (SignatureAlgorithm alg : values()) { 77 if (alg.keyAlgorithm.equalsIgnoreCase(keyAlgorithm)) { 78 if (alg.minSdkVersion > minSdkVersion) { 79 throw new NoSuchAlgorithmException("Signatures with " + keyAlgorithm 80 + " keys are not supported on minSdkVersion " + minSdkVersion 81 + ". They are supported only for minSdkVersion >= " 82 + alg.minSdkVersion); 83 } 84 85 return alg; 86 } 87 } 88 89 throw new NoSuchAlgorithmException("Signing with " + keyAlgorithm 90 + " keys is not supported"); 91 } 92 93 /** 94 * Obtains the name of the signature algorithm when used with a digest algorithm. 95 * 96 * @param digestAlgorithm the digest algorithm to use 97 * @return the name of the signature algorithm 98 */ 99 @Nonnull 100 public String signatureAlgorithmName(@Nonnull DigestAlgorithm digestAlgorithm) { 101 return digestAlgorithm.messageDigestName.replace("-", "") + signatureAlgorithmSuffix; 102 } 103 } 104