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.key; 17 18 import com.ohos.hapsigntool.api.ServiceApi; 19 import com.ohos.hapsigntool.error.CustomException; 20 import com.ohos.hapsigntool.error.ERROR; 21 import com.ohos.hapsigntool.utils.ValidateUtils; 22 import org.apache.logging.log4j.LogManager; 23 import org.apache.logging.log4j.Logger; 24 import org.bouncycastle.util.encoders.Base64; 25 26 import java.security.Key; 27 import java.security.KeyFactory; 28 import java.security.KeyPair; 29 import java.security.KeyPairGenerator; 30 import java.security.PublicKey; 31 import java.security.PrivateKey; 32 import java.security.NoSuchAlgorithmException; 33 import java.security.spec.InvalidKeySpecException; 34 import java.security.spec.PKCS8EncodedKeySpec; 35 import java.security.spec.X509EncodedKeySpec; 36 37 /** 38 * Key pair relation Class, to create new key pairs. 39 * 40 * @since 2021/12/28 41 */ 42 public final class KeyPairTools { KeyPairTools()43 private KeyPairTools() { 44 } 45 46 /** 47 * Field RSA. 48 */ 49 public static final String RSA = "RSA"; 50 51 /** 52 * Field EC. 53 */ 54 public static final String ECC = "EC"; 55 56 /** 57 * Field ECC. 58 */ 59 public static final String ECC_INPUT = "ECC"; 60 61 /** 62 * Field RSA_2048. 63 */ 64 public static final int RSA_2048 = 2048; 65 66 /** 67 * Field RSA_3072. 68 */ 69 public static final int RSA_3072 = 3072; 70 71 /** 72 * Field RSA_4096. 73 */ 74 public static final int RSA_4096 = 4096; 75 76 /** 77 * Field NIST_P_256. 78 */ 79 public static final int NIST_P_256 = 256; 80 81 /** 82 * Field NIST_P_384. 83 */ 84 public static final int NIST_P_384 = 384; 85 86 /** 87 * Logger. 88 */ 89 private static final Logger LOGGER = LogManager.getLogger(ServiceApi.class); 90 91 92 /** 93 * @param algorithm RSA/ECC 94 * @param keySize RSA_2048/3072/4096 NIST_P_256/384 95 * @return Generated keypair 96 */ generateKeyPair(String algorithm, int keySize)97 public static KeyPair generateKeyPair(String algorithm, int keySize) { 98 if (algorithm.equalsIgnoreCase(ECC_INPUT)) { 99 algorithm = ECC; 100 } 101 if (algorithm.equalsIgnoreCase(RSA)) { 102 ValidateUtils.throwIfNotMatches((keySize == RSA_2048 || keySize == RSA_3072 || keySize == RSA_4096), 103 ERROR.NOT_SUPPORT_ERROR, "Algorithm 'RSA' not support size: " + keySize); 104 } else if (algorithm.equalsIgnoreCase(ECC)) { 105 ValidateUtils.throwIfNotMatches((keySize == NIST_P_256 || keySize == NIST_P_384), 106 ERROR.NOT_SUPPORT_ERROR, "Algorithm 'ECC' not support size: " + keySize); 107 } else { 108 CustomException.throwException(ERROR.NOT_SUPPORT_ERROR, "Not support algorithm: " + algorithm); 109 } 110 111 try { 112 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm); 113 keyPairGenerator.initialize(keySize); 114 return keyPairGenerator.generateKeyPair(); 115 } catch (NoSuchAlgorithmException e) { 116 LOGGER.debug(e.getMessage(), e); 117 CustomException.throwException(ERROR.NOT_SUPPORT_ERROR, e.getMessage()); 118 return null; 119 } 120 } 121 122 /** 123 * Convert key to String 124 * 125 * @param key input parameter and key can not be null. 126 * @return return key.getEncoded() in Base64 format. 127 */ key2String(Key key)128 public static String key2String(Key key) { 129 return Base64.toBase64String(key.getEncoded()); 130 } 131 132 /** 133 * Convert string back to key 134 * 135 * @param algorithm input parameter and algorithm can not be null. 136 * @param keyString input parameter and keyString can not be null. 137 * @return return PublicKey. 138 */ stringToPublicKey(String algorithm, String keyString)139 public static PublicKey stringToPublicKey(String algorithm, String keyString) { 140 X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.decode(keyString)); 141 PublicKey result = null; 142 try { 143 result = KeyFactory.getInstance(algorithm).generatePublic(spec); 144 } catch (InvalidKeySpecException | NoSuchAlgorithmException exception) { 145 LOGGER.debug(exception.getMessage(), exception); 146 CustomException.throwException(ERROR.ACCESS_ERROR, exception.getMessage()); 147 } 148 return result; 149 } 150 151 /** 152 * Convert string back to key 153 * 154 * @param algorithm input parameter and algorithm can not be null. 155 * @param keyString input parameter and keyString can not be null. 156 * @return return PrivateKey. 157 */ stringToPrivateKey(String algorithm, String keyString)158 public static PrivateKey stringToPrivateKey(String algorithm, String keyString) { 159 PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Base64.decode(keyString)); 160 PrivateKey result = null; 161 try { 162 result = KeyFactory.getInstance(algorithm).generatePrivate(spec); 163 } catch (InvalidKeySpecException | NoSuchAlgorithmException exception) { 164 LOGGER.debug(exception.getMessage(), exception); 165 CustomException.throwException(ERROR.ACCESS_ERROR, exception.getMessage()); 166 } 167 return result; 168 } 169 } 170