Home | History | Annotate | Download | only in sign
      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