package com.xiaopeng.map.utils;
|
|
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Hex;
|
import org.apache.commons.lang.RandomStringUtils;
|
import org.bouncycastle.openssl.PEMKeyPair;
|
import org.bouncycastle.openssl.PEMParser;
|
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
|
import org.bouncycastle.util.io.pem.PemReader;
|
|
import java.io.*;
|
import java.math.BigInteger;
|
import java.security.*;
|
import java.security.interfaces.ECPrivateKey;
|
import java.security.interfaces.ECPublicKey;
|
import java.security.spec.*;
|
import java.util.UUID;
|
|
/**
|
* @author chenjl
|
* @date 2020/6/3
|
*/
|
public class VehicleCodec {
|
static {
|
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
|
}
|
|
/**
|
* 获得一个UUID
|
*
|
* @return String UUID
|
*/
|
public static String getUUID() {
|
String s = UUID.randomUUID().toString();
|
// 去掉“-”符号
|
return s.substring(0, 8) + s.substring(9, 13) + s.substring(14, 18) + s.substring(19, 23) + s.substring(24);
|
}
|
|
/**
|
* 生成序列号
|
* @return
|
*/
|
public static String generateSn() {
|
return String.join("-",
|
RandomStringUtils.randomAlphanumeric(4),
|
RandomStringUtils.randomAlphanumeric(4),
|
RandomStringUtils.randomAlphanumeric(4),
|
RandomStringUtils.randomAlphanumeric(4)).toUpperCase();
|
}
|
|
/**
|
* Encode binary data to base64
|
*
|
* @param value
|
* The binary data
|
* @return The base64 encoded String
|
*/
|
public static String encodeBASE64(byte[] value) {
|
return new String(Base64.encodeBase64(value));
|
}
|
|
/**
|
* Decode a base64 value
|
*
|
* @param value
|
* The base64 encoded String
|
* @return decoded binary data
|
* @throws UnsupportedEncodingException
|
*/
|
public static byte[] decodeBASE64(String value) {
|
try {
|
return Base64.decodeBase64(value.getBytes("utf-8"));
|
} catch (UnsupportedEncodingException ex) {
|
throw new IllegalArgumentException(ex);
|
}
|
}
|
|
/**
|
* ECDSA签名
|
* @param data 明文
|
* @param ecPrivateKey EC私钥
|
* @return 签名byte[]
|
* @throws Exception
|
*/
|
public static String sign(byte[] data, ECPrivateKey ecPrivateKey) throws Exception {
|
Signature signature = Signature.getInstance("SHA256withECDSA", "BC");
|
signature.initSign(ecPrivateKey);
|
signature.update(data);
|
return encodeBASE64(signature.sign());
|
}
|
|
/**
|
* ECDSA 验签
|
* @param data 明文
|
* @param sign 签名byte[]
|
* @param ecPublicKey EC公钥
|
* @return 通过-true,失败-false
|
* @throws Exception
|
*/
|
public static boolean verify(byte[] data, String sign, ECPublicKey ecPublicKey) throws Exception {
|
Signature signature = Signature.getInstance("SHA256withECDSA", "BC");
|
signature.initVerify(ecPublicKey);
|
signature.update(data);
|
return signature.verify(decodeBASE64(sign));
|
}
|
|
/**
|
* 根据X和Y,得到EC公钥
|
* @param publicKeyXBase64
|
* @param publicKeyYBase64
|
* @return
|
* @throws NoSuchAlgorithmException
|
* @throws InvalidParameterSpecException
|
* @throws InvalidKeySpecException
|
*/
|
public static ECPublicKey getECPublicKeyFromPoint(String publicKeyXBase64, String publicKeyYBase64) throws NoSuchAlgorithmException, InvalidParameterSpecException, InvalidKeySpecException {
|
byte[] xkeyBytes = decodeBASE64(publicKeyXBase64);
|
byte[] ykeyBytes = decodeBASE64(publicKeyYBase64);
|
|
KeyFactory keyFactory = KeyFactory.getInstance("ECDSA");
|
|
ECPoint pubPoint = new ECPoint(new BigInteger(1, xkeyBytes), new BigInteger(1, ykeyBytes));
|
AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC");
|
parameters.init(new ECGenParameterSpec("secp256k1"));
|
ECParameterSpec ecParameters = parameters.getParameterSpec(ECParameterSpec.class);
|
ECPublicKeySpec pubSpec = new ECPublicKeySpec(pubPoint, ecParameters);
|
|
return (ECPublicKey) keyFactory.generatePublic(pubSpec);
|
}
|
|
|
/**
|
* 获取ECPrivateKey对象
|
* @param privateKeyBase64
|
* @return
|
* @throws NoSuchAlgorithmException
|
* @throws InvalidKeySpecException
|
*/
|
public static ECPrivateKey getECPrivateKey(String privateKeyBase64) throws NoSuchAlgorithmException, InvalidKeySpecException {
|
byte[] keyBytes = decodeBASE64(privateKeyBase64);
|
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
|
KeyFactory keyFactory = KeyFactory.getInstance("EC");
|
|
return (ECPrivateKey) keyFactory
|
.generatePrivate(pkcs8KeySpec);
|
}
|
|
|
/**
|
* 从KEY文件解析KeyPair
|
* @param pemFile
|
* @return
|
* @throws IOException
|
*/
|
public static KeyPair parsePEMFile(File pemFile) throws IOException {
|
if (!pemFile.isFile() || !pemFile.exists()) {
|
throw new FileNotFoundException(String.format("The file '%s' doesn't exist.", pemFile.getAbsolutePath()));
|
}
|
PemReader reader = new PemReader(new FileReader(pemFile));
|
PEMKeyPair pemKeyPair;
|
try (PEMParser pemParser = new PEMParser(reader)) {
|
reader.readPemObject();
|
pemKeyPair = (PEMKeyPair) pemParser.readObject();
|
return new JcaPEMKeyConverter().getKeyPair(pemKeyPair);
|
} catch (Exception e) {
|
//ignore
|
}
|
return null;
|
}
|
|
/**
|
* Write a byte array as hexadecimal String.
|
*/
|
public static String byteToHexString(byte[] bytes) {
|
return String.valueOf(Hex.encodeHex(bytes));
|
}
|
|
/**
|
* Build an hexadecimal MD5 hash for a String
|
*
|
* @param value
|
* The String to hash
|
* @return An hexadecimal Hash
|
* @throws Exception
|
*/
|
public static String hexMD5(String value) {
|
try {
|
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
|
messageDigest.reset();
|
messageDigest.update(value.getBytes("utf-8"));
|
byte[] digest = messageDigest.digest();
|
return byteToHexString(digest);
|
} catch (Exception ex) {
|
throw new IllegalArgumentException(ex);
|
}
|
}
|
|
|
|
/**
|
* VIN 转UUID
|
* @param vin 车架号
|
* @param salt1 盐1
|
* @param salt2 盐2
|
* @return
|
*/
|
public static String vinToUUID(String vin, String salt1, String salt2) {
|
return hexMD5(hexMD5(vin + salt1) + salt2).toUpperCase();
|
}
|
|
/**
|
* 将字节数组转换成16进制字符串
|
*/
|
public static String encodeHexStr(final byte[] bytes){
|
if (bytes == null) {
|
return null;
|
}
|
char[] digital = "0123456789ABCDEF".toCharArray();
|
char[] result = new char[bytes.length * 2];
|
for (int i = 0; i < bytes.length; i++) {
|
result[i * 2] = digital[(bytes[i] & 0xf0) >> 4];
|
result[i * 2 + 1] = digital[bytes[i] & 0x0f];
|
}
|
return new String(result);
|
}
|
|
/**
|
* 检查是否VIN
|
* @param vin
|
* @return
|
*/
|
public static boolean isVin(String vin) {
|
return vin.length() == 17 && vin.charAt(0) == 'L';
|
}
|
|
|
}
|