Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 4 additions & 2 deletions sdk/src/main/java/io/opentdf/platform/sdk/ECKeyPair.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@

public class ECKeyPair {

private static final int SHA256_BYTES = 32;

static {
Security.addProvider(new BouncyCastleProvider());
}
Expand Down Expand Up @@ -233,8 +235,8 @@ public static byte[] computeECDHKey(ECPublicKey publicKey, ECPrivateKey privateK
}
}

public static byte[] calculateHKDF(byte[] salt, byte[] secret) {
byte[] key = new byte[secret.length];
public static byte[] calculateSHA256HKDF(byte[] salt, byte[] secret) {
byte[] key = new byte[SHA256_BYTES];
HKDFParameters params = new HKDFParameters(secret, salt, null);

HKDFBytesGenerator hkdf = new HKDFBytesGenerator(SHA256Digest.newInstance());
Expand Down
4 changes: 2 additions & 2 deletions sdk/src/main/java/io/opentdf/platform/sdk/KASClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ public byte[] unwrap(Manifest.KeyAccess keyAccess, String policy, KeyType sessi
var publicKey = ECKeyPair.publicKeyFromPem(kasEphemeralPublicKey);
byte[] symKey = ECKeyPair.computeECDHKey(publicKey, ecKeyPair.getPrivateKey());

var sessionKey = ECKeyPair.calculateHKDF(GLOBAL_KEY_SALT, symKey);
var sessionKey = ECKeyPair.calculateSHA256HKDF(GLOBAL_KEY_SALT, symKey);

AesGcm gcm = new AesGcm(sessionKey);
AesGcm.Encrypted encrypted = new AesGcm.Encrypted(wrappedKey);
Expand Down Expand Up @@ -278,7 +278,7 @@ public byte[] unwrapNanoTDF(NanoTDFType.ECCurve curve, String header, String kas
throw new SDKException("error creating SHA-256 message digest", e);
}
byte[] hashOfSalt = digest.digest(NanoTDF.MAGIC_NUMBER_AND_VERSION);
byte[] key = ECKeyPair.calculateHKDF(hashOfSalt, symmetricKey);
byte[] key = ECKeyPair.calculateSHA256HKDF(hashOfSalt, symmetricKey);

AesGcm gcm = new AesGcm(key);
AesGcm.Encrypted encrypted = new AesGcm.Encrypted(wrappedKey);
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/main/java/io/opentdf/platform/sdk/NanoTDF.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ private Config.HeaderInfo getHeaderInfo(Config.NanoTDFConfig nanoTDFConfig) thro
throw new SDKException("error getting instance of SHA-256 digest", e);
}
byte[] hashOfSalt = digest.digest(MAGIC_NUMBER_AND_VERSION);
byte[] key = ECKeyPair.calculateHKDF(hashOfSalt, symmetricKey);
byte[] key = ECKeyPair.calculateSHA256HKDF(hashOfSalt, symmetricKey);

// Encrypt policy
PolicyObject policyObject = createPolicyObject(nanoTDFConfig.attributes);
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/main/java/io/opentdf/platform/sdk/TDF.java
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ private ECKeyWrappedKeyInfo createECWrappedKey(Config.TDFConfig tdfConfig, Confi
ECPublicKey kasPubKey = ECKeyPair.publicKeyFromPem(kasInfo.PublicKey);
byte[] symmetricKey = ECKeyPair.computeECDHKey(kasPubKey, keyPair.getPrivateKey());

var sessionKey = ECKeyPair.calculateHKDF(GLOBAL_KEY_SALT, symmetricKey);
var sessionKey = ECKeyPair.calculateSHA256HKDF(GLOBAL_KEY_SALT, symmetricKey);

AesGcm gcm = new AesGcm(sessionKey);
AesGcm.Encrypted wrappedKey = gcm.encrypt(symKey);
Expand Down
20 changes: 17 additions & 3 deletions sdk/src/test/java/io/opentdf/platform/sdk/ECKeyPairTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.util.Base64;

import static io.opentdf.platform.sdk.NanoTDFType.ECCurve.SECP256R1;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;

Expand Down Expand Up @@ -114,9 +115,22 @@ void extractPemPubKeyFromX509() throws CertificateException, IOException, NoSuch
byte[] symmetricKey = ECKeyPair.computeECDHKey(publicKey, ECKeyPair.privateKeyFromPem(keypairPrivateKey));
System.out.println(Arrays.toString(symmetricKey));

byte[] key = ECKeyPair.calculateHKDF(ECKeys.salt.getBytes(StandardCharsets.UTF_8), symmetricKey);
byte[] key = ECKeyPair.calculateSHA256HKDF(ECKeys.salt.getBytes(StandardCharsets.UTF_8), symmetricKey);
System.out.println(Arrays.toString(key));
System.out.println(key.length);

assertThat(key.length).isEqualTo(32); // SHA-256 produces a 32-byte key
}

@Test
void createSymmetricKeysWithOtherC() {
ECKeyPair pubPair = new ECKeyPair(NanoTDFType.ECCurve.SECP384R1, ECKeyPair.ECAlgorithm.ECDH);
ECKeyPair keyPair = new ECKeyPair(NanoTDFType.ECCurve.SECP384R1, ECKeyPair.ECAlgorithm.ECDH);

byte[] sharedSecret = ECKeyPair.computeECDHKey(pubPair.getPublicKey(), keyPair.getPrivateKey());
byte[] encryptionKey = ECKeyPair.calculateSHA256HKDF(ECKeys.salt.getBytes(StandardCharsets.UTF_8), sharedSecret);

assertThat(encryptionKey).hasSize(32); // SHA-256 produces a 32-byte key
}

@Test
Expand All @@ -131,13 +145,13 @@ void testECDH() {
ECPrivateKey sdkPriKey = ECKeyPair.privateKeyFromPem(ECKeys.sdkPrivateKey);

byte[] symmetricKey = ECKeyPair.computeECDHKey(kasPubKey, sdkPriKey);
byte[] key = ECKeyPair.calculateHKDF(ECKeys.salt.getBytes(StandardCharsets.UTF_8), symmetricKey);
byte[] key = ECKeyPair.calculateSHA256HKDF(ECKeys.salt.getBytes(StandardCharsets.UTF_8), symmetricKey);
String encodedKey = Base64.getEncoder().encodeToString(key);
assertEquals(encodedKey, expectedKey);

// KAS side
symmetricKey = ECKeyPair.computeECDHKey(sdkPubKey, kasPriKey);
key = ECKeyPair.calculateHKDF(ECKeys.salt.getBytes(StandardCharsets.UTF_8), symmetricKey);
key = ECKeyPair.calculateSHA256HKDF(ECKeys.salt.getBytes(StandardCharsets.UTF_8), symmetricKey);
encodedKey = Base64.getEncoder().encodeToString(key);
assertEquals(encodedKey, expectedKey);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ public void testNanoTDFEncryption()
byte[] secret = ECKeyPair.computeECDHKey(ECKeyPair.publicKeyFromPem(kasPublicKey),
ECKeyPair.privateKeyFromPem(sdkPrivateKeyForEncrypt));
byte[] saltValue = { 'V', 'I', 'R', 'T', 'R', 'U' };
encryptKey = ECKeyPair.calculateHKDF(saltValue, secret);
encryptKey = ECKeyPair.calculateSHA256HKDF(saltValue, secret);

// Encrypt the policy with key from KDF
int encryptedPayLoadSize = policy.length() + nanoTDFIvSize + tagSize;
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/test/java/io/opentdf/platform/sdk/NanoTDFTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public byte[] unwrapNanoTDF(NanoTDFType.ECCurve curve, String header, String kas
throw new SDKException("error creating SHA-256 message digest", e);
}
byte[] hashOfSalt = digest.digest(NanoTDF.MAGIC_NUMBER_AND_VERSION);
byte[] key = ECKeyPair.calculateHKDF(hashOfSalt, symmetricKey);
byte[] key = ECKeyPair.calculateSHA256HKDF(hashOfSalt, symmetricKey);
return key;
}

Expand Down
2 changes: 1 addition & 1 deletion sdk/src/test/java/io/opentdf/platform/sdk/TDFTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public byte[] unwrap(Manifest.KeyAccess keyAccess, String policy, KeyType sessio
var publicKey = ECKeyPair.publicKeyFromPem(clientEphemeralPublicKey);
byte[] symKey = ECKeyPair.computeECDHKey(publicKey, privateKey);

var sessionKey = ECKeyPair.calculateHKDF(GLOBAL_KEY_SALT, symKey);
var sessionKey = ECKeyPair.calculateSHA256HKDF(GLOBAL_KEY_SALT, symKey);

AesGcm gcm = new AesGcm(sessionKey);
AesGcm.Encrypted encrypted = new AesGcm.Encrypted(bytes);
Expand Down