convex.core.crypto.SLIP10 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of convex-core Show documentation
Show all versions of convex-core Show documentation
Convex core libraries and common utilities
The newest version!
package convex.core.crypto;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import convex.core.data.Blob;
import convex.core.util.Utils;
import convex.core.exceptions.Panic;
/**
* Class implementing SLIP-0010 private key generations for Ed25519 private keys
*
* See: https://github.com/satoshilabs/slips/blob/master/slip-0010.md
*/
public class SLIP10 {
// Algorithm identifier for HMAC-SHA512 (as specified in RFC 4231)
private static final String HMAC_ALGORITHM= "HmacSHA512";
// Key as specified in SLIP10 for Ed25519
private static final byte[] ED25519_KEY = "ed25519 seed".getBytes(StandardCharsets.UTF_8);
private static final SecretKeySpec masterKey=new SecretKeySpec(ED25519_KEY,HMAC_ALGORITHM);
/**
* Gets the the master key for a given seed according to SLIP10
* @param bip39seed BIP39 seed value (or other source of good entropy!)
* @return Blob containing the SLIP10 master key
*/
public static Blob getMaster(Blob bip39seed) {
try {
Mac hmac=Mac.getInstance(HMAC_ALGORITHM);
hmac.init(masterKey);
byte[] data=bip39seed.getBytes();
hmac.update(data);
Blob result=Blob.wrap(hmac.doFinal());
return result;
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
throw new Panic(e);
}
}
/**
* Derives an Ed25519 private key from a BIP32 master key
* @param master Master key as defined in SLIP10
* @param ixs key derivation path indexes
*/
public static Blob derive(Blob master, int... ixs) {
if (ixs.length==0) return master;
if (ixs.length>255) throw new IllegalArgumentException("Maximum BIP32 path length exceeded (must be 255 or less)");
byte[] bs=master.getBytes();
if (bs.length!=64) throw new IllegalArgumentException("Invalid SLIP10 master key, must be 64 bytes");
byte[] data=new byte[1+32+4]; // 0x00 || ser256(kpar) || ser32(i)) from SLIP-10
try {
Mac hmac=Mac.getInstance(HMAC_ALGORITHM);
for (int i=0; i