Last active
November 30, 2021 11:28
-
-
Save celsoagra/e3b99df57f4fad1ed0c693761058bc0f to your computer and use it in GitHub Desktop.
code about to generate bitcoin address
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-----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