EdDSA-Java by str4d To the extent possible under law, the person who associated CC0 with EdDSA-Java has waived all copyright and related or neighboring rights to EdDSA-Java. You should have received a copy of the CC0 legalcode along with this work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
package net.i2p.crypto.eddsa.spec;
import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.spec.KeySpec; import java.util.Arrays;
import net.i2p.crypto.eddsa.math.GroupElement;
@author str4d /
public class EdDSAPrivateKeySpec implements KeySpec {
private final byte[] seed; private final byte[] h; private final byte[] a; private final GroupElement A; private final EdDSAParameterSpec spec; /** @param seed the private key @param spec the parameter specification for this key @throws IllegalArgumentException if seed length is wrong or hash algorithm is unsupported / public EdDSAPrivateKeySpec(byte[] seed, EdDSAParameterSpec spec) { if (seed.length != spec.getCurve().getField().getb()/8) throw new IllegalArgumentException("seed length is wrong"); this.spec = spec; this.seed = seed; try { MessageDigest hash = MessageDigest.getInstance(spec.getHashAlgorithm()); int b = spec.getCurve().getField().getb(); // H(k) h = hash.digest(seed); /*a = BigInteger.valueOf(2).pow(b-2); for (int i=3;i<(b-2);i++) { a = a.add(BigInteger.valueOf(2).pow(i).multiply(BigInteger.valueOf(Utils.bit(h,i)))); } // Saves ~0.4ms per key when running signing tests. // TODO: are these bitflips the same for any hash function? h[0] &= 248; h[(b/8)-1] &= 63; h[(b/8)-1] |= 64; a = Arrays.copyOfRange(h, 0, b/8); A = spec.getB().scalarMultiply(a); } catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException("Unsupported hash algorithm"); } } /** Initialize directly from the hash. getSeed() will return null if this constructor is used. @param spec the parameter specification for this key @param h the private key @throws IllegalArgumentException if hash length is wrong @since 0.1.1 / public EdDSAPrivateKeySpec(EdDSAParameterSpec spec, byte[] h) { if (h.length != spec.getCurve().getField().getb()/4) throw new IllegalArgumentException("hash length is wrong"); this.seed = null; this.h = h; this.spec = spec; int b = spec.getCurve().getField().getb(); h[0] &= 248; h[(b/8)-1] &= 63; h[(b/8)-1] |= 64; a = Arrays.copyOfRange(h, 0, b/8); A = spec.getB().scalarMultiply(a); } public EdDSAPrivateKeySpec(byte[] seed, byte[] h, byte[] a, GroupElement A, EdDSAParameterSpec spec) { this.seed = seed; this.h = h; this.a = a; this.A = A; this.spec = spec; } /** @return will be null if constructed directly from the private key / public byte[] getSeed() { return seed; } /** @return the hash / public byte[] getH() { return h; } /** @return the private key / public byte[] geta() { return a; } /** @return the public key / public GroupElement getA() { return A; } public EdDSAParameterSpec getParams() { return spec; }
}