Skip to content

Instantly share code, notes, and snippets.

@celsoagra
Last active November 30, 2021 11:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save celsoagra/e3b99df57f4fad1ed0c693761058bc0f to your computer and use it in GitHub Desktop.
Save celsoagra/e3b99df57f4fad1ed0c693761058bc0f to your computer and use it in GitHub Desktop.
code about to generate bitcoin address
package org.example.keypair;
import org.bitcoinj.core.Base58;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import org.bouncycastle.util.io.pem.PemWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
/**
* https://www.novixys.com/blog/generate-bitcoin-addresses-java/
* https://academy.bit2me.com/pt/o-que-%C3%A9-curva-el%C3%ADptica-ecdsa/
* https://crypto.stackexchange.com/questions/12823/ecdsa-vs-ecies-vs-ecdh
*/
public class GenerateKeypair {
public static void main( String[] args ) throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
KeyPair kp = null;
PrivateKey pk = null;
ECPrivateKey epvt = null;
ECPublicKey epub = null;
File walletkey = new File(".", "walletkey.pem");
if(!walletkey.exists()) { // if there's no wallet, generate one
kp = generate("ECDSA");
epvt = (ECPrivateKey) kp.getPrivate();
epub = (ECPublicKey) kp.getPublic();
PemObject obj = new PemObject("PRIVATE KEY", kp.getPrivate().getEncoded());
PemWriter writer = new PemWriter(new FileWriter(walletkey));
writer.writeObject(obj);
writer.close();
} else { // otherwise, get file with privatekey and get the public key to generate address
PemReader pr = new PemReader(new FileReader(walletkey));
PemObject obj = pr.readPemObject();
KeyFactory kf = KeyFactory.getInstance("ECDSA");
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(obj.getContent());
epvt = (ECPrivateKey) kf.generatePrivate(spec);
ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(epvt.getParams().getGenerator(), epvt.getParams());
epub = (ECPublicKey) kf.generatePublic(publicKeySpec);
}
// 3. The ECDSA Private Key
String sepvt = adjustTo64(epvt.getS().toString(16)).toUpperCase();
System.out.println("s[" + sepvt.length() + "]: " + sepvt);
// 4. The ECDSA Public Key
ECPoint pt = epub.getW();
String sx = adjustTo64(pt.getAffineX().toString(16)).toUpperCase();
String sy = adjustTo64(pt.getAffineY().toString(16)).toUpperCase();
String bcPub = "04" + sx + sy;
System.out.println("bcPub: " + bcPub);
performHash(bcPub);
}
public static void performHash(String bcPub) throws NoSuchAlgorithmException, UnsupportedEncodingException, NoSuchProviderException {
// SHA-256
MessageDigest sha = MessageDigest.getInstance("SHA-256");
byte[] s1 = sha.digest(bcPub.getBytes("UTF-8"));
System.out.println(" sha: " + Hex.toHexString(s1).toUpperCase());
// RipeMD160
MessageDigest rmd = MessageDigest.getInstance("RipeMD160", BouncyCastleProvider.PROVIDER_NAME);
byte[] r1 = rmd.digest(s1);
// add 0x00
byte[] r2 = new byte[r1.length + 1];
r2[0] = 0;
for (int i = 0 ; i < r1.length ; i++) r2[i+1] = r1[i];
System.out.println(" rmd1: " + Hex.toHexString(r1).toUpperCase());
System.out.println(" rmd2: " + Hex.toHexString(r2).toUpperCase());
// 6. Repeat the SHA-256 Hashing Twice
byte[] s2 = sha.digest(r2);
System.out.println(" sha s2: " + Hex.toHexString(s2).toUpperCase());
byte[] s3 = sha.digest(s2);
System.out.println(" sha s3: " + Hex.toHexString(s3).toUpperCase());
byte[] a1 = new byte[25];
for (int i = 0 ; i < r2.length ; i++) a1[i] = r2[i];
for (int i = 0 ; i < 5 ; i++) a1[20 + i] = s3[i];
// 7. Encode the Address Using Base58
System.out.println(" final adr: " + Base58.encode(a1));
}
public static KeyPair generate(String alg) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256k1");
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(alg, BouncyCastleProvider.PROVIDER_NAME);
keyPairGenerator.initialize(ecSpec, new SecureRandom());
return keyPairGenerator.generateKeyPair();
}
static private String adjustTo64(String s) {
switch(s.length()) {
case 62: return "00" + s;
case 63: return "0" + s;
case 64: return s;
default:
throw new IllegalArgumentException("not a valid key: " + s);
}
}
}
s[64]: 12BB8F00B59B95ED377E9D359CBE3989B69735E7D5157561E0F7A79C2BB1D5F9
bcPub: 0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
sha: 024A8E4F2343424FBF9CDCC22198477813DED7E2F94B04D6081274EA4FE3926B
rmd1: 64BC8F970EF0D40E1F0C89B6471209A6E94E2CEA
rmd2: 0064BC8F970EF0D40E1F0C89B6471209A6E94E2CEA
sha s2: 22A7CB65FCE60BA391D92D51FE75B9E3E295BCAF5CBBD5A0C0DE0FE88544716B
sha s3: 00DB0584FF5D443B11D4458F57B156A93FF3C24AF57B679D783FD9E6F59AC9C7
final adr: 1ABeTdC2kg7YGXRH1UdMyfxUzwi9aArFav
Process finished with exit code 0
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.68</version>
</dependency>
<dependency>
<groupId>org.bitcoinj</groupId>
<artifactId>bitcoinj-core</artifactId>
<version>0.16.1</version>
</dependency>
</dependencies>
-----BEGIN PRIVATE KEY-----
MIGNAgEAMBAGByqGSM49AgEGBSuBBAAKBHYwdAIBAQQgEruPALWble03fp01nL45
ibaXNefVFXVh4PennCux1fmgBwYFK4EEAAqhRANCAASnSF+TXum0ZI6I4W8afjtB
6qIRbuHhXHgnTM2j9CZcroSvR5JZXXDI02+IdEaT8LkZ5UMb4sxLvWy1B5rXAZ5n
-----END PRIVATE KEY-----
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment