Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sdk/keyvault/azure-security-keyvault-keys/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
### Bugs Fixed

- Fixed an issue where certain `HttpResponseException.getResponse()` calls could cause a `NullPointerException`. ([#47801](https://github.com/Azure/azure-sdk-for-java/issues/47801))
- Fixed an issue where cryptographic operation results (`SignResult`, `EncryptResult`, `DecryptResult`, `WrapResult`, `UnwrapResult`) returned a versionless key ID instead of the full versioned key ID returned by the service. This caused issues when attempting roundtrip scenarios, as callers couldn't determine which key version was used for the original operation. ([#47822](https://github.com/Azure/azure-sdk-for-java/issues/47822))

### Other Changes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ private Mono<EncryptResult> encryptAsync(EncryptionAlgorithm algorithm, byte[] p
.map(response -> {
KeyOperationResult result = response.getValue().toObject(KeyOperationResult.class);

return new EncryptResult(result.getResult(), algorithm, keyId, result.getIv(),
return new EncryptResult(result.getResult(), algorithm, result.getKid(), result.getIv(),
result.getAuthenticationTag(), result.getAdditionalAuthenticatedData());
});
}
Expand Down Expand Up @@ -191,8 +191,8 @@ private EncryptResult encrypt(EncryptionAlgorithm algorithm, byte[] plainText, b
.getValue()
.toObject(KeyOperationResult.class);

return new EncryptResult(result.getResult(), algorithm, keyId, result.getIv(), result.getAuthenticationTag(),
result.getAdditionalAuthenticatedData());
return new EncryptResult(result.getResult(), algorithm, result.getKid(), result.getIv(),
result.getAuthenticationTag(), result.getAdditionalAuthenticatedData());
}

public Mono<DecryptResult> decryptAsync(EncryptionAlgorithm algorithm, byte[] ciphertext, Context context) {
Expand Down Expand Up @@ -224,7 +224,7 @@ private Mono<DecryptResult> decryptAsync(EncryptionAlgorithm algorithm, byte[] c
.map(response -> {
KeyOperationResult result = response.getValue().toObject(KeyOperationResult.class);

return new DecryptResult(result.getResult(), algorithm, keyId);
return new DecryptResult(result.getResult(), algorithm, result.getKid());
});
}

Expand Down Expand Up @@ -257,7 +257,7 @@ private DecryptResult decrypt(EncryptionAlgorithm algorithm, byte[] ciphertext,
.getValue()
.toObject(KeyOperationResult.class);

return new DecryptResult(result.getResult(), algorithm, keyId);
return new DecryptResult(result.getResult(), algorithm, result.getKid());
}

public Mono<SignResult> signAsync(SignatureAlgorithm algorithm, byte[] digest, Context context) {
Expand All @@ -272,7 +272,7 @@ public Mono<SignResult> signAsync(SignatureAlgorithm algorithm, byte[] digest, C
.map(response -> {
KeyOperationResult result = response.getValue().toObject(KeyOperationResult.class);

return new SignResult(result.getResult(), algorithm, keyId);
return new SignResult(result.getResult(), algorithm, result.getKid());
});
}

Expand All @@ -289,7 +289,7 @@ public SignResult sign(SignatureAlgorithm algorithm, byte[] digest, Context cont
.getValue()
.toObject(KeyOperationResult.class);

return new SignResult(result.getResult(), algorithm, keyId);
return new SignResult(result.getResult(), algorithm, result.getKid());
}

public Mono<VerifyResult> verifyAsync(SignatureAlgorithm algorithm, byte[] digest, byte[] signature,
Expand Down Expand Up @@ -341,7 +341,7 @@ public Mono<WrapResult> wrapKeyAsync(KeyWrapAlgorithm algorithm, byte[] key, Con
.map(response -> {
KeyOperationResult result = response.getValue().toObject(KeyOperationResult.class);

return new WrapResult(result.getResult(), algorithm, keyId);
return new WrapResult(result.getResult(), algorithm, result.getKid());
});
}

Expand All @@ -358,7 +358,7 @@ public WrapResult wrapKey(KeyWrapAlgorithm algorithm, byte[] key, Context contex
.getValue()
.toObject(KeyOperationResult.class);

return new WrapResult(result.getResult(), algorithm, keyId);
return new WrapResult(result.getResult(), algorithm, result.getKid());
}

public Mono<UnwrapResult> unwrapKeyAsync(KeyWrapAlgorithm algorithm, byte[] encryptedKey, Context context) {
Expand All @@ -374,7 +374,7 @@ public Mono<UnwrapResult> unwrapKeyAsync(KeyWrapAlgorithm algorithm, byte[] encr
.map(response -> {
KeyOperationResult result = response.getValue().toObject(KeyOperationResult.class);

return new UnwrapResult(result.getResult(), algorithm, keyId);
return new UnwrapResult(result.getResult(), algorithm, result.getKid());
});
}

Expand All @@ -392,7 +392,7 @@ public UnwrapResult unwrapKey(KeyWrapAlgorithm algorithm, byte[] encryptedKey, C
.getValue()
.toObject(KeyOperationResult.class);

return new UnwrapResult(result.getResult(), algorithm, keyId);
return new UnwrapResult(result.getResult(), algorithm, result.getKid());
}

public Mono<SignResult> signDataAsync(SignatureAlgorithm algorithm, byte[] data, Context context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,23 @@
import com.azure.core.util.logging.ClientLogger;
import com.azure.core.util.logging.LogLevel;
import com.azure.security.keyvault.keys.KeyClient;
import com.azure.security.keyvault.keys.cryptography.models.DecryptResult;
import com.azure.security.keyvault.keys.cryptography.models.EncryptParameters;
import com.azure.security.keyvault.keys.cryptography.models.EncryptResult;
import com.azure.security.keyvault.keys.cryptography.models.EncryptionAlgorithm;
import com.azure.security.keyvault.keys.cryptography.models.KeyWrapAlgorithm;
import com.azure.security.keyvault.keys.cryptography.models.SignResult;
import com.azure.security.keyvault.keys.cryptography.models.SignatureAlgorithm;
import com.azure.security.keyvault.keys.cryptography.models.UnwrapResult;
import com.azure.security.keyvault.keys.cryptography.models.VerifyResult;
import com.azure.security.keyvault.keys.cryptography.models.WrapResult;
import com.azure.security.keyvault.keys.models.CreateEcKeyOptions;
import com.azure.security.keyvault.keys.models.JsonWebKey;
import com.azure.security.keyvault.keys.models.KeyCurveName;
import com.azure.security.keyvault.keys.models.KeyOperation;
import com.azure.security.keyvault.keys.models.KeyVaultKey;
import com.azure.security.keyvault.keys.models.KeyVaultKeyIdentifier;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
Expand All @@ -38,6 +45,8 @@
import static com.azure.security.keyvault.keys.TestUtils.buildSyncAssertingClient;
import static com.azure.security.keyvault.keys.cryptography.TestHelper.DISPLAY_NAME_WITH_ARGUMENTS;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

Expand Down Expand Up @@ -87,15 +96,21 @@ public void encryptDecryptRsa(HttpClient httpClient, CryptographyServiceVersion

new Random(0x1234567L).nextBytes(plaintext);

byte[] ciphertext = cryptoClient.encrypt(algorithm, plaintext).getCipherText();
byte[] decryptedText = cryptoClient.decrypt(algorithm, ciphertext).getPlainText();
EncryptResult encryptResult = cryptoClient.encrypt(algorithm, plaintext);

assertEquals(encryptResult.getAlgorithm(), algorithm);
assertNotNull(encryptResult.getCipherText());

String keyId = encryptResult.getKeyId();

assertNotNull(keyId);

assertArrayEquals(decryptedText, plaintext);
// Ensure the keyId includes the key version
assertNotNull(new KeyVaultKeyIdentifier(keyId).getVersion(), "keyId does not contain key version.");

ciphertext = cryptoClient.encrypt(algorithm, plaintext).getCipherText();
decryptedText = cryptoClient.decrypt(algorithm, ciphertext).getPlainText();
DecryptResult decryptResult = cryptoClient.decrypt(algorithm, encryptResult.getCipherText());

assertArrayEquals(decryptedText, plaintext);
assertArrayEquals(decryptResult.getPlainText(), plaintext);
}
});
}
Expand All @@ -114,10 +129,10 @@ public void encryptDecryptRsaLocal() throws Exception {

new Random(0x1234567L).nextBytes(plainText);

byte[] cipherText = cryptoClient.encrypt(algorithm, plainText).getCipherText();
byte[] decryptedText = cryptoClient.decrypt(algorithm, cipherText).getPlainText();
EncryptResult encryptResult = cryptoClient.encrypt(algorithm, plainText);
DecryptResult decryptResult = cryptoClient.decrypt(algorithm, encryptResult.getCipherText());

assertArrayEquals(decryptedText, plainText);
assertArrayEquals(decryptResult.getPlainText(), plainText);
}
});
}
Expand All @@ -142,17 +157,22 @@ public void wrapUnwrapRsa(HttpClient httpClient, CryptographyServiceVersion serv

new Random(0x1234567L).nextBytes(plaintext);

byte[] encryptedKey = cryptoClient.wrapKey(algorithm, plaintext).getEncryptedKey();
byte[] decryptedKey = cryptoClient.unwrapKey(algorithm, encryptedKey).getKey();
WrapResult wrapResult = cryptoClient.wrapKey(algorithm, plaintext);

assertArrayEquals(decryptedKey, plaintext);
assertEquals(wrapResult.getAlgorithm(), algorithm);
assertNotNull(wrapResult.getEncryptedKey());

encryptedKey = cryptoClient.wrapKey(algorithm, plaintext).getEncryptedKey();
decryptedKey = cryptoClient.unwrapKey(algorithm, encryptedKey).getKey();
String keyId = wrapResult.getKeyId();

assertArrayEquals(decryptedKey, plaintext);
}
assertNotNull(keyId);

// Ensure the keyId includes the key version
assertNotNull(new KeyVaultKeyIdentifier(keyId).getVersion(), "keyId does not contain key version.");

UnwrapResult unwrapResult = cryptoClient.unwrapKey(algorithm, wrapResult.getEncryptedKey());

assertArrayEquals(unwrapResult.getKey(), plaintext);
}
});
}

Expand All @@ -169,12 +189,11 @@ public void wrapUnwrapRsaLocal() throws Exception {

new Random(0x1234567L).nextBytes(plainText);

byte[] encryptedKey = cryptoClient.wrapKey(algorithm, plainText).getEncryptedKey();
byte[] decryptedKey = cryptoClient.unwrapKey(algorithm, encryptedKey).getKey();
WrapResult wrapResult = cryptoClient.wrapKey(algorithm, plainText);
UnwrapResult unwrapResult = cryptoClient.unwrapKey(algorithm, wrapResult.getEncryptedKey());

assertArrayEquals(decryptedKey, plainText);
assertArrayEquals(unwrapResult.getKey(), plainText);
}

});
}

Expand Down Expand Up @@ -208,6 +227,16 @@ public void signVerifyEc(HttpClient httpClient, CryptographyServiceVersion servi

SignResult signResult = cryptographyClient.sign(curveToSignature.get(curve), digest);

assertEquals(signResult.getAlgorithm(), curveToSignature.get(curve));
assertNotNull(signResult.getSignature());

String keyId = signResult.getKeyId();

assertNotNull(keyId);

// Ensure the keyId includes the key version
assertNotNull(new KeyVaultKeyIdentifier(keyId).getVersion(), "keyId does not contain key version.");

Boolean verifyStatus
= cryptographyClient.verify(curveToSignature.get(curve), digest, signResult.getSignature())
.isValid();
Expand Down Expand Up @@ -239,10 +268,21 @@ public void signDataVerifyEc(HttpClient httpClient, CryptographyServiceVersion s

new Random(0x1234567L).nextBytes(plaintext);

byte[] signature = cryptographyClient.signData(curveToSignature.get(curve), plaintext).getSignature();
SignResult signResult = cryptographyClient.signData(curveToSignature.get(curve), plaintext);

assertEquals(signResult.getAlgorithm(), curveToSignature.get(curve));
assertNotNull(signResult.getSignature());

String keyId = signResult.getKeyId();

assertNotNull(keyId);

// Ensure the keyId includes the key version
assertNotNull(new KeyVaultKeyIdentifier(keyId).getVersion(), "keyId does not contain key version.");

Boolean verifyStatus
= cryptographyClient.verifyData(curveToSignature.get(curve), plaintext, signature).isValid();
= cryptographyClient.verifyData(curveToSignature.get(curve), plaintext, signResult.getSignature())
.isValid();

assertTrue(verifyStatus);
});
Expand Down Expand Up @@ -281,9 +321,20 @@ public void signVerifyRsa(HttpClient httpClient, CryptographyServiceVersion serv
byte[] digest = md.digest();

SignResult signResult = cryptoClient.sign(algorithm, digest);
Boolean verifyStatus = cryptoClient.verify(algorithm, digest, signResult.getSignature()).isValid();

assertTrue(verifyStatus);
assertEquals(signResult.getAlgorithm(), algorithm);
assertNotNull(signResult.getSignature());

String keyId = signResult.getKeyId();

assertNotNull(keyId);

// Ensure the keyId includes the key version
assertNotNull(new KeyVaultKeyIdentifier(keyId).getVersion(), "keyId does not contain key version.");

VerifyResult verifyResult = cryptoClient.verify(algorithm, digest, signResult.getSignature());

assertTrue(verifyResult.isValid());
} catch (NoSuchAlgorithmException e) {
fail(e);
}
Expand All @@ -310,10 +361,21 @@ public void signDataVerifyRsa(HttpClient httpClient, CryptographyServiceVersion

new Random(0x1234567L).nextBytes(plaintext);

byte[] signature = cryptoClient.signData(algorithm, plaintext).getSignature();
Boolean verifyStatus = cryptoClient.verifyData(algorithm, plaintext, signature).isValid();
SignResult signResult = cryptoClient.signData(algorithm, plaintext);

assertTrue(verifyStatus);
assertEquals(signResult.getAlgorithm(), algorithm);
assertNotNull(signResult.getSignature());

String keyId = signResult.getKeyId();

assertNotNull(keyId);

// Ensure the keyId includes the key version
assertNotNull(new KeyVaultKeyIdentifier(keyId).getVersion(), "keyId does not contain key version.");

VerifyResult verifyResult = cryptoClient.verifyData(algorithm, plaintext, signResult.getSignature());

assertTrue(verifyResult.isValid());
}
});
}
Expand Down Expand Up @@ -369,11 +431,11 @@ public void signDataVerifyEcLocal() {

new Random(0x1234567L).nextBytes(plainText);

byte[] signature = cryptographyClient.signData(curveToSignature.get(curve), plainText).getSignature();
Boolean verifyStatus
= cryptographyClient.verifyData(curveToSignature.get(curve), plainText, signature).isValid();
SignResult signResult = cryptographyClient.signData(curveToSignature.get(curve), plainText);
VerifyResult verifyResult
= cryptographyClient.verifyData(curveToSignature.get(curve), plainText, signResult.getSignature());

assertTrue(verifyStatus);
assertTrue(verifyResult.isValid());
});
}

Expand Down