Skip to content

Commit

Permalink
[main] Update 2024-07-11.10 (#195)
Browse files Browse the repository at this point in the history
Reference commit: 1e93cf33d2

Co-authored-by: Canton <canton@digitalasset.com>
  • Loading branch information
canton-machine and Canton authored Jul 11, 2024
1 parent f0ddd4b commit 06451f6
Show file tree
Hide file tree
Showing 141 changed files with 2,630 additions and 1,008 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ object VaultAdminCommands {

}

final case class GenerateEncryptionKey(name: String, scheme: Option[EncryptionKeyScheme])
final case class GenerateEncryptionKey(name: String, keySpec: Option[EncryptionKeySpec])
extends BaseVaultAdminCommand[
v30.GenerateEncryptionKeyRequest,
v30.GenerateEncryptionKeyResponse,
Expand All @@ -176,8 +176,8 @@ object VaultAdminCommands {
Right(
v30.GenerateEncryptionKeyRequest(
name = name,
keyScheme = scheme.fold[cryptoproto.EncryptionKeyScheme](
cryptoproto.EncryptionKeyScheme.ENCRYPTION_KEY_SCHEME_UNSPECIFIED
keySpec = keySpec.fold[cryptoproto.EncryptionKeySpec](
cryptoproto.EncryptionKeySpec.ENCRYPTION_KEY_SPEC_UNSPECIFIED
)(_.toProtoEnum),
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package com.digitalasset.canton.admin.api.client.data

import cats.syntax.either.*
import com.daml.nonempty.{NonEmpty, NonEmptyUtil}
import com.digitalasset.canton.ProtoDeserializationError.FieldNotSet
import com.digitalasset.canton.config.RequireTypes.NonNegativeInt
import com.digitalasset.canton.config.{
CommunityCryptoConfig,
Expand All @@ -14,8 +15,10 @@ import com.digitalasset.canton.config.{
}
import com.digitalasset.canton.crypto.{
CryptoKeyFormat,
EncryptionKeyScheme,
EncryptionAlgorithmSpec,
EncryptionKeySpec,
HashAlgorithm,
RequiredEncryptionSpecs,
SigningKeyScheme,
SymmetricKeyScheme,
}
Expand Down Expand Up @@ -46,7 +49,7 @@ import scala.Ordering.Implicits.*

final case class StaticDomainParameters(
requiredSigningKeySchemes: Set[SigningKeyScheme],
requiredEncryptionKeySchemes: Set[EncryptionKeyScheme],
requiredEncryptionSpecs: RequiredEncryptionSpecs,
requiredSymmetricKeySchemes: Set[SymmetricKeyScheme],
requiredHashAlgorithms: Set[HashAlgorithm],
requiredCryptoKeyFormats: Set[CryptoKeyFormat],
Expand All @@ -60,9 +63,7 @@ final case class StaticDomainParameters(
requiredSigningKeySchemes = NonEmptyUtil.fromUnsafe(
requiredSigningKeySchemes.map(_.transformInto[DomainCrypto.SigningKeyScheme])
),
requiredEncryptionKeySchemes = NonEmptyUtil.fromUnsafe(
requiredEncryptionKeySchemes.map(_.transformInto[DomainCrypto.EncryptionKeyScheme])
),
requiredEncryptionSpecs = requiredEncryptionSpecs,
requiredSymmetricKeySchemes = NonEmptyUtil.fromUnsafe(
requiredSymmetricKeySchemes.map(_.transformInto[DomainCrypto.SymmetricKeyScheme])
),
Expand Down Expand Up @@ -116,8 +117,7 @@ object StaticDomainParameters {
StaticDomainParameters(
requiredSigningKeySchemes =
domain.requiredSigningKeySchemes.forgetNE.map(_.transformInto[SigningKeyScheme]),
requiredEncryptionKeySchemes =
domain.requiredEncryptionKeySchemes.forgetNE.map(_.transformInto[EncryptionKeyScheme]),
requiredEncryptionSpecs = domain.requiredEncryptionSpecs,
requiredSymmetricKeySchemes =
domain.requiredSymmetricKeySchemes.forgetNE.map(_.transformInto[SymmetricKeyScheme]),
requiredHashAlgorithms =
Expand Down Expand Up @@ -151,7 +151,7 @@ object StaticDomainParameters {
): ParsingResult[StaticDomainParameters] = {
val v30.StaticDomainParameters(
requiredSigningKeySchemesP,
requiredEncryptionKeySchemesP,
requiredEncryptionSpecsP,
requiredSymmetricKeySchemesP,
requiredHashAlgorithmsP,
requiredCryptoKeyFormatsP,
Expand All @@ -164,10 +164,18 @@ object StaticDomainParameters {
requiredSigningKeySchemesP,
SigningKeyScheme.fromProtoEnum,
)
requiredEncryptionKeySchemes <- requiredKeySchemes(
"requiredEncryptionKeySchemes",
requiredEncryptionKeySchemesP,
EncryptionKeyScheme.fromProtoEnum,
requiredEncryptionSpecsP <- requiredEncryptionSpecsP.toRight(
FieldNotSet("requiredEncryptionSpecs")
)
requiredEncryptionAlgorithmSpecs <- requiredKeySchemes(
"requiredEncryptionAlgorithmSpecs",
requiredEncryptionSpecsP.algorithms,
EncryptionAlgorithmSpec.fromProtoEnum,
)
requiredEncryptionKeySpecs <- requiredKeySchemes(
"requiredEncryptionKeySpecs",
requiredEncryptionSpecsP.keys,
EncryptionKeySpec.fromProtoEnum,
)
requiredSymmetricKeySchemes <- requiredKeySchemes(
"requiredSymmetricKeySchemes",
Expand All @@ -188,7 +196,7 @@ object StaticDomainParameters {
protocolVersion <- ProtocolVersion.fromProtoPrimitive(protocolVersionP, allowDeleted = true)
} yield StaticDomainParameters(
requiredSigningKeySchemes,
requiredEncryptionKeySchemes,
RequiredEncryptionSpecs(requiredEncryptionAlgorithmSpecs, requiredEncryptionKeySpecs),
requiredSymmetricKeySchemes,
requiredHashAlgorithms,
requiredCryptoKeyFormats,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -706,10 +706,12 @@ object CantonConfig {
deriveReader[GrpcHealthServerConfig]
lazy implicit val communityCryptoProviderReader: ConfigReader[CommunityCryptoProvider] =
deriveEnumerationReader[CommunityCryptoProvider]
lazy implicit val encryptionKeySpecReader: ConfigReader[EncryptionKeySpec] =
deriveEnumerationReader[EncryptionKeySpec]
lazy implicit val cryptoSigningKeySchemeReader: ConfigReader[SigningKeyScheme] =
deriveEnumerationReader[SigningKeyScheme]
lazy implicit val cryptoEncryptionKeySchemeReader: ConfigReader[EncryptionKeyScheme] =
deriveEnumerationReader[EncryptionKeyScheme]
lazy implicit val cryptoEncryptionAlgorithmSpecReader: ConfigReader[EncryptionAlgorithmSpec] =
deriveEnumerationReader[EncryptionAlgorithmSpec]
lazy implicit val cryptoSymmetricKeySchemeReader: ConfigReader[SymmetricKeyScheme] =
deriveEnumerationReader[SymmetricKeyScheme]
lazy implicit val cryptoHashAlgorithmReader: ConfigReader[HashAlgorithm] =
Expand Down Expand Up @@ -1123,10 +1125,12 @@ object CantonConfig {
InitConfigBase.writerForSubtype(deriveWriter[ParticipantInitConfig])
lazy implicit val communityCryptoProviderWriter: ConfigWriter[CommunityCryptoProvider] =
deriveEnumerationWriter[CommunityCryptoProvider]
lazy implicit val encryptionKeySpecWriter: ConfigWriter[EncryptionKeySpec] =
deriveEnumerationWriter[EncryptionKeySpec]
lazy implicit val cryptoSigningKeySchemeWriter: ConfigWriter[SigningKeyScheme] =
deriveEnumerationWriter[SigningKeyScheme]
lazy implicit val cryptoEncryptionKeySchemeWriter: ConfigWriter[EncryptionKeyScheme] =
deriveEnumerationWriter[EncryptionKeyScheme]
lazy implicit val cryptoEncryptionAlgorithmSpecWriter: ConfigWriter[EncryptionAlgorithmSpec] =
deriveEnumerationWriter[EncryptionAlgorithmSpec]
lazy implicit val cryptoSymmetricKeySchemeWriter: ConfigWriter[SymmetricKeyScheme] =
deriveEnumerationWriter[SymmetricKeyScheme]
lazy implicit val cryptoHashAlgorithmWriter: ConfigWriter[HashAlgorithm] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class SecretKeyAdministration(
currentKey match {
case encKey: EncryptionPublicKey =>
instance.keys.secret.generate_encryption_key(
scheme = Some(encKey.scheme),
keySpec = Some(encKey.keySpec),
name = OptionUtil.noneAsEmptyString(name),
)
case signKey: SigningPublicKey =>
Expand Down Expand Up @@ -93,10 +93,10 @@ class SecretKeyAdministration(
)
def generate_encryption_key(
name: String = "",
scheme: Option[EncryptionKeyScheme] = None,
keySpec: Option[EncryptionKeySpec] = None,
): EncryptionPublicKey = {
consoleEnvironment.run {
adminCommand(VaultAdminCommands.GenerateEncryptionKey(name, scheme))
adminCommand(VaultAdminCommands.GenerateEncryptionKey(name, keySpec))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ message GenerateSigningKeyResponse {
}

message GenerateEncryptionKeyRequest {
com.digitalasset.canton.crypto.v30.EncryptionKeyScheme key_scheme = 1;
com.digitalasset.canton.crypto.v30.EncryptionKeySpec key_spec = 1;

// optional descriptive name for the key
string name = 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ enum SignatureFormat {
SIGNATURE_FORMAT_RAW = 1;
}

enum EncryptionKeySpec {
ENCRYPTION_KEY_SPEC_UNSPECIFIED = 0;

// Elliptic Curve Key based on NIST P-256 (aka Secp256r1)
// as defined in https://doi.org/10.6028/NIST.FIPS.186-4
ENCRYPTION_KEY_SPEC_EC_P256 = 1;

// RSA with 2048 bits
ENCRYPTION_KEY_SPEC_RSA_2048 = 3;
}

message PublicKey {
oneof key {
SigningPublicKey signing_public_key = 1;
Expand Down Expand Up @@ -122,8 +133,11 @@ message EncryptionPublicKey {
// Serialized public key in the format specified above
bytes public_key = 3;

// Explicit state the key scheme of the serialized public key
EncryptionKeyScheme scheme = 4;
// No longer used (only kept for backwards compatibility) stores both the crypto key scheme and algorithm.
EncryptionKeyScheme scheme = 4 [deprecated = true];

// The key specification that was used to generate the key pair
EncryptionKeySpec key_spec = 5;
}

message EncryptionPrivateKey {
Expand All @@ -134,15 +148,34 @@ message EncryptionPrivateKey {
// Serialized private key in the format specified above
bytes private_key = 3;

// Explicit state the key scheme of the serialized private key
EncryptionKeyScheme scheme = 4;
// No longer used (only kept for backwards compatibility) stores both the crypto key scheme and algorithm.
EncryptionKeyScheme scheme = 4 [deprecated = true];

// The key specification that was used to generate the key pair
EncryptionKeySpec key_spec = 5;
}

message EncryptionKeyPair {
EncryptionPublicKey public_key = 1;
EncryptionPrivateKey private_key = 2;
}

enum EncryptionAlgorithmSpec {
ENCRYPTION_ALGORITHM_SPEC_UNSPECIFIED = 0;

/* ECIES with ECDH, AES128 GCM, and HKDF and authentication (MAC) with HMAC-SHA256. This requires a P-256 key
because we use SHA256 and we need to align the lengths of the curve and the hash function. */
ENCRYPTION_ALGORITHM_SPEC_ECIES_HKDF_HMAC_SHA256_AES128GCM = 1;

/* ECIES with ECDH, AES128 CBC, and HKDF and authentication (MAC) with HMAC-SHA256. This requires a P-256 key
because we use SHA256 and we need to align the lengths of the curve the and hash function. */
ENCRYPTION_ALGORITHM_SPEC_ECIES_HKDF_HMAC_SHA256_AES128CBC = 2;

/* RSA with OAEP Padding,
using SHA-256 for both the hash and in the MGF1 mask generation function along with an empty label. */
ENCRYPTION_ALGORITHM_SPEC_RSA_OAEP_SHA256 = 3;
}

enum EncryptionKeyScheme {
ENCRYPTION_KEY_SCHEME_UNSPECIFIED = 0;

Expand All @@ -157,6 +190,11 @@ enum EncryptionKeyScheme {
ENCRYPTION_KEY_SCHEME_RSA2048_OAEP_SHA256 = 3;
}

message RequiredEncryptionSpecs {
repeated EncryptionAlgorithmSpec algorithms = 1;
repeated EncryptionKeySpec keys = 2;
}

message CryptoKeyPair {
oneof pair {
SigningKeyPair signing_key_pair = 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,11 @@ message SessionKeyLookup {
// randomness field in `EncryptedViewMessage`
bytes session_key_randomness = 1;

// The asymmetric encryption specification used to encrypt the session key randomness
com.digitalasset.canton.crypto.v30.EncryptionAlgorithmSpec encryption_algorithm_spec = 2;

// The fingerprint of the public key that was used to encrypt the session key randomness
string fingerprint = 2;
string fingerprint = 3;
}

message EncryptedViewMessage {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ message StaticDomainParameters {
option (scalapb.message).companion_extends = "com.digitalasset.canton.version.StableProtoVersion";

repeated com.digitalasset.canton.crypto.v30.SigningKeyScheme required_signing_key_schemes = 1;
repeated com.digitalasset.canton.crypto.v30.EncryptionKeyScheme required_encryption_key_schemes = 2;
com.digitalasset.canton.crypto.v30.RequiredEncryptionSpecs required_encryption_specs = 2;
repeated com.digitalasset.canton.crypto.v30.SymmetricKeyScheme required_symmetric_key_schemes = 3;
repeated com.digitalasset.canton.crypto.v30.HashAlgorithm required_hash_algorithms = 4;
repeated com.digitalasset.canton.crypto.v30.CryptoKeyFormat required_crypto_key_formats = 5;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ class Crypto(

/** Helper method to generate a new encryption key pair and store the public key in the public store as well. */
def generateEncryptionKey(
scheme: EncryptionKeyScheme = privateCrypto.defaultEncryptionKeyScheme,
keySpec: EncryptionKeySpec = privateCrypto.defaultEncryptionKeySpec,
name: Option[KeyName] = None,
)(implicit
traceContext: TraceContext
): EitherT[FutureUnlessShutdown, EncryptionKeyGenerationError, EncryptionPublicKey] =
for {
publicKey <- privateCrypto.generateEncryptionKey(scheme, name)
publicKey <- privateCrypto.generateEncryptionKey(keySpec, name)
_ <- EitherT.right(cryptoPublicStore.storeEncryptionKey(publicKey, name))
} yield publicKey

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,43 @@ object CryptoKeyValidation {
.leftMap(err => errFn(s"Failed to deserialize ${publicKey.format} public key: $err"))
}

private[crypto] def selectEncryptionAlgorithmSpec[E](
keySpec: EncryptionKeySpec,
defaultAlgorithmSpec: EncryptionAlgorithmSpec,
supportedAlgorithmSpecs: Set[EncryptionAlgorithmSpec],
errFn: EncryptionAlgorithmSpec => E,
): Either[E, EncryptionAlgorithmSpec] = {
if (defaultAlgorithmSpec.supportedEncryptionKeySpecs.contains(keySpec))
Right(defaultAlgorithmSpec)
else
supportedAlgorithmSpecs
.find(_.supportedEncryptionKeySpecs.contains(keySpec))
.toRight(errFn(defaultAlgorithmSpec))
}

/** Ensures that a given key specification is supported by the selected crypto algorithm. It
* also checks if this crypto algorithm is part of the set of supported algorithms.
*/
private[crypto] def ensureEncryptionSpec[E](
keySpec: EncryptionKeySpec,
defaultAlgorithmSpec: EncryptionAlgorithmSpec,
supportedAlgorithmSpecs: Set[EncryptionAlgorithmSpec],
errFnAlgorithm: EncryptionAlgorithmSpec => E,
errFnKey: EncryptionKeySpec => E,
): Either[E, Unit] =
for {
_ <- Either.cond(
supportedAlgorithmSpecs.contains(defaultAlgorithmSpec),
(),
errFnAlgorithm(defaultAlgorithmSpec),
)
_ <- Either.cond(
defaultAlgorithmSpec.supportedEncryptionKeySpecs.contains(keySpec),
(),
errFnKey(keySpec),
)
} yield ()

private[crypto] def ensureFormat[E](
actual: CryptoKeyFormat,
acceptedFormats: Set[CryptoKeyFormat],
Expand Down
Loading

0 comments on commit 06451f6

Please sign in to comment.