org.bcos.web3j.crypto.Keys Maven / Gradle / Ivy
package org.bcos.web3j.crypto;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.ECGenParameterSpec;
import java.util.Arrays;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bcos.web3j.utils.Numeric;
import org.bcos.web3j.utils.Strings;
/**
* Crypto key utilities.
*/
public class Keys {
static final int PRIVATE_KEY_SIZE = 32;
static final int PUBLIC_KEY_SIZE = 64;
public static final int ADDRESS_LENGTH_IN_HEX = 40;
static final int PUBLIC_KEY_LENGTH_IN_HEX = PUBLIC_KEY_SIZE << 1;
public static final int PRIVATE_KEY_LENGTH_IN_HEX = PRIVATE_KEY_SIZE << 1;
static {
Security.addProvider(new BouncyCastleProvider());
}
private Keys() { }
/**
* Create a keypair using SECP-256k1 curve.
*
* Private keypairs are encoded using PKCS8
*
*
Private keys are encoded using X.509
*/
static KeyPair createSecp256k1KeyPair() throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidAlgorithmParameterException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ECDSA", "BC");
ECGenParameterSpec ecGenParameterSpec = new ECGenParameterSpec("secp256k1");
keyPairGenerator.initialize(ecGenParameterSpec, new SecureRandom());
return keyPairGenerator.generateKeyPair();
}
public static ECKeyPair createEcKeyPair() throws InvalidAlgorithmParameterException,
NoSuchAlgorithmException, NoSuchProviderException {
KeyPair keyPair = createSecp256k1KeyPair();
return ECKeyPair.create(keyPair);
}
public static String getAddress(ECKeyPair ecKeyPair) {
return getAddress(ecKeyPair.getPublicKey());
}
public static String getAddress(BigInteger publicKey) {
return getAddress(
Numeric.toHexStringWithPrefixZeroPadded(publicKey, PUBLIC_KEY_LENGTH_IN_HEX));
}
public static String getAddress(String publicKey) {
String publicKeyNoPrefix = Numeric.cleanHexPrefix(publicKey);
if (publicKeyNoPrefix.length() < PUBLIC_KEY_LENGTH_IN_HEX) {
publicKeyNoPrefix = Strings.zeros(
PUBLIC_KEY_LENGTH_IN_HEX - publicKeyNoPrefix.length())
+ publicKeyNoPrefix;
}
String hash = Hash.sha3(publicKeyNoPrefix);
return hash.substring(hash.length() - ADDRESS_LENGTH_IN_HEX); // right most 160 bits
}
public static byte[] getAddress(byte[] publicKey) {
byte[] hash = Hash.sha3(publicKey);
return Arrays.copyOfRange(hash, hash.length - 20, hash.length); // right most 160 bits
}
public static byte[] serialize(ECKeyPair ecKeyPair) {
byte[] privateKey = Numeric.toBytesPadded(ecKeyPair.getPrivateKey(), PRIVATE_KEY_SIZE);
byte[] publicKey = Numeric.toBytesPadded(ecKeyPair.getPublicKey(), PUBLIC_KEY_SIZE);
byte[] result = Arrays.copyOf(privateKey, PRIVATE_KEY_SIZE + PUBLIC_KEY_SIZE);
System.arraycopy(publicKey, 0, result, PRIVATE_KEY_SIZE, PUBLIC_KEY_SIZE);
return result;
}
public static ECKeyPair deserialize(byte[] input) {
if (input.length != PRIVATE_KEY_SIZE + PUBLIC_KEY_SIZE) {
throw new RuntimeException("Invalid input key size");
}
BigInteger privateKey = Numeric.toBigInt(input, 0, PRIVATE_KEY_SIZE);
BigInteger publicKey = Numeric.toBigInt(input, PRIVATE_KEY_SIZE, PUBLIC_KEY_SIZE);
return new ECKeyPair(privateKey, publicKey);
}
}