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 { KeyPairTools()41 private KeyPairTools() { 42 } 43 44 /** 45 * Field RSA. 46 */ 47 public static final String RSA = "RSA"; 48 49 /** 50 * Field EC. 51 */ 52 public static final String ECC = "EC"; 53 54 /** 55 * Field ECC. 56 */ 57 public static final String ECC_INPUT = "ECC"; 58 59 /** 60 * Field RSA_2048. 61 */ 62 public static final int RSA_2048 = 2048; 63 64 /** 65 * Field RSA_3072. 66 */ 67 public static final int RSA_3072 = 3072; 68 69 /** 70 * Field RSA_4096. 71 */ 72 public static final int RSA_4096 = 4096; 73 74 /** 75 * Field NIST_P_256. 76 */ 77 public static final int NIST_P_256 = 256; 78 79 /** 80 * Field NIST_P_384. 81 */ 82 public static final int NIST_P_384 = 384; 83 84 /** 85 * Logger. 86 */ 87 private static final Logger LOGGER = LogManager.getLogger(KeyPairTools.class); 88 89 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.equalsIgnoreCase(ECC_INPUT)) { 97 algorithm = ECC; 98 } 99 if (algorithm.equalsIgnoreCase(RSA)) { 100 ValidateUtils.throwIfNotMatches((keySize == RSA_2048 || keySize == RSA_3072 || keySize == RSA_4096), 101 ERROR.NOT_SUPPORT_ERROR, "Algorithm 'RSA' not support size: " + keySize); 102 } else if (algorithm.equalsIgnoreCase(ECC)) { 103 ValidateUtils.throwIfNotMatches((keySize == NIST_P_256 || keySize == NIST_P_384), 104 ERROR.NOT_SUPPORT_ERROR, "Algorithm 'ECC' not support size: " + keySize); 105 } else { 106 CustomException.throwException(ERROR.NOT_SUPPORT_ERROR, "Not support algorithm: " + algorithm); 107 } 108 109 try { 110 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm); 111 keyPairGenerator.initialize(keySize); 112 return keyPairGenerator.generateKeyPair(); 113 } catch (NoSuchAlgorithmException e) { 114 LOGGER.debug(e.getMessage(), e); 115 CustomException.throwException(ERROR.NOT_SUPPORT_ERROR, e.getMessage()); 116 return null; 117 } 118 } 119 120 /** 121 * Convert key to String 122 * 123 * @param key input parameter and key can not be null. 124 * @return return key.getEncoded() in Base64 format. 125 */ key2String(Key key)126 public static String key2String(Key key) { 127 return Base64.toBase64String(key.getEncoded()); 128 } 129 130 /** 131 * Convert string back to key 132 * 133 * @param algorithm input parameter and algorithm can not be null. 134 * @param keyString input parameter and keyString can not be null. 135 * @return return PublicKey. 136 */ stringToPublicKey(String algorithm, String keyString)137 public static PublicKey stringToPublicKey(String algorithm, String keyString) { 138 X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.decode(keyString)); 139 PublicKey result = null; 140 try { 141 result = KeyFactory.getInstance(algorithm).generatePublic(spec); 142 } catch (InvalidKeySpecException | NoSuchAlgorithmException exception) { 143 LOGGER.debug(exception.getMessage(), exception); 144 CustomException.throwException(ERROR.ACCESS_ERROR, exception.getMessage()); 145 } 146 return result; 147 } 148 149 /** 150 * Convert string back to key 151 * 152 * @param algorithm input parameter and algorithm can not be null. 153 * @param keyString input parameter and keyString can not be null. 154 * @return return PrivateKey. 155 */ stringToPrivateKey(String algorithm, String keyString)156 public static PrivateKey stringToPrivateKey(String algorithm, String keyString) { 157 PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Base64.decode(keyString)); 158 PrivateKey result = null; 159 try { 160 result = KeyFactory.getInstance(algorithm).generatePrivate(spec); 161 } catch (InvalidKeySpecException | NoSuchAlgorithmException exception) { 162 LOGGER.debug(exception.getMessage(), exception); 163 CustomException.throwException(ERROR.ACCESS_ERROR, exception.getMessage()); 164 } 165 return result; 166 } 167 } 168