Address
Examples showing how to integrate Bitcoin with the TSM
The example uses two btcsuite library dependencies, to create a Bitcoin address. You need to have access to an ECDSA Client, which is connected to the TSM, as shown here https://docs.sepior.com/docs/tsm-sdk.
import (
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcutil"
)
curveName := "secp256k1"
keyID, err := ecdsaClient.Keygen(curveName)
if err != nil {
panic(err)
}
chainPath := []uint32{1, 2, 3, 4}
derPublicKey, err := ecdsaClient.PublicKey(keyID, chainPath)
if err != nil {
panic(err)
}
publicKey, err := ecdsaClient.ParsePublicKey(derPublicKey)
if err != nil {
panic(err)
}
compressedPublicKey := make([]byte, 1+32)
ySignFlag := byte(publicKey.Y.Bit(0))
compressedPublicKey[0] = 2 | ySignFlag
publicKey.X.FillBytes(compressedPublicKey[1:])
address, err := btcutil.NewAddressPubKey(compressedPublicKey, &chaincfg.TestNet3Params)
if err != nil {
panic(err)
}
// Note: Encoding a *AddressPubKey (pay-to-pubkey) results in a P2PKH address
// (pay-to-pubkey-hash). Convert address to a *AddressPubKeyHash before using it.
btcAddress := address.EncodeAddress()
fmt.Println("Bitcoin address: ", btcAddress)
final String keyID = sdk.ecdsaKeygenWithSessionID(sdk.generateSessionID(),"secp256k1");
final int[] chainPath = new int[] {1,2,3,4};
final byte[] derPublicKey = sdk.ecdsaPublicKey(keyID, chainPath);
Security.addProvider(new BouncyCastleProvider());
final X509EncodedKeySpec spec = new X509EncodedKeySpec(derPublicKey);
final KeyFactory kf = KeyFactory.getInstance("EC", "BC");
final ECPublicKey publicKey = (ECPublicKey) kf.generatePublic(spec);
final ECPoint w = publicKey.getW();
final BigInteger x = w.getAffineX();
final BigInteger y = w.getAffineY();
byte[] xBytes = x.toByteArray();
if (xBytes.length == 33) {
xBytes = Arrays.copyOfRange(xBytes, 1, 33);
}
byte[] leadingZeroes = new byte[32 - xBytes.length];
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(y.testBit(0) ? 3 : 2);
baos.write(leadingZeroes, 0, leadingZeroes.length);
baos.write(xBytes, 0, xBytes.length);
final MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
final byte[] digest1 = sha256.digest(baos.toByteArray());
final MessageDigest ripemd160 = MessageDigest.getInstance("RIPEMD160", "BC");
final byte[] digest2 = ripemd160.digest(digest1);
final ByteArrayOutputStream addressBuilder = new ByteArrayOutputStream();
addressBuilder.write(0x00); // 0x00 for Mainnet, 0x6f for Testnet
addressBuilder.write(digest2, 0, digest2.length);
byte[] checksum = sha256.digest(addressBuilder.toByteArray());
checksum = sha256.digest(checksum);
addressBuilder.write(checksum, 0, 4);
// TODO: Use some Base58 encoder instead of Hex
String base58 = HexFormat.of().formatHex(addressBuilder.toByteArray());
System.out.println("Bitcoin address: " + base58);
The chainPath is the bip-32 derivation path.
Updated 8 months ago