diff options
author | ioannanedelcu <ioannanedelcu@google.com> | 2023-08-07 01:26:51 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-08-07 01:27:59 -0700 |
commit | 8f20e13e02d77cff41d94837bdaeac2e146ff143 (patch) | |
tree | 8d8098bfd30857c55b1c98286591a4e7d1a14b4f /java_src/src/test/java | |
parent | 8e84baffd9c94b3dbb561633a8ebf58dae961c52 (diff) | |
download | tink-8f20e13e02d77cff41d94837bdaeac2e146ff143.tar.gz |
Add serialization for Ecies Private Keys.
PiperOrigin-RevId: 554395954
Diffstat (limited to 'java_src/src/test/java')
-rw-r--r-- | java_src/src/test/java/com/google/crypto/tink/hybrid/BUILD.bazel | 3 | ||||
-rw-r--r-- | java_src/src/test/java/com/google/crypto/tink/hybrid/EciesProtoSerializationTest.java | 273 |
2 files changed, 276 insertions, 0 deletions
diff --git a/java_src/src/test/java/com/google/crypto/tink/hybrid/BUILD.bazel b/java_src/src/test/java/com/google/crypto/tink/hybrid/BUILD.bazel index 5ce9ce2dd..8b23db591 100644 --- a/java_src/src/test/java/com/google/crypto/tink/hybrid/BUILD.bazel +++ b/java_src/src/test/java/com/google/crypto/tink/hybrid/BUILD.bazel @@ -392,6 +392,7 @@ java_test( "//src/main/java/com/google/crypto/tink/aead:aead_config", "//src/main/java/com/google/crypto/tink/aead:x_cha_cha20_poly1305_parameters", "//src/main/java/com/google/crypto/tink/hybrid:ecies_parameters", + "//src/main/java/com/google/crypto/tink/hybrid:ecies_private_key", "//src/main/java/com/google/crypto/tink/hybrid:ecies_proto_serialization", "//src/main/java/com/google/crypto/tink/hybrid:ecies_public_key", "//src/main/java/com/google/crypto/tink/internal:key_template_proto_converter", @@ -404,6 +405,8 @@ java_test( "//src/main/java/com/google/crypto/tink/subtle:random", "//src/main/java/com/google/crypto/tink/subtle:x25519", "//src/main/java/com/google/crypto/tink/util:bytes", + "//src/main/java/com/google/crypto/tink/util:secret_big_integer", + "//src/main/java/com/google/crypto/tink/util:secret_bytes", "@maven//:com_google_code_findbugs_jsr305", "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_truth_truth", diff --git a/java_src/src/test/java/com/google/crypto/tink/hybrid/EciesProtoSerializationTest.java b/java_src/src/test/java/com/google/crypto/tink/hybrid/EciesProtoSerializationTest.java index a2ef28f6e..f2b601172 100644 --- a/java_src/src/test/java/com/google/crypto/tink/hybrid/EciesProtoSerializationTest.java +++ b/java_src/src/test/java/com/google/crypto/tink/hybrid/EciesProtoSerializationTest.java @@ -35,6 +35,7 @@ import com.google.crypto.tink.proto.EcPointFormat; import com.google.crypto.tink.proto.EciesAeadDemParams; import com.google.crypto.tink.proto.EciesAeadHkdfKeyFormat; import com.google.crypto.tink.proto.EciesAeadHkdfParams; +import com.google.crypto.tink.proto.EciesAeadHkdfPrivateKey; import com.google.crypto.tink.proto.EciesAeadHkdfPublicKey; import com.google.crypto.tink.proto.EciesHkdfKemParams; import com.google.crypto.tink.proto.EllipticCurveType; @@ -47,6 +48,8 @@ import com.google.crypto.tink.subtle.Hex; import com.google.crypto.tink.subtle.Random; import com.google.crypto.tink.subtle.X25519; import com.google.crypto.tink.util.Bytes; +import com.google.crypto.tink.util.SecretBigInteger; +import com.google.crypto.tink.util.SecretBytes; import com.google.protobuf.ByteString; import java.math.BigInteger; import java.security.GeneralSecurityException; @@ -865,4 +868,274 @@ public final class EciesProtoSerializationTest { GeneralSecurityException.class, () -> registry.parseKey(serialization, InsecureSecretKeyAccess.get())); } + + // PRIVATE KEY SERIALIZATION ===================================================================== + @Test + public void serializeParseNistPrivateKey_works() throws Exception { + String hexX = "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6"; + String hexY = "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299"; + String hexPrivateValue = "C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721"; + + // Java object + EciesParameters parameters = + EciesParameters.builder() + .setCurveType(EciesParameters.CurveType.NIST_P256) + .setHashType(EciesParameters.HashType.SHA256) + .setNistCurvePointFormat(EciesParameters.PointFormat.COMPRESSED) + .setVariant(EciesParameters.Variant.TINK) + .setDemParameters(DEM_PARAMETERS) + .setSalt(SALT) + .build(); + EciesPublicKey publicKey = + EciesPublicKey.createForNistCurve( + parameters, new ECPoint(new BigInteger(hexX, 16), new BigInteger(hexY, 16)), 101); + EciesPrivateKey privateKey = + EciesPrivateKey.createForNistCurve( + publicKey, + SecretBigInteger.fromBigInteger( + new BigInteger(hexPrivateValue, 16), InsecureSecretKeyAccess.get())); + + // Proto object + EciesAeadHkdfPublicKey protoPublicKey = + EciesAeadHkdfPublicKey.newBuilder() + .setVersion(0) + .setParams( + validParamsForCurve(com.google.crypto.tink.proto.EllipticCurveType.NIST_P256)) + .setX(ByteString.copyFrom(Hex.decode("00" + hexX))) + .setY(ByteString.copyFrom(Hex.decode("00" + hexY))) + .build(); + EciesAeadHkdfPrivateKey protoPrivateKey = + EciesAeadHkdfPrivateKey.newBuilder() + .setVersion(0) + .setPublicKey(protoPublicKey) + // privateValue is currently serialized with an extra zero at the beginning. + .setKeyValue(ByteString.copyFrom(Hex.decode("00" + hexPrivateValue))) + .build(); + ProtoKeySerialization serialization = + ProtoKeySerialization.create( + "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey", + protoPrivateKey.toByteString(), + KeyMaterialType.ASYMMETRIC_PRIVATE, + OutputPrefixType.TINK, + /* idRequirement= */ 101); + + // Comparison + Key parsed = registry.parseKey(serialization, InsecureSecretKeyAccess.get()); + assertThat(parsed.equalsKey(privateKey)).isTrue(); + + ProtoKeySerialization serialized = + registry.serializeKey( + privateKey, ProtoKeySerialization.class, InsecureSecretKeyAccess.get()); + + assertEqualWhenValueParsed(EciesAeadHkdfPublicKey.parser(), serialized, serialization); + } + + @Test + public void serializeParseX25519PrivateKey_works() throws Exception { + byte[] privateKeyBytes = X25519.generatePrivateKey(); + byte[] publicKeyBytes = X25519.publicFromPrivate(privateKeyBytes); + + // Java object + EciesParameters parameters = + EciesParameters.builder() + .setCurveType(EciesParameters.CurveType.X25519) + .setHashType(EciesParameters.HashType.SHA256) + .setVariant(EciesParameters.Variant.TINK) + .setDemParameters(DEM_PARAMETERS) + .setSalt(SALT) + .build(); + EciesPublicKey publicKey = + EciesPublicKey.createForCurveX25519(parameters, Bytes.copyFrom(publicKeyBytes), 101); + EciesPrivateKey privateKey = + EciesPrivateKey.createForCurveX25519( + publicKey, SecretBytes.copyFrom(privateKeyBytes, InsecureSecretKeyAccess.get())); + + // Proto object + EciesAeadHkdfPublicKey protoPublicKey = + EciesAeadHkdfPublicKey.newBuilder() + .setVersion(0) + .setParams(validParamsForCurve(EllipticCurveType.CURVE25519)) + .setX(ByteString.copyFrom(publicKeyBytes)) + .build(); + EciesAeadHkdfPrivateKey protoPrivateKey = + EciesAeadHkdfPrivateKey.newBuilder() + .setVersion(0) + .setPublicKey(protoPublicKey) + .setKeyValue(ByteString.copyFrom(privateKeyBytes)) + .build(); + ProtoKeySerialization serialization = + ProtoKeySerialization.create( + "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey", + protoPrivateKey.toByteString(), + KeyMaterialType.ASYMMETRIC_PRIVATE, + OutputPrefixType.TINK, + /* idRequirement= */ 101); + + // Comparison + Key parsed = registry.parseKey(serialization, InsecureSecretKeyAccess.get()); + assertThat(parsed.equalsKey(privateKey)).isTrue(); + + ProtoKeySerialization serialized = + registry.serializeKey( + privateKey, ProtoKeySerialization.class, InsecureSecretKeyAccess.get()); + + assertEqualWhenValueParsed(EciesAeadHkdfPublicKey.parser(), serialized, serialization); + } + + @Test + public void testParsePrivateKey_noAccess_throws() throws Exception { + String hexX = "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6"; + String hexY = "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299"; + String hexPrivateValue = "C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721"; + + // Proto object + EciesAeadHkdfPublicKey protoPublicKey = + EciesAeadHkdfPublicKey.newBuilder() + .setVersion(0) + .setParams( + validParamsForCurve(com.google.crypto.tink.proto.EllipticCurveType.NIST_P256)) + .setX(ByteString.copyFrom(Hex.decode("00" + hexX))) + .setY(ByteString.copyFrom(Hex.decode("00" + hexY))) + .build(); + EciesAeadHkdfPrivateKey protoPrivateKey = + EciesAeadHkdfPrivateKey.newBuilder() + .setVersion(0) + .setPublicKey(protoPublicKey) + // privateValue is currently serialized with an extra zero at the beginning. + .setKeyValue(ByteString.copyFrom(Hex.decode("00" + hexPrivateValue))) + .build(); + ProtoKeySerialization serialization = + ProtoKeySerialization.create( + "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey", + protoPrivateKey.toByteString(), + KeyMaterialType.ASYMMETRIC_PRIVATE, + OutputPrefixType.TINK, + /* idRequirement= */ 101); + assertThrows( + GeneralSecurityException.class, () -> registry.parseKey(serialization, /* access= */ null)); + } + + @Test + public void testSerializeKeys_noAccess_throws() throws Exception { + String hexX = "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6"; + String hexY = "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299"; + String hexPrivateValue = "C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721"; + + EciesParameters parameters = + EciesParameters.builder() + .setCurveType(EciesParameters.CurveType.NIST_P256) + .setHashType(EciesParameters.HashType.SHA256) + .setNistCurvePointFormat(EciesParameters.PointFormat.COMPRESSED) + .setVariant(EciesParameters.Variant.TINK) + .setDemParameters(DEM_PARAMETERS) + .setSalt(SALT) + .build(); + EciesPublicKey publicKey = + EciesPublicKey.createForNistCurve( + parameters, new ECPoint(new BigInteger(hexX, 16), new BigInteger(hexY, 16)), 101); + EciesPrivateKey privateKey = + EciesPrivateKey.createForNistCurve( + publicKey, + SecretBigInteger.fromBigInteger( + new BigInteger(hexPrivateValue, 16), InsecureSecretKeyAccess.get())); + + assertThrows( + GeneralSecurityException.class, + () -> registry.serializeKey(privateKey, ProtoKeySerialization.class, /* access= */ null)); + } + + private static ProtoKeySerialization[] createInvalidPrivateKeySerializations() { + try { + String hexX = "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6"; + String hexY = "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299"; + String hexPrivateValue = "C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721"; + + EciesAeadHkdfPublicKey validProtoPublicKey = + EciesAeadHkdfPublicKey.newBuilder() + .setVersion(0) + .setParams(validParamsForCurve(EllipticCurveType.NIST_P256)) + .setX(ByteString.copyFrom(Hex.decode("00" + hexX))) + .setY(ByteString.copyFrom(Hex.decode("00" + hexY))) + .build(); + + return new ProtoKeySerialization[] { + // Bad private key value + ProtoKeySerialization.create( + "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey", + EciesAeadHkdfPrivateKey.newBuilder() + .setVersion(0) + .setPublicKey(validProtoPublicKey) + .setKeyValue( + ByteString.copyFrom( + Hex.decode( + // modified hexPrivateValue + "C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6720"))) + .build() + .toByteString(), + KeyMaterialType.ASYMMETRIC_PRIVATE, + OutputPrefixType.TINK, + /* idRequirement= */ 101), + // Bad version + ProtoKeySerialization.create( + "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey", + EciesAeadHkdfPrivateKey.newBuilder() + .setVersion(1) + .setPublicKey(validProtoPublicKey) + .setKeyValue(ByteString.copyFrom(Hex.decode(hexPrivateValue))) + .build() + .toByteString(), + KeyMaterialType.ASYMMETRIC_PRIVATE, + OutputPrefixType.TINK, + /* idRequirement= */ 101), + // Unknown prefix + ProtoKeySerialization.create( + "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey", + EciesAeadHkdfPrivateKey.newBuilder() + .setVersion(0) + .setPublicKey(validProtoPublicKey) + .setKeyValue(ByteString.copyFrom(Hex.decode(hexPrivateValue))) + .build() + .toByteString(), + KeyMaterialType.ASYMMETRIC_PRIVATE, + OutputPrefixType.UNKNOWN_PREFIX, + /* idRequirement= */ 101), + // Bad Public Key (X25519 Curve with EC Point Format uncompressed) + ProtoKeySerialization.create( + "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey", + EciesAeadHkdfPrivateKey.newBuilder() + .setVersion(0) + .setPublicKey( + EciesAeadHkdfPublicKey.newBuilder() + .setVersion(0) + .setParams( + validParamsForCurve(EllipticCurveType.CURVE25519).toBuilder() + .setEcPointFormat(EcPointFormat.UNCOMPRESSED) + .build()) + .setX(ByteString.copyFrom(Random.randBytes(32))) + .build()) + .setKeyValue(ByteString.copyFrom(Random.randBytes(32))) + .build() + .toByteString(), + KeyMaterialType.ASYMMETRIC_PUBLIC, + OutputPrefixType.TINK, + /* idRequirement= */ 101), + }; + + } catch (GeneralSecurityException e) { + throw new RuntimeException(e); + } + } + + @DataPoints("invalidPrivateKeySerializations") + public static final ProtoKeySerialization[] INVALID_PRIVATE_KEY_SERIALIZATIONS = + createInvalidPrivateKeySerializations(); + + @Theory + public void testParseInvalidPrivateKeys_throws( + @FromDataPoints("invalidPublicKeySerializations") ProtoKeySerialization serialization) + throws Exception { + assertThrows( + GeneralSecurityException.class, + () -> registry.parseKey(serialization, InsecureSecretKeyAccess.get())); + } } |