相关源码开源地址:研发人员加班打包创建中...
核心加密算法:
数字签名密钥算法:ECDSA,
椭圆曲线(EC)域参数设定:secp256k(比特币选择的也是该算法),
数字签名签名/验证算法:SHA512withECDSA;
Hash算法:SHA256、RIPEMD160算法(RACE原始完整性校验讯息摘要);
私钥说明
私钥字节总长度:144位(后68位为公钥的动态字节b)
例如私钥字节:
[48, -127, -115, 2, 1, 0, 48, 16, 6, 7, 42, -122, 72, -50, 61, 2, 1, 6, 5, 43, -127, 4, 0, 10, 4, 118, 48, 116, 2, 1, 1, 4, 32, 111, 96, -19, 42, -3, -105, -91, -46, -79, -82, -79, 108, 96, -37, 91, -23, -40, 102, -114, 2, 67, -70, -100, 102, 90, -29, -127, -120, 125, 66, -11, -90, -96, 7, 6, 5, 43, -127, 4, 0, 10, -95, 68, 3, 66, 0, 4, 88, -23, 4, 81, 31, 69, 102, 52, 32, -73, 15, -48, 56, -120, -58, 49, -34, 67, 76, 47, -73, 74, 123, -22, -67, 82, -125, -42, 108, 24, 116, 88, -88, 53, 105, 78, 123, -13, 116, 40, -92, 47, 1, 54, 101, -63, -125, 26, 22, 29, -120, -32, -89, -36, -107, -27, -119, -18, -77, -71, 69, 103, 47, 63]
转换为字符串:30818d020100301006072a8648ce3d020106052b8104000a0476307402010104206f60ed2afd97a5d2b1aeb16c60db5be9d8668e0243ba9c665ae381887d42f5a6a00706052b8104000aa1440342000458e904511f45663420b70fd03888c631de434c2fb74a7beabd5283d66c187458a835694e7bf37428a42f013665c1831a161d88e0a7dc95e589eeb3b945672f3f
公钥说明
公钥字节总长度:88位(前20位为固定字节a,后68位为公钥动态字节b)
例如公钥字节:
[48, 86, 48, 16, 6, 7, 42, -122, 72, -50, 61, 2, 1, 6, 5, 43, -127, 4, 0, 10, 3, 66, 0, 4, 88, -23, 4, 81, 31, 69, 102, 52, 32, -73, 15, -48, 56, -120, -58, 49, -34, 67, 76, 47, -73, 74, 123, -22, -67, 82, -125, -42, 108, 24, 116, 88, -88, 53, 105, 78, 123, -13, 116, 40, -92, 47, 1, 54, 101, -63, -125, 26, 22, 29, -120, -32, -89, -36, -107, -27, -119, -18, -77, -71, 69, 103, 47, 63]
其中:48, 86, 48, 16, 6, 7, 42, -122, 72, -50, 61, 2, 1, 6, 5, 43, -127, 4, 0, 10 为固定的公钥前缀。为椭圆算法密钥对的算法标识、以及主编码格式标识。
转换为字符串:3056301006072a8648ce3d020106052b8104000a0342000458e904511f45663420b70fd03888c631de434c2fb74a7beabd5283d66c187458a835694e7bf37428a42f013665c1831a161d88e0a7dc95e589eeb3b945672f3f
部分展示代码
创建新的密钥对
/**
* 创建新的密钥对
* @return
*/
public static KeyPair newECKeyPair() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException {
// 注册 BC Provider
Security.addProvider(new BouncyCastleProvider());
// 创建椭圆曲线算法的密钥对生成器,算法为 ECDSA
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM, BouncyCastleProvider.PROVIDER_NAME);
// 椭圆曲线(EC)域参数设定
ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(EC_PARAMETER_SPEC);
//使用给定的参数集和随机源初始化密钥对生成器,生成公私钥
keyPairGenerator.initialize(ecSpec, new SecureRandom());
return keyPairGenerator.generateKeyPair();
}
通过密钥对获取到公私钥字节
KeyPair keyPair = ECDSAUtils.newECKeyPair();
//获取私钥
BCECPrivateKey privateKey = (BCECPrivateKey) keyPair.getPrivate();
//获取公钥
BCECPublicKey publicKey = (BCECPublicKey) keyPair.getPublic();
//获取到私钥字节
this.setPrivateKey(ECDSAUtils.getBytesByKey(privateKey));
//获取到公钥字节
this.setPublicKey(ECDSAUtils.getBytesByKey(publicKey));
通过公私钥字节获取到公私钥字符串
字节数组转16进制字符串
/**
* 公钥
* @return
*/
public String getPublicKeyStr(){
return ByteUtils.bytesToHexString(this.publicKey);
}
/**
* 私钥
* @return
*/
public String getPrivateKeyStr(){
return ByteUtils.bytesToHexString(this.privateKey);
}
通过公私钥字符串获取到公私钥字节
/**
* 通过公钥字符串获取公钥字节
* @param pubKeyStr 公钥字符串
* @return 公钥字节
*/
public static byte[] getPubkeyByPubkeyStr(String pubKeyStr) {
return ByteUtils.hexStringToByte(pubKeyStr);
}
/**
* 通过私钥字符串获取私钥字节
* @param privateKeyStr 私钥字符串
* @return 私钥字节
*/
public static byte[] getPrivateKeyByPrivateKeyStr(String privateKeyStr) {
return ByteUtils.hexStringToByte(privateKeyStr);
}
通过公钥字节生成公钥Hash
/**
* ripeMD160Hash
* 计算公钥的 RIPEMD160 Hash值
* 通过公钥获取到公钥Hash
* 获取公钥hash
* @param pubKey 公钥
* @return ipeMD160Hash(sha256 ( pubkey))
*/
public static byte[] getPubkeyHashByPubkey(byte[] pubKey) {
//1. 先对公钥做 sha256 处理
byte[] shaHashedKey = DigestUtils.sha256(pubKey);
RIPEMD160Digest ripemd160 = new RIPEMD160Digest();
ripemd160.update(shaHashedKey, 0, shaHashedKey.length);
byte[] output = new byte[ripemd160.getDigestSize()];
ripemd160.doFinal(output, 0);
return output;
}
通过公钥Hash生成地址
通过算法保证绝对不可能通过地址推算出公钥。
/**
* 通过公钥字节获取钱包地址
* @param pubkeyHashBytes
* @return
*/
private static String getAddressByPubkeyHash(byte[] pubkeyHashBytes) {
try {
// 2. 添加版本 0x00
ByteArrayOutputStream addrStream = new ByteArrayOutputStream();
addrStream.write((byte) 0);
addrStream.write(pubkeyHashBytes);
byte[] versionedPayload = addrStream.toByteArray();
// 3. 计算校验码
byte[] checksum = Wallet.checksum(versionedPayload);
// 4. 得到 version + paylod + checksum 的组合
addrStream.write(checksum);
byte[] binaryAddress = addrStream.toByteArray();
// 5. 执行Base58转换处理
return Base58Check.rawBytesToBase58(binaryAddress);
} catch (Exception e) {
log.error("通过公钥获取钱包失败",e);
throw new ServiceException("错误的公钥地址");
}
}
通过私钥字节推导出公钥字节
/**
* 通过私钥字节获取公钥字节
* @param privateKeyBytes 私钥字节
* @return 公钥字节
*/
public static byte[] getPubkeyByteByPrivateKey(byte[] privateKeyBytes){
byte[] pubkey = new byte[88];
pubkey[0]=48;
pubkey[1]=86;
System.arraycopy(privateKeyBytes, 6, pubkey, 2, 18);
System.arraycopy(privateKeyBytes, 76, pubkey, 20, 68);
return pubkey;
}
公钥、公钥Hash、地址之间的关系:
私钥->公钥->公钥Hash->地址(注意:无法反向推导) .