/** * @since 0.9.25 */ @Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof EdDSAParameterSpec)) return false; EdDSAParameterSpec s = (EdDSAParameterSpec) o; return hashAlgo.equals(s.getHashAlgorithm()) && curve.equals(s.getCurve()) && B.equals(s.getB()); } }
if (!edDsaSpec.equals(EdDSANamedCurveTable.ED_25519_CURVE_SPEC)) return null; int totlen = 12 + Abyte.length;
private byte[] x_engineSign() throws SignatureException { Curve curve = key.getParams().getCurve(); ScalarOps sc = key.getParams().getScalarOps(); byte[] a = ((EdDSAPrivateKey) key).geta(); GroupElement R = key.getParams().getB().scalarMultiply(r); byte[] Rbyte = R.toByteArray();
/** * 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.9.27 (GitHub issue #17) */ public EdDSAPrivateKeySpec(EdDSAParameterSpec spec, byte[] h) { int bd4 = spec.getCurve().getField().getb() / 4; if (h.length != bd4) throw new IllegalArgumentException("hash length is wrong"); int bd8 = bd4 / 2; this.seed = null; this.h = h; this.spec = spec; h[0] &= 248; h[bd8 - 1] &= 63; h[bd8 - 1] |= 64; a = Arrays.copyOfRange(h, 0, bd8); A = spec.getB().scalarMultiply(a); }
public Ed25519PublicKey(EdDSAPublicKeySpec spec) { super(spec); EdDSANamedCurveSpec ed25519 = EdDSANamedCurveTable.getByName("Ed25519"); if (!spec.getParams().getCurve().equals(ed25519.getCurve())) { throw new SSHRuntimeException("Cannot create Ed25519 Public Key from wrong spec"); } }
@Override protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException { reset(); if (privateKey instanceof EdDSAPrivateKey) { EdDSAPrivateKey privKey = (EdDSAPrivateKey) privateKey; key = privKey; if (digest == null) { // Instantiate the digest from the key parameters try { digest = MessageDigest.getInstance(key.getParams().getHashAlgorithm()); } catch (NoSuchAlgorithmException e) { throw new InvalidKeyException("cannot get required digest " + key.getParams().getHashAlgorithm() + " for private key."); } } else if (!key.getParams().getHashAlgorithm().equals(digest.getAlgorithm())) throw new InvalidKeyException("Key hash algorithm does not match chosen digest"); digestInitSign(privKey); } else { throw new InvalidKeyException("cannot identify EdDSA private key: " + privateKey.getClass()); } }
/** * @param pk the public key * @param spec the parameter specification for this key * @throws IllegalArgumentException if key length is wrong */ public EdDSAPublicKeySpec(byte[] pk, EdDSAParameterSpec spec) { if (pk.length != spec.getCurve().getField().getb()/8) throw new IllegalArgumentException("public-key length is wrong"); this.A = new GroupElement(spec.getCurve(), pk); this.spec = spec; }
@Override protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException { reset(); if (publicKey instanceof EdDSAPublicKey) { key = (EdDSAPublicKey) publicKey; if (digest == null) { // Instantiate the digest from the key parameters try { digest = MessageDigest.getInstance(key.getParams().getHashAlgorithm()); } catch (NoSuchAlgorithmException e) { throw new InvalidKeyException("cannot get required digest " + key.getParams().getHashAlgorithm() + " for private key."); } } else if (!key.getParams().getHashAlgorithm().equals(digest.getAlgorithm())) throw new InvalidKeyException("Key hash algorithm does not match chosen digest"); } else if (publicKey.getClass().getName().equals("sun.security.x509.X509Key")) { // X509Certificate will sometimes contain an X509Key rather than the EdDSAPublicKey itself; the contained // key is valid but needs to be instanced as an EdDSAPublicKey before it can be used. EdDSAPublicKey parsedPublicKey; try { parsedPublicKey = new EdDSAPublicKey(new X509EncodedKeySpec(publicKey.getEncoded())); } catch (InvalidKeySpecException ex) { throw new InvalidKeyException("cannot handle X.509 EdDSA public key: " + publicKey.getAlgorithm()); } engineInitVerify(parsedPublicKey); } else { throw new InvalidKeyException("cannot identify EdDSA public key: " + publicKey.getClass()); } }
/** * 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); }
/** * @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) { int bd8 = spec.getCurve().getField().getb() / 8; if (seed.length != bd8) throw new IllegalArgumentException("seed length is wrong"); this.spec = spec; this.seed = seed; try { MessageDigest hash = MessageDigest.getInstance(spec.getHashAlgorithm()); // 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[bd8 - 1] &= 63; h[bd8 - 1] |= 64; a = Arrays.copyOfRange(h, 0, bd8); A = spec.getB().scalarMultiply(a); } catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException("Unsupported hash algorithm"); } }
private boolean x_engineVerify(byte[] sigBytes) throws SignatureException { Curve curve = key.getParams().getCurve(); int b = curve.getField().getb(); if (sigBytes.length != b/4) h = key.getParams().getScalarOps().reduce(h); GroupElement R = key.getParams().getB().doubleScalarMultiplyVariableTime( ((EdDSAPublicKey) key).getNegativeA(), h, Sbyte);
private void digestInitSign(EdDSAPrivateKey privKey) { // Preparing for hash // r = H(h_b,...,h_2b-1,M) int b = privKey.getParams().getCurve().getField().getb(); digest.update(privKey.getH(), b/8, b/4 - b/8); }
@Test public void testSignResetsForReuse() throws Exception { EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519); Signature sgr = new EdDSAEngine(MessageDigest.getInstance(spec.getHashAlgorithm())); EdDSAPrivateKeySpec privKey = new EdDSAPrivateKeySpec(TEST_SEED, spec); PrivateKey sKey = new EdDSAPrivateKey(privKey); sgr.initSign(sKey); // First usage sgr.update(new byte[] {0}); sgr.sign(); // Second usage sgr.update(TEST_MSG); assertThat("Second sign failed", sgr.sign(), is(equalTo(TEST_MSG_SIG))); }
if (!edDsaSpec.equals(EdDSANamedCurveTable.ED_25519_CURVE_SPEC)) return null; if (seed == null)
public static boolean compareEDDSAKeyParams(EdDSAParameterSpec s1, EdDSAParameterSpec s2) { if (Objects.equals(s1, s2)) { return true; } else if (s1 == null || s2 == null) { return false; // both null is covered by Objects#equals } else { return Objects.equals(s1.getHashAlgorithm(), s2.getHashAlgorithm()) && Objects.equals(s1.getCurve(), s2.getCurve()) && Objects.equals(s1.getB(), s2.getB()); } }
private byte[] x_engineSign() throws SignatureException { Curve curve = key.getParams().getCurve(); ScalarOps sc = key.getParams().getScalarOps(); byte[] a = ((EdDSAPrivateKey) key).geta(); GroupElement R = key.getParams().getB().scalarMultiply(r); byte[] Rbyte = R.toByteArray();
public KeyPair generateKeyPair() { if (!initialized) initialize(DEFAULT_KEYSIZE, RandomSource.getInstance()); byte[] seed = new byte[edParams.getCurve().getField().getb()/8]; random.nextBytes(seed); EdDSAPrivateKeySpec privKey = new EdDSAPrivateKeySpec(seed, edParams); EdDSAPublicKeySpec pubKey = new EdDSAPublicKeySpec(privKey.getA(), edParams); return new KeyPair(new EdDSAPublicKey(pubKey), new EdDSAPrivateKey(privKey)); }
@Test public void testVerifyResetsForReuse() throws Exception { EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519); Signature sgr = new EdDSAEngine(MessageDigest.getInstance(spec.getHashAlgorithm())); EdDSAPublicKeySpec pubKey = new EdDSAPublicKeySpec(TEST_PK, spec); PublicKey vKey = new EdDSAPublicKey(pubKey); sgr.initVerify(vKey); // First usage sgr.update(new byte[] {0}); sgr.verify(TEST_MSG_SIG); // Second usage sgr.update(TEST_MSG); assertThat("Second verify failed", sgr.verify(TEST_MSG_SIG), is(true)); }
/** * @since 0.9.25 */ @Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof EdDSAPublicKey)) return false; EdDSAPublicKey pk = (EdDSAPublicKey) o; return Arrays.equals(Abyte, pk.getAbyte()) && edDsaSpec.equals(pk.getParams()); } }
public static boolean compareEDDSAKeyParams(EdDSAParameterSpec s1, EdDSAParameterSpec s2) { if (Objects.equals(s1, s2)) { return true; } else if (s1 == null || s2 == null) { return false; // both null is covered by Objects#equals } else { return Objects.equals(s1.getHashAlgorithm(), s2.getHashAlgorithm()) && Objects.equals(s1.getCurve(), s2.getCurve()) && Objects.equals(s1.getB(), s2.getB()); } }