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.hapsigntoolcmd; 17 18 import com.ohos.hapsigntool.error.CustomException; 19 import com.ohos.hapsigntool.error.ERROR; 20 import com.ohos.hapsigntool.error.SignToolErrMsg; 21 import com.ohos.hapsigntool.utils.StringUtils; 22 import com.ohos.hapsigntool.utils.ValidateUtils; 23 24 import java.util.Arrays; 25 import java.util.List; 26 import java.util.Locale; 27 import java.util.regex.Pattern; 28 29 /** 30 * CmdUtil. 31 * 32 * @since 2021/12/28 33 */ 34 public final class CmdUtil { 35 /** 36 * Minimum length of input args. 37 */ 38 private static final int ARGS_MIN_LEN = 2; 39 40 /** 41 * Match size String. 42 */ 43 private static final Pattern INTEGER_PATTERN = Pattern.compile("\\d{1,10}"); 44 CmdUtil()45 private CmdUtil() { 46 } 47 48 /** 49 * Analyze and convert args to Params object. 50 * 51 * @param args Command line args 52 * @return Params 53 */ convert2Params(String[] args)54 public static Params convert2Params(String[] args) { 55 ValidateUtils.throwIfNotMatches(args.length >= ARGS_MIN_LEN, ERROR.COMMAND_ERROR, 56 SignToolErrMsg.PARAM_NUM_ERROR.toString()); 57 58 Params params = new Params(); 59 String method = args[0]; 60 params.setMethod(method); 61 String keyStandBy = null; 62 boolean readKey = true; 63 List<String> trustList = ParamsTrustlist.getTrustList(method); 64 if (trustList.isEmpty()) { 65 CustomException.throwException(ERROR.COMMAND_ERROR, SignToolErrMsg.UNSUPPORTED_METHOD.toString(method)); 66 } 67 for (int i = 1; i < args.length; i++) { 68 String value = args[i]; 69 if (StringUtils.isEmpty(value)) { 70 CustomException.throwException(ERROR.COMMAND_ERROR, SignToolErrMsg.PARAM_VALUE_EMPTY 71 .toString("first param")); 72 } 73 if (readKey) { 74 // prepare key 75 if (value.startsWith("-")) { 76 value = value.equals("-signcode") ? "-signCode" : value; 77 boolean isTrust = trustList.contains(value); 78 ValidateUtils.throwIfNotMatches(isTrust, 79 ERROR.COMMAND_PARAM_ERROR, SignToolErrMsg.PARAM_NOT_TRUSTED.toString()); 80 keyStandBy = value.substring(1); 81 readKey = false; 82 } else { 83 CustomException.throwException(ERROR.COMMAND_PARAM_ERROR, SignToolErrMsg 84 .PARAM_NOT_IN_PAIRS.toString()); 85 } 86 } else { 87 // prepare value 88 boolean success = validAndPutParam(params, keyStandBy, value); 89 if (success) { 90 keyStandBy = null; 91 readKey = true; 92 } 93 } 94 } 95 return params; 96 } 97 validAndPutParam(Params params, String key, String value)98 private static boolean validAndPutParam(Params params, String key, String value) { 99 boolean result; 100 if (StringUtils.isEmpty(key)) { 101 result = false; 102 } else if (StringUtils.isEmpty(value)) { 103 CustomException.throwException(ERROR.COMMAND_ERROR, 104 SignToolErrMsg.PARAM_VALUE_EMPTY.toString(key)); 105 result = false; 106 } else if (params.getOptions().containsKey(key)) { 107 CustomException.throwException(ERROR.COMMAND_ERROR, SignToolErrMsg.PARAM_DUPLICATE.toString(key)); 108 result = false; 109 } else if (key.toLowerCase(Locale.ROOT).endsWith("pwd")) { 110 params.getOptions().put(key, value.toCharArray()); 111 result = true; 112 } else { 113 params.getOptions().put(key, value); 114 result = true; 115 } 116 return result; 117 } 118 119 /** 120 * Alg type must between RSA and ECC. 121 * 122 * @param alg Incoming string 123 */ judgeAlgType(String alg)124 public static void judgeAlgType(String alg) { 125 if (!"RSA".equalsIgnoreCase(alg) && !"ECC".equalsIgnoreCase(alg)) { 126 CustomException.throwException(ERROR.COMMAND_ERROR, SignToolErrMsg.PARAM_CHECK_FAILED 127 .toString("keyAlg", "Key algorithm only allowed to be ECC or RSA.")); 128 } 129 } 130 131 /** 132 * Check whether the algorithm size is within specified scope. 133 * 134 * @param size algorithm size 135 * @param alg algorithm 136 */ judgeSize(String size, String alg)137 public static void judgeSize(String size, String alg) { 138 String[] array = {"2048", "3072", "4096", "NIST-P-256", "NIST-P-384"}; 139 List<String> arrayList = Arrays.asList(array); 140 if (!arrayList.contains(size)) { 141 CustomException.throwException(ERROR.COMMAND_ERROR, SignToolErrMsg.PARAM_CHECK_FAILED 142 .toString("KeySize", "Key size include in set of " + arrayList)); 143 } 144 145 if ("RSA".equalsIgnoreCase(alg)) { 146 if (!"2048".equals(size) && !"3072".equals(size) && !"4096".equals(size)) { 147 CustomException.throwException(ERROR.COMMAND_ERROR, SignToolErrMsg.PARAM_CHECK_FAILED 148 .toString("KeySize", "Key size of RSA include in set of {2048, 3072, 4096}")); 149 } 150 } else { 151 if (!"NIST-P-256".equalsIgnoreCase(size) && !"NIST-P-384".equalsIgnoreCase(size)) { 152 CustomException.throwException(ERROR.COMMAND_ERROR, SignToolErrMsg.PARAM_CHECK_FAILED 153 .toString("KeySize", "Key size include in set of " + arrayList)); 154 } 155 } 156 } 157 158 /** 159 * Check whether the signature algorithm is within specified scope. 160 * 161 * @param signAlg signature algorithm 162 */ judgeSignAlgType(String signAlg)163 public static void judgeSignAlgType(String signAlg) { 164 List<String> arrayList = Arrays.asList("SHA256withRSA", "SHA384withRSA", "SHA256withECDSA", 165 "SHA384withECDSA"); 166 if (!arrayList.contains(signAlg)) { 167 CustomException.throwException(ERROR.COMMAND_ERROR, SignToolErrMsg.PARAM_CHECK_FAILED 168 .toString("SignAlg", "signature algorithms include " + arrayList)); 169 } 170 } 171 172 /** 173 * Check whether the signature algorithm is within specified scope. 174 * 175 * @param signAlg signature algorithm 176 */ judgeEndSignAlgType(String signAlg)177 public static void judgeEndSignAlgType(String signAlg) { 178 List<String> arrayList = Arrays.asList("SHA256withECDSA", "SHA384withECDSA"); 179 if (!arrayList.contains(signAlg)) { 180 CustomException.throwException(ERROR.COMMAND_ERROR, SignToolErrMsg.PARAM_CHECK_FAILED 181 .toString("SignAlg", "signature algorithms include SHA256withECDSA,SHA384withECDSA")); 182 } 183 } 184 185 /** 186 * Verify target type. 187 * 188 * @param inputType Types with ',' 189 * @param supportTypes Target types with ',' 190 */ verifyType(String inputType, String supportTypes)191 public static void verifyType(String inputType, String supportTypes) { 192 String[] types = inputType.split(","); 193 List<String> supportList = Arrays.asList(supportTypes.split(",")); 194 for (String type : types) { 195 if (StringUtils.isEmpty(type)) { 196 continue; 197 } 198 if (!supportList.contains(type.trim())) { 199 CustomException.throwException(ERROR.COMMAND_ERROR, SignToolErrMsg 200 .PARAM_NOT_TRUSTED.toString(inputType)); 201 } 202 } 203 } 204 205 /** 206 * Convert passed in args to 'integer'. 207 * 208 * @param size String passed in 209 * @return 'integer' String 210 */ convertAlgSize(String size)211 public static String convertAlgSize(String size) { 212 if (size.startsWith("NIST-P-")) { 213 return size.replace("NIST-P-", ""); 214 } else if (INTEGER_PATTERN.matcher(size).matches()) { 215 return size; 216 } else { 217 CustomException.throwException(ERROR.COMMAND_ERROR, SignToolErrMsg.PARAM_CHECK_FAILED 218 .toString("KeySize", "Key size is incorrect")); 219 return size; 220 } 221 } 222 223 /** 224 * Command parameter constant 225 * 226 */ 227 public static final class Method { 228 /** 229 * Generate app cert method name. 230 */ 231 public static final String GENERATE_APP_CERT = "generate-app-cert"; 232 233 /** 234 * Generate ca method name. 235 */ 236 public static final String GENERATE_CA = "generate-ca"; 237 238 /** 239 * Generate cert method name. 240 */ 241 public static final String GENERATE_CERT = "generate-cert"; 242 243 /** 244 * Generate csr method name. 245 */ 246 public static final String GENERATE_CSR = "generate-csr"; 247 248 /** 249 * Generate key pair method name. 250 */ 251 public static final String GENERATE_KEYPAIR = "generate-keypair"; 252 253 /** 254 * Generate profile cert method name. 255 */ 256 public static final String GENERATE_PROFILE_CERT = "generate-profile-cert"; 257 258 /** 259 * Sign app method name. 260 */ 261 public static final String SIGN_APP = "sign-app"; 262 263 /** 264 * Sign profile method name. 265 */ 266 public static final String SIGN_PROFILE = "sign-profile"; 267 268 /** 269 * Verify app method name. 270 */ 271 public static final String VERIFY_APP = "verify-app"; 272 273 /** 274 * Verify profile method name. 275 */ 276 public static final String VERIFY_PROFILE = "verify-profile"; 277 } 278 } 279