/** * @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"); } }
/** * 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); }
GroupElement R = key.getParams().getB().scalarMultiply(r); byte[] Rbyte = R.toByteArray();
@Test public void scalarMultiplyBasePointWithOneReturnsBasePoint() { // Arrange: final GroupElement basePoint = ed25519.getB(); // Act: final GroupElement g = basePoint.scalarMultiply(curve.getField().ONE.toByteArray()); // Assert: Assert.assertThat(basePoint, IsEqual.equalTo(g)); }
/** * Test method for {@link GroupElement#scalarMultiply(byte[])}. * Test values generated with Python Ed25519 implementation. */ @Test public void testScalarMultiplyByteArray() { // Little-endian byte[] zero = Utils.hexToBytes("0000000000000000000000000000000000000000000000000000000000000000"); byte[] one = Utils.hexToBytes("0100000000000000000000000000000000000000000000000000000000000000"); byte[] two = Utils.hexToBytes("0200000000000000000000000000000000000000000000000000000000000000"); byte[] a = Utils.hexToBytes("d072f8dd9c07fa7bc8d22a4b325d26301ee9202f6db89aa7c3731529e37e437c"); GroupElement A = new GroupElement(curve, Utils.hexToBytes("d4cf8595571830644bd14af416954d09ab7159751ad9e0f7a6cbd92379e71a66")); assertThat("scalarMultiply(0) failed", ed25519.getB().scalarMultiply(zero), is(equalTo(curve.getZero(GroupElement.Representation.P3)))); assertThat("scalarMultiply(1) failed", ed25519.getB().scalarMultiply(one), is(equalTo(ed25519.getB()))); assertThat("scalarMultiply(2) failed", ed25519.getB().scalarMultiply(two), is(equalTo(ed25519.getB().dbl()))); assertThat("scalarMultiply(a) failed", ed25519.getB().scalarMultiply(a), is(equalTo(A))); }
@Test public void scalarMultiplyBasePointWithZeroReturnsNeutralElement() { // Arrange: final GroupElement basePoint = ed25519.getB(); // Act: final GroupElement g = basePoint.scalarMultiply(curve.getField().ZERO.toByteArray()); // Assert: Assert.assertThat(curve.getZero(GroupElement.Representation.P3), IsEqual.equalTo(g)); }
@Test public void scalarMultiplyBasePointReturnsExpectedResult() { for (int i=0; i<10; i++) { // Arrange: final GroupElement basePoint = ed25519.getB(); final FieldElement f = MathUtils.getRandomFieldElement(); // Act: final GroupElement g = basePoint.scalarMultiply(f.toByteArray()); final GroupElement h = MathUtils.scalarMultiplyGroupElement(basePoint, f); // Assert: Assert.assertThat(g, IsEqual.equalTo(h)); } }
/** * @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); }
GroupElement R = key.getParams().getB().scalarMultiply(r); byte[] Rbyte = R.toByteArray();