use of io.nem.symbol.core.crypto.ed25519.arithmetic.Ed25519EncodedGroupElement in project nem2-sdk-java by nemtech.
the class Ed25519BlockCipher method getSharedKey.
private byte[] getSharedKey(final PrivateKey privateKey, final PublicKey publicKey, final byte[] salt) {
final Ed25519GroupElement senderA = new Ed25519EncodedGroupElement(publicKey.getRaw()).decode();
senderA.precomputeForScalarMultiplication();
final byte[] sharedKey = senderA.scalarMultiply(Ed25519Utils.prepareForScalarMultiply(privateKey)).encode().getRaw();
for (int i = 0; i < this.keyLength; i++) {
sharedKey[i] ^= salt[i];
}
return Hashes.sha3_256(sharedKey);
}
use of io.nem.symbol.core.crypto.ed25519.arithmetic.Ed25519EncodedGroupElement in project nem2-sdk-java by nemtech.
the class Ed25519DsaSigner method verify.
@Override
public boolean verify(final byte[] data, final Signature signature) {
if (!this.isCanonicalSignature(signature)) {
return false;
}
if (1 == ArrayUtils.isEqualConstantTime(this.getKeyPair().getPublicKey().getRaw(), new byte[32])) {
return false;
}
// h = H(encodedR, encodedA, data).
final byte[] rawEncodedR = signature.getBinaryR();
final byte[] rawEncodedA = this.getKeyPair().getPublicKey().getRaw();
final Ed25519EncodedFieldElement h = new Ed25519EncodedFieldElement(Hashes.sha3_512(rawEncodedR, rawEncodedA, data));
// hReduced = h mod group order
final Ed25519EncodedFieldElement hModQ = h.modQ();
// Must compute A.
final Ed25519GroupElement A = new Ed25519EncodedGroupElement(rawEncodedA).decode();
A.precomputeForDoubleScalarMultiplication();
// R = encodedS * B - H(encodedR, encodedA, data) * A
final Ed25519GroupElement calculatedR = Ed25519Group.BASE_POINT.doubleScalarMultiplyVariableTime(A, hModQ, new Ed25519EncodedFieldElement(signature.getBinaryS()));
// Compare calculated R to given R.
final byte[] encodedCalculatedR = calculatedR.encode().getRaw();
final int result = ArrayUtils.isEqualConstantTime(encodedCalculatedR, rawEncodedR);
return 1 == result;
}
use of io.nem.symbol.core.crypto.ed25519.arithmetic.Ed25519EncodedGroupElement in project nem2-sdk-java by nemtech.
the class Ed25519DsaSigner method sign.
@Override
@SuppressWarnings("squid:S00117")
public Signature sign(final byte[] data) {
if (!this.getKeyPair().hasPrivateKey()) {
throw new CryptoException("cannot sign without private key");
}
Hasher hasher32 = Hashes::sha512;
Hasher hasher64 = Hashes::sha512;
// Hash the private key to improve randomness.
final byte[] hash = hasher32.hash(this.getKeyPair().getPrivateKey().getBytes());
// r = H(hash_b,...,hash_2b-1, data) where b=256.
final Ed25519EncodedFieldElement r = new Ed25519EncodedFieldElement(hasher64.hash(// only
Arrays.copyOfRange(hash, 32, 64), // key hash
data));
// Reduce size of r since we are calculating mod group order anyway
final Ed25519EncodedFieldElement rModQ = r.modQ();
// R = rModQ * base point.
final Ed25519GroupElement R = Ed25519Group.BASE_POINT.scalarMultiply(rModQ);
final Ed25519EncodedGroupElement encodedR = R.encode();
// S = (r + H(encodedR, encodedA, data) * a) mod group order where
// encodedR and encodedA are the little endian encodings of the group element R
// and the
// public
// key A and
// a is the lower 32 bytes of hash after clamping.
final Ed25519EncodedFieldElement h = new Ed25519EncodedFieldElement(hasher64.hash(encodedR.getRaw(), this.getKeyPair().getPublicKey().getBytes(), data));
final Ed25519EncodedFieldElement hModQ = h.modQ();
final Ed25519EncodedFieldElement encodedS = hModQ.multiplyAndAddModQ(Ed25519Utils.prepareForScalarMultiply(this.getKeyPair().getPrivateKey()), rModQ);
// Signature is (encodedR, encodedS)
final Signature signature = new Signature(encodedR.getRaw(), encodedS.getRaw());
if (!this.isCanonicalSignature(signature)) {
throw new CryptoException("Generated signature is not canonical");
}
return signature;
}
use of io.nem.symbol.core.crypto.ed25519.arithmetic.Ed25519EncodedGroupElement in project nem2-sdk-java by nemtech.
the class Ed25519DsaSigner method verify.
@Override
public boolean verify(final byte[] data, final Signature signature) {
if (!this.isCanonicalSignature(signature)) {
return false;
}
if (1 == ArrayUtils.isEqualConstantTime(this.getKeyPair().getPublicKey().getBytes(), new byte[32])) {
return false;
}
Hasher hasher64 = Hashes::sha512;
// h = H(encodedR, encodedA, data).
final byte[] rawEncodedR = signature.getBinaryR();
final byte[] rawEncodedA = this.getKeyPair().getPublicKey().getBytes();
final Ed25519EncodedFieldElement h = new Ed25519EncodedFieldElement(hasher64.hash(rawEncodedR, rawEncodedA, data));
// hReduced = h mod group order
final Ed25519EncodedFieldElement hModQ = h.modQ();
// Must compute A.
final Ed25519GroupElement a = new Ed25519EncodedGroupElement(rawEncodedA).decode();
a.precomputeForDoubleScalarMultiplication();
// R = encodedS * B - H(encodedR, encodedA, data) * A
final Ed25519GroupElement calculatedR = Ed25519Group.BASE_POINT.doubleScalarMultiplyVariableTime(a, hModQ, new Ed25519EncodedFieldElement(signature.getBinaryS()));
// Compare calculated R to given R.
final byte[] encodedCalculatedR = calculatedR.encode().getRaw();
final int result = ArrayUtils.isEqualConstantTime(encodedCalculatedR, rawEncodedR);
return 1 == result;
}
use of io.nem.symbol.core.crypto.ed25519.arithmetic.Ed25519EncodedGroupElement in project nem2-sdk-java by nemtech.
the class Ed25519KeyGeneratorTest method derivedPublicKeyIsValidPointOnCurve.
@Test
public void derivedPublicKeyIsValidPointOnCurve() {
// Arrange:
final KeyGenerator generator = this.getKeyGenerator();
for (int i = 0; i < 100; i++) {
final KeyPair kp = generator.generateKeyPair();
// Act:
final PublicKey publicKey = generator.derivePublicKey(kp.getPrivateKey());
// Assert (throws if not on the curve):
new Ed25519EncodedGroupElement(publicKey.getRaw()).decode();
}
}
Aggregations