• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package com.ohos.hapsigntool.utils;
17 
18 import com.ohos.hapsigntool.error.CustomException;
19 import com.ohos.hapsigntool.error.ERROR;
20 
21 import com.ohos.hapsigntool.error.SignToolErrMsg;
22 import org.bouncycastle.util.encoders.Base64;
23 
24 import java.security.Key;
25 import java.security.KeyFactory;
26 import java.security.KeyPair;
27 import java.security.KeyPairGenerator;
28 import java.security.PublicKey;
29 import java.security.PrivateKey;
30 import java.security.NoSuchAlgorithmException;
31 import java.security.spec.InvalidKeySpecException;
32 import java.security.spec.PKCS8EncodedKeySpec;
33 import java.security.spec.X509EncodedKeySpec;
34 
35 /**
36  * Key pair relation Class, to create new key pairs.
37  *
38  * @since 2021/12/28
39  */
40 public final class KeyPairTools {
41     /**
42      * Field RSA.
43      */
44     public static final String RSA = "RSA";
45 
46     /**
47      * Field EC.
48      */
49     public static final String ECC = "EC";
50 
51     /**
52      * Field ECC.
53      */
54     public static final String ECC_INPUT = "ECC";
55 
56     /**
57      * Field RSA_2048.
58      */
59     public static final int RSA_2048 = 2048;
60 
61     /**
62      * Field RSA_3072.
63      */
64     public static final int RSA_3072 = 3072;
65 
66     /**
67      * Field RSA_4096.
68      */
69     public static final int RSA_4096 = 4096;
70 
71     /**
72      * Field NIST_P_256.
73      */
74     public static final int NIST_P_256 = 256;
75 
76     /**
77      * Field NIST_P_384.
78      */
79     public static final int NIST_P_384 = 384;
80 
81     /**
82      * Logger.
83      */
84     private static final LogUtils LOGGER = new LogUtils(KeyPairTools.class);
85 
KeyPairTools()86     private KeyPairTools() {}
87 
88     /**
89      * generateKeyPair
90      *
91      * @param algorithm RSA/ECC
92      * @param keySize   RSA_2048/3072/4096 NIST_P_256/384
93      * @return Generated keypair
94      */
generateKeyPair(String algorithm, int keySize)95     public static KeyPair generateKeyPair(String algorithm, int keySize) {
96         if (algorithm == null) {
97             CustomException.throwException(ERROR.NOT_SUPPORT_ERROR, SignToolErrMsg.ALGORITHM_NOT_SUPPORT
98                     .toString("Not support algorithm: null"));
99         }
100         String alg = algorithm;
101         if (ECC_INPUT.equalsIgnoreCase(alg)) {
102             alg = ECC;
103         }
104         if (RSA.equalsIgnoreCase(alg)) {
105             ValidateUtils.throwIfNotMatches((keySize == RSA_2048 || keySize == RSA_3072 || keySize == RSA_4096),
106                     ERROR.NOT_SUPPORT_ERROR, SignToolErrMsg.ALGORITHM_NOT_SUPPORT
107                             .toString("Algorithm 'RSA' not support size: " + keySize));
108         } else if (ECC.equalsIgnoreCase(alg)) {
109             ValidateUtils.throwIfNotMatches((keySize == NIST_P_256 || keySize == NIST_P_384),
110                     ERROR.NOT_SUPPORT_ERROR, SignToolErrMsg.ALGORITHM_NOT_SUPPORT
111                             .toString("Algorithm 'ECC' not support size: " + keySize));
112         } else {
113             CustomException.throwException(ERROR.NOT_SUPPORT_ERROR, SignToolErrMsg.ALGORITHM_NOT_SUPPORT
114                     .toString("Not support algorithm: " + alg));
115         }
116 
117         try {
118             KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(alg);
119             keyPairGenerator.initialize(keySize);
120             return keyPairGenerator.generateKeyPair();
121         } catch (NoSuchAlgorithmException e) {
122             LOGGER.debug(e.getMessage(), e);
123             CustomException.throwException(ERROR.NOT_SUPPORT_ERROR, SignToolErrMsg.NO_SUCH_SIGNATURE
124                     .toString(e.getMessage()));
125             return null;
126         }
127     }
128 
129     /**
130      * Convert key to String
131      *
132      * @param key input parameter and key can not be null.
133      * @return return key.getEncoded() in Base64 format.
134      */
key2String(Key key)135     public static String key2String(Key key) {
136         return Base64.toBase64String(key.getEncoded());
137     }
138 
139     /**
140      * Convert string back to key
141      *
142      * @param algorithm input parameter and algorithm can not be null.
143      * @param keyString input parameter and keyString can not be null.
144      * @return return PublicKey.
145      */
stringToPublicKey(String algorithm, String keyString)146     public static PublicKey stringToPublicKey(String algorithm, String keyString) {
147         X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.decode(keyString));
148         PublicKey result = null;
149         try {
150             result = KeyFactory.getInstance(algorithm).generatePublic(spec);
151         } catch (InvalidKeySpecException | NoSuchAlgorithmException exception) {
152             LOGGER.debug(exception.getMessage(), exception);
153             CustomException.throwException(ERROR.ACCESS_ERROR, SignToolErrMsg.NO_SUCH_SIGNATURE
154                     .toString(exception.getMessage()));
155         }
156         return result;
157     }
158 
159     /**
160      * Convert string back to key
161      *
162      * @param algorithm input parameter and algorithm can not be null.
163      * @param keyString input parameter and keyString can not be null.
164      * @return return PrivateKey.
165      */
stringToPrivateKey(String algorithm, String keyString)166     public static PrivateKey stringToPrivateKey(String algorithm, String keyString) {
167         PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Base64.decode(keyString));
168         PrivateKey result = null;
169         try {
170             result = KeyFactory.getInstance(algorithm).generatePrivate(spec);
171         } catch (InvalidKeySpecException | NoSuchAlgorithmException exception) {
172             LOGGER.debug(exception.getMessage(), exception);
173             CustomException.throwException(ERROR.ACCESS_ERROR, SignToolErrMsg.NO_SUCH_SIGNATURE
174                     .toString(exception.getMessage()));
175         }
176         return result;
177     }
178 }
179