### Question:
Ed25519DsaSigner implements DsaSigner { @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; final byte[] hash = hasher32.hash(this.getKeyPair().getPrivateKey().getBytes()); final Ed25519EncodedFieldElement r = new Ed25519EncodedFieldElement( hasher64.hash( Arrays.copyOfRange(hash, 32, 64), data)); final Ed25519EncodedFieldElement rModQ = r.modQ(); final Ed25519GroupElement R = Ed25519Group.BASE_POINT.scalarMultiply(rModQ); final Ed25519EncodedGroupElement encodedR = R.encode(); 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); final Signature signature = new Signature(encodedR.getRaw(), encodedS.getRaw()); if (!this.isCanonicalSignature(signature)) { throw new CryptoException("Generated signature is not canonical"); } return signature; } Ed25519DsaSigner(final KeyPair keyPair); KeyPair getKeyPair(); @Override @SuppressWarnings("squid:S00117") Signature sign(final byte[] data); @Override boolean verify(final byte[] data, final Signature signature); @Override boolean isCanonicalSignature(final Signature signature); @Override Signature makeSignatureCanonical(final Signature signature);  }### Answer:
@Test public void signReturnsExpectedSignature() { final CryptoEngine engine = this.getCryptoEngine(); final KeyPair keyPair = KeyPair.random(engine); for (int i = 0; i < 20; i++) { final DsaSigner dsaSigner = this.getDsaSigner(keyPair); final byte[] input = RandomUtils.generateRandomBytes(); final Signature signature1 = dsaSigner.sign(input); final Signature signature2 = MathUtils.sign(keyPair, input); Assertions.assertEquals(signature1, signature2); } }
@Test public void signThrowsIfGeneratedSignatureIsNotCanonical() { final CryptoEngine engine = this.getCryptoEngine(); final KeyPair keyPair = KeyPair.random(engine); final Ed25519DsaSigner dsaSigner = new Ed25519DsaSigner(keyPair) { @Override public boolean isCanonicalSignature(Signature signature) { return false; } }; final byte[] input = RandomUtils.generateRandomBytes(); Assertions.assertEquals( "Generated signature is not canonical", Assertions.assertThrows(CryptoException.class, () -> dsaSigner.sign(input)).getMessage()); }