vite.Wallet Maven / Gradle / Ivy
The newest version!
package vite;
import com.rfksystems.blake2b.Blake2b;
import com.rfksystems.blake2b.security.Blake2bProvider;
import net.i2p.crypto.eddsa.EdDSAEngine;
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
import net.i2p.crypto.eddsa.EdDSAPublicKey;
import net.i2p.crypto.eddsa.Utils;
import net.i2p.crypto.eddsa.math.Curve;
import net.i2p.crypto.eddsa.math.Field;
import net.i2p.crypto.eddsa.math.ed25519.Ed25519LittleEndianEncoding;
import net.i2p.crypto.eddsa.math.ed25519.Ed25519ScalarOps;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import vite.bean.Key;
import vite.bean.ViteMnemonics;
import vite.utils.PBKDF2SHA512;
import java.security.*;
import java.util.Arrays;
import java.util.List;
import static vite.utils.BytesUtils.byteMerger;
import static vite.utils.BytesUtils.int2Bytes;
public class Wallet {
private static final SecureRandom SECURE_RANDOM = new SecureRandom();
private static String ViteAccountPathFormat = "m/44'/666666'/%d'";
private static final String seceret = "ed25519 blake2b seed";
private static EdDSANamedCurveSpec ED25519_BLAKE2B_CURVES_PEC;
private static Provider provider;
static {
provider = new Blake2bProvider();
Security.addProvider(provider);
Field ED25519_FIELD = new Field(
256, // b
Utils.hexToBytes("edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f"), // q
new Ed25519LittleEndianEncoding());
Curve ED25519_CURVE = new Curve(ED25519_FIELD,
Utils.hexToBytes("a3785913ca4deb75abd841414d0a700098e879777940c78c73fe6f2bee6c0352"), // d
ED25519_FIELD.fromByteArray(Utils.hexToBytes("b0a00e4a271beec478e42fad0618432fa7d7fb3d99004d2b0bdfc14f8024832b"))); // I
ED25519_BLAKE2B_CURVES_PEC = new EdDSANamedCurveSpec(
EdDSANamedCurveTable.ED_25519,
ED25519_CURVE,
Blake2b.BLAKE2_B_512, // H
new Ed25519ScalarOps(), // l
ED25519_CURVE.createPoint( // B
Utils.hexToBytes("5866666666666666666666666666666666666666666666666666666666666666"),
true)); // Precompute tables for B
EdDSANamedCurveTable.defineCurve(ED25519_BLAKE2B_CURVES_PEC);
}
public static byte[] createPublicKey(byte[] privateKey) {
EdDSAPrivateKeySpec key = new EdDSAPrivateKeySpec(privateKey, ED25519_BLAKE2B_CURVES_PEC);
return key.getA().toByteArray();
}
public static byte[] sign(byte[] hash, byte[] privateKey) {
try {
EdDSAEngine edDSAEngine = new EdDSAEngine(MessageDigest.getInstance(Blake2b.BLAKE2_B_512, provider));
EdDSAPrivateKeySpec edDSAPrivateKeySpec = new EdDSAPrivateKeySpec(privateKey, ED25519_BLAKE2B_CURVES_PEC);
EdDSAPrivateKey edDSAPrivateKey = new EdDSAPrivateKey(edDSAPrivateKeySpec);
edDSAEngine.initSign(edDSAPrivateKey);
edDSAEngine.setParameter(EdDSAEngine.ONE_SHOT_MODE);
edDSAEngine.update(hash);
return edDSAEngine.sign();
} catch (GeneralSecurityException e) {
throw new IllegalStateException("It wasn't possible to sign " + Arrays.toString(hash), e);
}
}
public static boolean verify(byte[] signature, byte[] hash, byte[] publicKey) {
try {
EdDSAEngine edDSAEngine = new EdDSAEngine(MessageDigest.getInstance(Blake2b.BLAKE2_B_512, provider));
EdDSAPublicKeySpec edDSAPublicKeySpec = new EdDSAPublicKeySpec(publicKey, ED25519_BLAKE2B_CURVES_PEC);
EdDSAPublicKey edDSAPublicKey = new EdDSAPublicKey(edDSAPublicKeySpec);
edDSAEngine.initVerify(edDSAPublicKey);
edDSAEngine.setParameter(EdDSAEngine.ONE_SHOT_MODE);
edDSAEngine.update(hash);
return edDSAEngine.verify(signature);
} catch (GeneralSecurityException e) {
throw new IllegalStateException("It wasn't possible to verify " + Arrays.toString(hash), e);
}
}
public static List createBip39Mnemonic(int length, ViteMnemonics.ViteMnemonicLanguage language) {
return ViteMnemonics.createBip39Mnemonic(generateSeed(32 * length / 3 / 8), language);
}
public static List createBip39Mnemonic() {
return createBip39Mnemonic(24, ViteMnemonics.ViteMnemonicLanguage.ENGLISH);
}
private static byte[] generateSeed(int length) {
byte[] seed = new byte[length];
SECURE_RANDOM.nextBytes(seed);
return seed;
}
//m/44'/666666'/0' 5c196b50d9c0d9edc174c49fc9d18e59a0629b8b96b33d5815b560204e9ec988 vite_f41ea3215ef1b195e1389c23bfde50534260be96304cb2db46
/**
* @param mnemonics
* @param index
* @param type user or contract
* @return
*/
public static Key generateKeyPairsFromMnemonics(String mnemonics, int index, int type) {
// seed pbkdf2sha512
byte[] seed = PBKDF2SHA512.derive(mnemonics, "mnemonic" + "", 2048, 64);
// System.out.println("seed: " + Hex.encodeHexString(seed));
String path = ViteAccountPathFormat.replaceAll("%d", index + "");
byte[] result = deriveForPath(path, seed);
byte[] key = new byte[32];
System.arraycopy(result, 0, key, 0, 32);
byte[] pubKey = createPublicKey(key);
byte[] addressFirst = ViteWalletHelper.digest(20, pubKey);
byte[] checkSum = null;
if (type == 1) {
checkSum = ViteWalletHelper.digest(5, addressFirst);
for (int i = 0; i < checkSum.length; i++) {
checkSum[i] = (byte)~checkSum[i];
}
} else {
checkSum = ViteWalletHelper.digest(5, addressFirst);
}
Key keyresult = new Key();
keyresult.setPriKey(key);
keyresult.setPubKey(createPublicKey(key));
keyresult.setAddress(addressFirst);
keyresult.setChecksum(checkSum);
if (type == 1) {
keyresult.setIsContract((byte)1);
} else {
keyresult.setIsContract((byte)0);
}
return keyresult;
// System.out.println(path + "\t" + Hex.encodeHexString(key) + "\t" + "vite_" + Hex.encodeHexString(address) + Hex.encodeHexString(checkSum));
}
public static String getViteAddressFromBase64PubKey(String base64PubKey, int type) {
Base64 base64 = new Base64();
byte[] pubBytes = base64.decode(base64PubKey);
byte[] addressFirst = ViteWalletHelper.digest(20, pubBytes);
byte[] checkSum = null;
if (type == 1) {
checkSum = ViteWalletHelper.digest(5, addressFirst);
for (int i = 0; i < checkSum.length; i++) {
checkSum[i] = (byte)~checkSum[i];
}
} else {
checkSum = ViteWalletHelper.digest(5, addressFirst);
}
return "vite_" + Hex.encodeHexString(addressFirst) + Hex.encodeHexString(checkSum);
}
private static byte[] deriveForPath(String path, byte[] seed) {
try {
byte[] bytes = hmacSha512(seceret.getBytes("utf-8"), seed);
byte[] masterKey = new byte[32];
byte[] chaincode = new byte[32];
System.arraycopy(bytes, 0, masterKey, 0, 32);
System.arraycopy(bytes, 32, chaincode, 0, 32);
// System.out.println("masterKey " + new String(Hex.encodeHex(masterKey)));
// System.out.println("chainCode " + new String(Hex.encodeHex(chaincode)));
String segments[] = path.replaceAll("'", "").split("/");
byte[] result = null;
for (int i = 1; i < 4; i++) {
int i32 = Integer.parseInt(segments[i]);
i32 = i32 | 1 << 31;
// System.out.println(i32);
result = derive(i32, masterKey, chaincode);
masterKey = new byte[32];
chaincode = new byte[32];
System.arraycopy(result, 0, masterKey, 0, 32);
System.arraycopy(result, 32, chaincode, 0, 32);
}
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static byte[] derive(int index, byte[] masterkey, byte[] chainCode) {
byte[] iBytes = int2Bytes(index);
byte[] prefix = {0x0};
byte[] keymodfify = byteMerger(prefix, masterkey);
keymodfify = byteMerger(keymodfify, iBytes);
byte[] result = hmacSha512(chainCode, keymodfify);
return result;
}
static HMac createHmacSha512Digest(byte[] key) {
SHA512Digest digest = new SHA512Digest();
HMac hMac = new HMac(digest);
hMac.init(new KeyParameter(key));
return hMac;
}
static byte[] hmacSha512(HMac hmacSha512, byte[] input) {
hmacSha512.reset();
hmacSha512.update(input, 0, input.length);
byte[] out = new byte[64];
hmacSha512.doFinal(out, 0);
return out;
}
public static byte[] hmacSha512(byte[] key, byte[] data) {
return hmacSha512(createHmacSha512Digest(key), data);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy