use of io.nem.symbol.core.crypto.CryptoException 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.CryptoException in project nem2-sdk-java by nemtech.
the class AESGCM method encrypt.
/**
* Encrypts the specified plain text using AES/GCM/NoPadding.
*
* @param secretKey The AES key. Must not be {@code null}.
* @param plainText The plain text. Must not be {@code null}.
* @param iv The initialisation vector (IV). Must not be {@code null}.
* @return The authenticated cipher text.
* @throws CryptoException If encryption failed.
*/
public static AuthenticatedCipherText encrypt(final byte[] secretKey, final byte[] iv, final byte[] plainText) throws RuntimeException {
// Initialise AES/GCM cipher for encryption
GCMBlockCipher cipher = createAESGCMCipher(secretKey, true, iv);
// Prepare output buffer
int outputLength = cipher.getOutputSize(plainText.length);
byte[] output = new byte[outputLength];
// Produce cipher text
int outputOffset = cipher.processBytes(plainText, 0, plainText.length, output, 0);
// Produce authentication tag
try {
outputOffset += cipher.doFinal(output, outputOffset);
} catch (InvalidCipherTextException e) {
throw new CryptoException("Could Not Generate GCM Authentication: " + ExceptionUtils.getMessage(e), e);
}
// Split output into cipher text and authentication tag
int authTagLength = AUTH_TAG_BIT_LENGTH / 8;
byte[] cipherText = new byte[outputOffset - authTagLength];
byte[] authTag = new byte[authTagLength];
System.arraycopy(output, 0, cipherText, 0, cipherText.length);
System.arraycopy(output, outputOffset - authTagLength, authTag, 0, authTag.length);
return new AuthenticatedCipherText(cipherText, authTag, iv);
}
use of io.nem.symbol.core.crypto.CryptoException in project nem2-sdk-java by nemtech.
the class AESGCM method decrypt.
/**
* Decrypts the specified cipher text using AES/GCM/NoPadding.
*
* @param secretKey The AES key. Must not be {@code null}.
* @param iv The initialisation vector (IV). Must not be {@code null}.
* @param cipherText The cipher text. Must not be {@code null}.
* @param authTag The authentication tag. Must not be {@code null}.
* @return The decrypted plain text.
* @throws CryptoException If decryption failed.
*/
public static byte[] decrypt(final byte[] secretKey, final byte[] iv, final byte[] cipherText, final byte[] authTag) throws RuntimeException {
// Initialise AES/GCM cipher for decryption
GCMBlockCipher cipher = createAESGCMCipher(secretKey, false, iv);
// Join cipher text and authentication tag to produce cipher input
byte[] input = new byte[cipherText.length + authTag.length];
System.arraycopy(cipherText, 0, input, 0, cipherText.length);
System.arraycopy(authTag, 0, input, cipherText.length, authTag.length);
int outputLength = cipher.getOutputSize(input.length);
byte[] output = new byte[outputLength];
// Decrypt
int outputOffset = cipher.processBytes(input, 0, input.length, output, 0);
// Validate authentication tag
try {
outputOffset += cipher.doFinal(output, outputOffset);
} catch (InvalidCipherTextException e) {
throw new CryptoException("Could decrypt value: " + ExceptionUtils.getMessage(e), e);
}
return output;
}
use of io.nem.symbol.core.crypto.CryptoException in project nem2-sdk-java by nemtech.
the class Ed25519BlockCipherTest method decryptFailsInputIsTooSmallInLength.
@Test
public void decryptFailsInputIsTooSmallInLength() {
// Arrange:
final CryptoEngine engine = this.getCryptoEngine();
final KeyPair kp = KeyPair.random(engine);
final BlockCipher blockCipher = this.getBlockCipher(kp, kp);
// Act:
CryptoException exception = Assertions.assertThrows(CryptoException.class, () -> blockCipher.decrypt(new byte[27]));
// Assert:
Assertions.assertEquals("Cannot decrypt input. Size is 27 when at least 28 is expected.", exception.getMessage());
}
use of io.nem.symbol.core.crypto.CryptoException in project nem2-sdk-java by nemtech.
the class Ed25519BlockCipherTest method decryptFailsIfInputIsNull.
@Test
public void decryptFailsIfInputIsNull() {
// Arrange:
final CryptoEngine engine = this.getCryptoEngine();
final KeyPair kp = KeyPair.random(engine);
final BlockCipher blockCipher = this.getBlockCipher(kp, kp);
// Act:
CryptoException exception = Assertions.assertThrows(CryptoException.class, () -> blockCipher.decrypt(null));
// Assert:
Assertions.assertEquals("Cannot decrypt. Input is required.", exception.getMessage());
}
Aggregations