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 import org.apache.logging.log4j.LogManager; 21 import org.apache.logging.log4j.Logger; 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 Logger LOGGER = LogManager.getLogger(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, "Not support algorithm: null"); 98 } 99 String alg = algorithm; 100 if (ECC_INPUT.equalsIgnoreCase(alg)) { 101 alg = ECC; 102 } 103 if (RSA.equalsIgnoreCase(alg)) { 104 ValidateUtils.throwIfNotMatches((keySize == RSA_2048 || keySize == RSA_3072 || keySize == RSA_4096), 105 ERROR.NOT_SUPPORT_ERROR, "Algorithm 'RSA' not support size: " + keySize); 106 } else if (ECC.equalsIgnoreCase(alg)) { 107 ValidateUtils.throwIfNotMatches((keySize == NIST_P_256 || keySize == NIST_P_384), 108 ERROR.NOT_SUPPORT_ERROR, "Algorithm 'ECC' not support size: " + keySize); 109 } else { 110 CustomException.throwException(ERROR.NOT_SUPPORT_ERROR, "Not support algorithm: " + alg); 111 } 112 113 try { 114 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(alg); 115 keyPairGenerator.initialize(keySize); 116 return keyPairGenerator.generateKeyPair(); 117 } catch (NoSuchAlgorithmException e) { 118 LOGGER.debug(e.getMessage(), e); 119 CustomException.throwException(ERROR.NOT_SUPPORT_ERROR, e.getMessage()); 120 return null; 121 } 122 } 123 124 /** 125 * Convert key to String 126 * 127 * @param key input parameter and key can not be null. 128 * @return return key.getEncoded() in Base64 format. 129 */ key2String(Key key)130 public static String key2String(Key key) { 131 return Base64.toBase64String(key.getEncoded()); 132 } 133 134 /** 135 * Convert string back to key 136 * 137 * @param algorithm input parameter and algorithm can not be null. 138 * @param keyString input parameter and keyString can not be null. 139 * @return return PublicKey. 140 */ stringToPublicKey(String algorithm, String keyString)141 public static PublicKey stringToPublicKey(String algorithm, String keyString) { 142 X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.decode(keyString)); 143 PublicKey result = null; 144 try { 145 result = KeyFactory.getInstance(algorithm).generatePublic(spec); 146 } catch (InvalidKeySpecException | NoSuchAlgorithmException exception) { 147 LOGGER.debug(exception.getMessage(), exception); 148 CustomException.throwException(ERROR.ACCESS_ERROR, exception.getMessage()); 149 } 150 return result; 151 } 152 153 /** 154 * Convert string back to key 155 * 156 * @param algorithm input parameter and algorithm can not be null. 157 * @param keyString input parameter and keyString can not be null. 158 * @return return PrivateKey. 159 */ stringToPrivateKey(String algorithm, String keyString)160 public static PrivateKey stringToPrivateKey(String algorithm, String keyString) { 161 PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Base64.decode(keyString)); 162 PrivateKey result = null; 163 try { 164 result = KeyFactory.getInstance(algorithm).generatePrivate(spec); 165 } catch (InvalidKeySpecException | NoSuchAlgorithmException exception) { 166 LOGGER.debug(exception.getMessage(), exception); 167 CustomException.throwException(ERROR.ACCESS_ERROR, exception.getMessage()); 168 } 169 return result; 170 } 171 } 172