bitcoinj库的Hex类型私钥生成公钥java实现-sawtooth的keygen相关代码java实现

分析

  • 我们在使用hyperledger sawtooth平台的时候,需要使用keygen这一个sawtooth的cli程序去创建一对密钥对,在hyperledger sawtooth中,该过程是使用一个特定的随机函数,生成一个私钥,再执行Secp256k1椭圆曲线算法,根据私钥导出公钥
  • 我在使用sawtooth的java sdk时候遇到了这样的问题,首先java的sdk 源码(https://github.com/hyperledger/sawtooth-sdk-java)

    • 在sdk的example代码,调用了如下两个函数:

      1
      2
      3
      4
      5
      6
      7
      public static ECKey readWif(String wif) {
      return DumpedPrivateKey.fromBase58(MAINNET, wif).getKey();
      }

      public static String getPublicKey(ECKey privateKey) {
      return ECKey.fromPrivate(privateKey.getPrivKey(), true).getPublicKeyAsHex();
      }
    • 并且按照example给出的测试集其中一对公钥私钥如下:

      1
      2
      私钥: 5JkisHAXScTk6Tah9jq9S5B4ByiputRjnKnQrF6k1uBLBQAD8Mi 
      公钥: 03bc976dc770b84decb90abeb94364c6368da051a9417cc4046f9f478d995b2ba7

      按照以上的调用,通过readWif(String wif) 把私钥导入,确实能够生成以上对应的公钥,也证明了bitcoinj库是没有任何问题

    • 同时我是用sawtooth自带的keygen工具去生成密钥对时候发现,sawtooth自带的生成公钥和私钥长度和以上测试用例的不一样,具体如下:

      1
      2
      私钥 :'20f34219eed055a8292767876e97cedc681cdee65f8d100f0c192d0b61cb13d6' 
      公钥 :'02fe868857f1dcb31137b34c55cf1b6e031447b5fe7902e49a083eaf95c54aaecf'
  • 通过分析我们发现,example给出的例子使用的经过了base58编码的公私密钥对,而sawtooth原生的keygen则没有采用base58编码。因此如果使用java的bitcoinj库现有的方法能生成sawtooth keygen格式的公钥私钥对呢?这个就是本文的一个重点。

解决方法:

  1. 我们首先观察example里面的Signing 类,发现里面调用的方法都是来自于ECKey这个类的,通过分析,首先在ECKey类里面的私钥都是使用BigInteger表示的,而我们sawtooth keygen生成的私钥是16位Hex格式的String
  2. 因此我们需要使用方法把导入的String从16位Hex读入再变成BigInteger对象,再使用ECKey的fromPrivate((BigInteger privKey)方法,由BigInteger对象生成一个ECKey的对象。
    具体的fromPrivate()方法如下:
    1
    2
    3
    public static ECKey fromPrivate(BigInteger privKey) {
    return fromPrivate(privKey, true);
    }
  3. 最后通过getPublicKeyAsHex()方法即可得到由16位hex编码的String 公钥

具体实现代码:

getPublicKeyFromHex()
1
2
3
4
5
public static String getPublicKeyFromHex(String key){
BigInteger privateKeyBigInt = new BigInteger(key,16);
ECKey privateKey = ECKey.fromPrivate(privateKeyBigInt);
return privateKey.getPublicKeyAsHex();
}

实现的例子:

main.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import org.bitcoinj.core.ECKey;
import java.math.BigInteger;

public class main {
public static String getPublicKeyFromHex(String key){
BigInteger privateKeyBigInt = new BigInteger(key,16);
ECKey privateKey = ECKey.fromPrivate(privateKeyBigInt);
return privateKey.getPublicKeyAsHex();
}

public static void main(String[] args) {

//此处我输入我上文提到的公钥
String privateKeyStr = "20f34219eed055a8292767876e97cedc681cdee65f8d100f0c192d0b61cb13d6";
System.out.println(getPublicKeyFromHex(privateKeyStr));
}
}
  • 程序执行结果:
    程序执行结果
    1
    02fe868857f1dcb31137b34c55cf1b6e031447b5fe7902e49a083eaf95c54aaecf
  • 我们成功的使用java实现了sawtooth自带的keygen功能,除了keygen的通过随机数生成privatekey外,我们已经实现了把keygen生成的私钥生成回sawtooth keygen兼容的公钥格式
生活再忙,也不要忘记生活原本简单的样子
0%