nano钱包 安卓版源码解读

版权声明:本文为博主原创文章,未经博主允许不得转载。深圳夸克时代在线技术有限公司 官网:http://www.kksdapp.com https://blog.csdn.net/wahaha13168/article/details/82914311

1:生成钱包种子

public static String generateSeed() {
    int numchars = 64;
    SecureRandom random = SecureRandomUtil.secureRandom();
    byte[] randomBytes = new byte[numchars / 2];
    random.nextBytes(randomBytes);

    StringBuilder sb = new StringBuilder(numchars);
    for (byte b : randomBytes) {
        sb.append(String.format("%02X", b));
    }
    return sb.toString();
}

2:根据钱包种子得到私钥

/**
 * Convert a wallet seed to private key
 *
 * @param seed Wallet seed
 * @return private key
 */
public static String seedToPrivate(String seed) {
    Sodium sodium = NaCl.sodium();
    byte[] state = new byte[Sodium.crypto_generichash_statebytes()];
    byte[] key = new byte[Sodium.crypto_generichash_keybytes()];

    byte[] seed_b = NanoUtil.hexToBytes(seed);
    byte[] index_b = {0x00, 0x00, 0x00, 0x00};
    byte[] output = new byte[32];

    Sodium.crypto_generichash_blake2b_init(state, key, 0, 32);
    Sodium.crypto_generichash_blake2b_update(state, seed_b, seed_b.length);
    Sodium.crypto_generichash_blake2b_update(state, index_b, index_b.length);
    Sodium.crypto_generichash_blake2b_final(state, output, output.length);

    return bytesToHex(output);
}

3:由私钥得到公钥


/**
 * Convert a private key to a public key
 *
 * @param private_key private key
 * @return public key
 */
public static String privateToPublic(String private_key) {
    Sodium sodium = NaCl.sodium();
    byte[] public_key_b = new byte[Sodium.crypto_generichash_blake2b_bytes()];
    byte[] private_key_b = hexToBytes(private_key);

    Sodium.crypto_sign_ed25519_sk_to_pk(public_key_b, private_key_b);

    return bytesToHex(public_key_b);
}

4:由公钥生成钱包地址

/**
 * Convert a Public Key to an Address
 *
 * @param public_key Public Key
 * @return xrb address
 */
public static String publicToAddress(String public_key) {
    Sodium sodium = NaCl.sodium();
    byte[] bytePublic = NanoUtil.hexStringToByteArray(public_key);
    String encodedAddress = encode(public_key);

    byte[] state = new byte[Sodium.crypto_generichash_statebytes()];
    byte[] key = new byte[Sodium.crypto_generichash_keybytes()];
    byte[] check_b = new byte[5];

    Sodium.crypto_generichash_blake2b_init(state, key, 0, 5);
    Sodium.crypto_generichash_blake2b_update(state, bytePublic, bytePublic.length);
    Sodium.crypto_generichash_blake2b_final(state, check_b, check_b.length);

    reverse(check_b);

    StringBuilder resultAddress = new StringBuilder();
    resultAddress.insert(0, "xrb_");
    resultAddress.append(encodedAddress);
    resultAddress.append(encode(NanoUtil.bytesToHex(check_b)));

    return resultAddress.toString();

}

5:由地址去得到公钥


/**
 * Convert an address to a public key
 *
 * @param encoded_address encoded Address
 * @return Public Key
 */
public static String addressToPublic(String encoded_address) {
    NaCl.sodium();
    String data = encoded_address.split("_")[1].substring(0, 52);
    byte[] data_b = NanoUtil.hexStringToByteArray(decodeAddressCharacters(data));

    byte[] state = new byte[Sodium.crypto_generichash_statebytes()];
    byte[] key = new byte[Sodium.crypto_generichash_keybytes()];
    byte[] verify_b = new byte[5];

    Sodium.crypto_generichash_blake2b_init(state, key, 0, 5);
    Sodium.crypto_generichash_blake2b_update(state, data_b, data_b.length);
    Sodium.crypto_generichash_blake2b_final(state, verify_b, verify_b.length);

    reverse(verify_b);

    // left pad byte array with zeros
    StringBuilder pk = new StringBuilder(NanoUtil.bytesToHex(data_b));
    while (pk.length() < 64) {
        pk.insert(0, "0");
    }

    return pk.toString();
}

6:验证地址是否合法


public boolean isValidAddress() {
    String[] parts = value.split("_");
    if (parts.length != 2) {
        return false;
    }
    if (!parts[0].equals("xrb") && !parts[0].equals("nano")) {
        return false;
    }
    if (parts[1].length() != 60) {
        return false;
    }
    checkCharacters:
    for (int i = 0; i < parts[1].length(); i++) {
        char letter = parts[1].toLowerCase().charAt(i);
        for (int j = 0; j < NanoUtil.addressCodeCharArray.length; j++) {
            if (NanoUtil.addressCodeCharArray[j] == letter) {
                continue checkCharacters;
            }
        }
        return false;
    }
    byte[] shortBytes = NanoUtil.hexToBytes(NanoUtil.decodeAddressCharacters(parts[1]));
    byte[] bytes = new byte[37];
    // Restore leading null bytes
    System.arraycopy(shortBytes, 0, bytes, bytes.length - shortBytes.length, shortBytes.length);
    byte[] checksum = new byte[5];
    byte[] state = new byte[Sodium.crypto_generichash_statebytes()];
    byte[] key = new byte[Sodium.crypto_generichash_keybytes()];
    NaCl.sodium();
    Sodium.crypto_generichash_blake2b_init(state, key, 0, 5);
    Sodium.crypto_generichash_blake2b_update(state, bytes, 32);
    Sodium.crypto_generichash_blake2b_final(state, checksum, checksum.length);
    for (int i = 0; i < checksum.length; i++) {
        if (checksum[i] != bytes[bytes.length - 1 - i]) {
            return false;
        }
    }
    return true;
}


7:验证钱包种子是否合法

public static boolean isValidSeed(String seed) {

    if (seed.length() != 64) {
        return false;
    }
    boolean isMatch = true;
    for (int i = 0; i < seed.length() && isMatch; i++) {
        char letter = seed.toLowerCase().charAt(i);
        if (!VALID_SEED_CHARACTERS.contains(letter)) {
            isMatch = false;
        }
    }
    return isMatch;
}

猜你喜欢

转载自blog.csdn.net/wahaha13168/article/details/82914311