diff --git a/docs/grpc/index.html b/docs/grpc/index.html
index c598fdd7a2..7c9c3285ba 100644
--- a/docs/grpc/index.html
+++ b/docs/grpc/index.html
@@ -4043,6 +4043,24 @@
Algorithm
|
+
+ | ALGORITHM_MLKEM_768 |
+ 20 |
+ |
+
+
+
+ | ALGORITHM_MLKEM_1024 |
+ 21 |
+ |
+
+
+
+ | ALGORITHM_HYBRID_XWING |
+ 30 |
+ |
+
+
@@ -4154,6 +4172,24 @@ KasPublicKeyAlgEnum
|
+
+ | KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768 |
+ 20 |
+ |
+
+
+
+ | KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024 |
+ 21 |
+ |
+
+
+
+ | KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING |
+ 30 |
+ |
+
+
@@ -6292,7 +6328,7 @@ KeyAccess
|
Type of key wrapping used for the data encryption key
Required: Always
-Values: 'wrapped' (RSA-wrapped for ZTDF), 'ec-wrapped' (experimental ECDH-wrapped) |
+Values: 'wrapped' (RSA-wrapped for ZTDF), 'ec-wrapped' (experimental ECDH-wrapped), 'mlkem-wrapped' (ML-KEM-wrapped), 'hybrid' (Hybrid X-Wing-wrapped)
@@ -6347,10 +6383,10 @@ KeyAccess
ephemeral_public_key |
string |
|
- Ephemeral public key for ECDH key derivation (ec-wrapped type only)
-Required: When key_type="ec-wrapped" (experimental ECDH-based ZTDF)
+ | Ephemeral public key for ECDH/ML-KEM/Hybrid key derivation
+Required: When key_type="ec-wrapped", "mlkem-wrapped", or "hybrid"
Omitted: When key_type="wrapped" (RSA-based ZTDF)
-Should be a PEM-encoded PKCS#8 (ASN.1) formatted public key
+Should be a PEM-encoded or Base64-encoded (for ML-KEM/Hybrid) public key material
Used to derive the symmetric key for unwrapping the DEK |
@@ -6676,8 +6712,8 @@ RewrapResponse
string |
|
KAS's ephemeral session public key in PEM format
-Required: For EC-based operations (key_type="ec-wrapped")
-Optional: Empty for RSA-based ZTDF (key_type="wrapped")
+Required: For EC-based operations (key_type="ec-wrapped") or Hybrid
+Optional: Empty for RSA-based ZTDF (key_type="wrapped") or ML-KEM
Used by client to perform ECDH key agreement and decrypt the kas_wrapped_key values |
diff --git a/docs/openapi/authorization/authorization.openapi.yaml b/docs/openapi/authorization/authorization.openapi.yaml
index b17083ebd1..414620572e 100644
--- a/docs/openapi/authorization/authorization.openapi.yaml
+++ b/docs/openapi/authorization/authorization.openapi.yaml
@@ -343,6 +343,9 @@ components:
- ALGORITHM_EC_P256
- ALGORITHM_EC_P384
- ALGORITHM_EC_P521
+ - ALGORITHM_MLKEM_768
+ - ALGORITHM_MLKEM_1024
+ - ALGORITHM_HYBRID_XWING
description: Supported key algorithms.
policy.KasPublicKeyAlgEnum:
type: string
@@ -354,6 +357,9 @@ components:
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024
+ - KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING
policy.SourceType:
type: string
title: SourceType
diff --git a/docs/openapi/authorization/v2/authorization.openapi.yaml b/docs/openapi/authorization/v2/authorization.openapi.yaml
index 0f4f92d55f..dfc69dbf78 100644
--- a/docs/openapi/authorization/v2/authorization.openapi.yaml
+++ b/docs/openapi/authorization/v2/authorization.openapi.yaml
@@ -175,6 +175,9 @@ components:
- ALGORITHM_EC_P256
- ALGORITHM_EC_P384
- ALGORITHM_EC_P521
+ - ALGORITHM_MLKEM_768
+ - ALGORITHM_MLKEM_1024
+ - ALGORITHM_HYBRID_XWING
description: Supported key algorithms.
policy.KasPublicKeyAlgEnum:
type: string
@@ -186,6 +189,9 @@ components:
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024
+ - KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING
policy.SourceType:
type: string
title: SourceType
diff --git a/docs/openapi/kas/kas.openapi.yaml b/docs/openapi/kas/kas.openapi.yaml
index b9e18aa899..cbb7de1b3b 100644
--- a/docs/openapi/kas/kas.openapi.yaml
+++ b/docs/openapi/kas/kas.openapi.yaml
@@ -214,7 +214,7 @@ components:
description: |-
Type of key wrapping used for the data encryption key
Required: Always
- Values: 'wrapped' (RSA-wrapped for ZTDF), 'ec-wrapped' (experimental ECDH-wrapped)
+ Values: 'wrapped' (RSA-wrapped for ZTDF), 'ec-wrapped' (experimental ECDH-wrapped), 'mlkem-wrapped' (ML-KEM-wrapped), 'hybrid' (Hybrid X-Wing-wrapped)
url:
type: string
title: kas_url
@@ -259,10 +259,10 @@ components:
type: string
title: ephemeral_public_key
description: |-
- Ephemeral public key for ECDH key derivation (ec-wrapped type only)
- Required: When key_type="ec-wrapped" (experimental ECDH-based ZTDF)
+ Ephemeral public key for ECDH/ML-KEM/Hybrid key derivation
+ Required: When key_type="ec-wrapped", "mlkem-wrapped", or "hybrid"
Omitted: When key_type="wrapped" (RSA-based ZTDF)
- Should be a PEM-encoded PKCS#8 (ASN.1) formatted public key
+ Should be a PEM-encoded or Base64-encoded (for ML-KEM/Hybrid) public key material
Used to derive the symmetric key for unwrapping the DEK
title: KeyAccess
additionalProperties: false
@@ -450,8 +450,8 @@ components:
title: session_public_key
description: |-
KAS's ephemeral session public key in PEM format
- Required: For EC-based operations (key_type="ec-wrapped")
- Optional: Empty for RSA-based ZTDF (key_type="wrapped")
+ Required: For EC-based operations (key_type="ec-wrapped") or Hybrid
+ Optional: Empty for RSA-based ZTDF (key_type="wrapped") or ML-KEM
Used by client to perform ECDH key agreement and decrypt the kas_wrapped_key values
schemaVersion:
type: string
diff --git a/docs/openapi/policy/actions/actions.openapi.yaml b/docs/openapi/policy/actions/actions.openapi.yaml
index ec633192ae..770efbd744 100644
--- a/docs/openapi/policy/actions/actions.openapi.yaml
+++ b/docs/openapi/policy/actions/actions.openapi.yaml
@@ -203,6 +203,9 @@ components:
- ALGORITHM_EC_P256
- ALGORITHM_EC_P384
- ALGORITHM_EC_P521
+ - ALGORITHM_MLKEM_768
+ - ALGORITHM_MLKEM_1024
+ - ALGORITHM_HYBRID_XWING
description: Supported key algorithms.
policy.AttributeRuleTypeEnum:
type: string
@@ -229,6 +232,9 @@ components:
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024
+ - KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING
policy.SourceType:
type: string
title: SourceType
diff --git a/docs/openapi/policy/attributes/attributes.openapi.yaml b/docs/openapi/policy/attributes/attributes.openapi.yaml
index 0fcb66f710..67052c49bf 100644
--- a/docs/openapi/policy/attributes/attributes.openapi.yaml
+++ b/docs/openapi/policy/attributes/attributes.openapi.yaml
@@ -724,6 +724,9 @@ components:
- ALGORITHM_EC_P256
- ALGORITHM_EC_P384
- ALGORITHM_EC_P521
+ - ALGORITHM_MLKEM_768
+ - ALGORITHM_MLKEM_1024
+ - ALGORITHM_HYBRID_XWING
description: Supported key algorithms.
policy.AttributeRuleTypeEnum:
type: string
@@ -750,6 +753,9 @@ components:
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024
+ - KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING
policy.SortDirection:
type: string
title: SortDirection
diff --git a/docs/openapi/policy/kasregistry/key_access_server_registry.openapi.yaml b/docs/openapi/policy/kasregistry/key_access_server_registry.openapi.yaml
index 9cdc346918..12ce447a18 100644
--- a/docs/openapi/policy/kasregistry/key_access_server_registry.openapi.yaml
+++ b/docs/openapi/policy/kasregistry/key_access_server_registry.openapi.yaml
@@ -534,6 +534,9 @@ components:
- ALGORITHM_EC_P256
- ALGORITHM_EC_P384
- ALGORITHM_EC_P521
+ - ALGORITHM_MLKEM_768
+ - ALGORITHM_MLKEM_1024
+ - ALGORITHM_HYBRID_XWING
description: Supported key algorithms.
policy.KasPublicKeyAlgEnum:
type: string
@@ -545,6 +548,9 @@ components:
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024
+ - KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING
policy.KeyMode:
type: string
title: KeyMode
@@ -1147,7 +1153,7 @@ components:
Required The algorithm to be used for the key
The key_algorithm must be one of the defined values.:
```
- this in [1, 2, 3, 4, 5]
+ this in [1, 2, 3, 4, 5, 20, 21]
```
$ref: '#/components/schemas/policy.Algorithm'
@@ -1932,7 +1938,7 @@ components:
Required
The key_algorithm must be one of the defined values.:
```
- this in [1, 2, 3, 4, 5]
+ this in [1, 2, 3, 4, 5, 20, 21]
```
$ref: '#/components/schemas/policy.Algorithm'
diff --git a/docs/openapi/policy/namespaces/namespaces.openapi.yaml b/docs/openapi/policy/namespaces/namespaces.openapi.yaml
index 4a5b7e35cb..071817abae 100644
--- a/docs/openapi/policy/namespaces/namespaces.openapi.yaml
+++ b/docs/openapi/policy/namespaces/namespaces.openapi.yaml
@@ -353,6 +353,9 @@ components:
- ALGORITHM_EC_P256
- ALGORITHM_EC_P384
- ALGORITHM_EC_P521
+ - ALGORITHM_MLKEM_768
+ - ALGORITHM_MLKEM_1024
+ - ALGORITHM_HYBRID_XWING
description: Supported key algorithms.
policy.KasPublicKeyAlgEnum:
type: string
@@ -364,6 +367,9 @@ components:
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024
+ - KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING
policy.SortDirection:
type: string
title: SortDirection
diff --git a/docs/openapi/policy/objects.openapi.yaml b/docs/openapi/policy/objects.openapi.yaml
index 917017b1a0..a48bfafd1d 100644
--- a/docs/openapi/policy/objects.openapi.yaml
+++ b/docs/openapi/policy/objects.openapi.yaml
@@ -21,6 +21,9 @@ components:
- ALGORITHM_EC_P256
- ALGORITHM_EC_P384
- ALGORITHM_EC_P521
+ - ALGORITHM_MLKEM_768
+ - ALGORITHM_MLKEM_1024
+ - ALGORITHM_HYBRID_XWING
description: Supported key algorithms.
policy.AttributeRuleTypeEnum:
type: string
@@ -47,6 +50,9 @@ components:
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024
+ - KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING
policy.KeyMode:
type: string
title: KeyMode
diff --git a/docs/openapi/policy/obligations/obligations.openapi.yaml b/docs/openapi/policy/obligations/obligations.openapi.yaml
index dbe62f43ca..4cff7da1ff 100644
--- a/docs/openapi/policy/obligations/obligations.openapi.yaml
+++ b/docs/openapi/policy/obligations/obligations.openapi.yaml
@@ -518,6 +518,9 @@ components:
- ALGORITHM_EC_P256
- ALGORITHM_EC_P384
- ALGORITHM_EC_P521
+ - ALGORITHM_MLKEM_768
+ - ALGORITHM_MLKEM_1024
+ - ALGORITHM_HYBRID_XWING
description: Supported key algorithms.
policy.AttributeRuleTypeEnum:
type: string
@@ -544,6 +547,9 @@ components:
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024
+ - KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING
policy.SourceType:
type: string
title: SourceType
diff --git a/docs/openapi/policy/registeredresources/registered_resources.openapi.yaml b/docs/openapi/policy/registeredresources/registered_resources.openapi.yaml
index 97b2d07814..80b5691319 100644
--- a/docs/openapi/policy/registeredresources/registered_resources.openapi.yaml
+++ b/docs/openapi/policy/registeredresources/registered_resources.openapi.yaml
@@ -413,6 +413,9 @@ components:
- ALGORITHM_EC_P256
- ALGORITHM_EC_P384
- ALGORITHM_EC_P521
+ - ALGORITHM_MLKEM_768
+ - ALGORITHM_MLKEM_1024
+ - ALGORITHM_HYBRID_XWING
description: Supported key algorithms.
policy.AttributeRuleTypeEnum:
type: string
@@ -439,6 +442,9 @@ components:
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024
+ - KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING
policy.SourceType:
type: string
title: SourceType
diff --git a/docs/openapi/policy/resourcemapping/resource_mapping.openapi.yaml b/docs/openapi/policy/resourcemapping/resource_mapping.openapi.yaml
index c768b805c0..696ae62059 100644
--- a/docs/openapi/policy/resourcemapping/resource_mapping.openapi.yaml
+++ b/docs/openapi/policy/resourcemapping/resource_mapping.openapi.yaml
@@ -413,6 +413,9 @@ components:
- ALGORITHM_EC_P256
- ALGORITHM_EC_P384
- ALGORITHM_EC_P521
+ - ALGORITHM_MLKEM_768
+ - ALGORITHM_MLKEM_1024
+ - ALGORITHM_HYBRID_XWING
description: Supported key algorithms.
policy.AttributeRuleTypeEnum:
type: string
@@ -439,6 +442,9 @@ components:
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024
+ - KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING
policy.SourceType:
type: string
title: SourceType
diff --git a/docs/openapi/policy/subjectmapping/subject_mapping.openapi.yaml b/docs/openapi/policy/subjectmapping/subject_mapping.openapi.yaml
index ce818161fb..530dab4c0f 100644
--- a/docs/openapi/policy/subjectmapping/subject_mapping.openapi.yaml
+++ b/docs/openapi/policy/subjectmapping/subject_mapping.openapi.yaml
@@ -449,6 +449,9 @@ components:
- ALGORITHM_EC_P256
- ALGORITHM_EC_P384
- ALGORITHM_EC_P521
+ - ALGORITHM_MLKEM_768
+ - ALGORITHM_MLKEM_1024
+ - ALGORITHM_HYBRID_XWING
description: Supported key algorithms.
policy.AttributeRuleTypeEnum:
type: string
@@ -475,6 +478,9 @@ components:
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024
+ - KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING
policy.SortDirection:
type: string
title: SortDirection
diff --git a/docs/openapi/policy/unsafe/unsafe.openapi.yaml b/docs/openapi/policy/unsafe/unsafe.openapi.yaml
index f52e95b427..e400f9b9e1 100644
--- a/docs/openapi/policy/unsafe/unsafe.openapi.yaml
+++ b/docs/openapi/policy/unsafe/unsafe.openapi.yaml
@@ -387,6 +387,9 @@ components:
- ALGORITHM_EC_P256
- ALGORITHM_EC_P384
- ALGORITHM_EC_P521
+ - ALGORITHM_MLKEM_768
+ - ALGORITHM_MLKEM_1024
+ - ALGORITHM_HYBRID_XWING
description: Supported key algorithms.
policy.AttributeRuleTypeEnum:
type: string
@@ -413,6 +416,9 @@ components:
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1
- KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768
+ - KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024
+ - KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING
policy.KeyMode:
type: string
title: KeyMode
diff --git a/lib/ocrypto/asym_decryption.go b/lib/ocrypto/asym_decryption.go
index 426f859723..e917bea75c 100644
--- a/lib/ocrypto/asym_decryption.go
+++ b/lib/ocrypto/asym_decryption.go
@@ -7,6 +7,7 @@ import (
"crypto/ecdh"
"crypto/ecdsa"
"crypto/elliptic"
+ "crypto/mlkem"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
@@ -26,6 +27,21 @@ type AsymDecryption struct {
type PrivateKeyDecryptor interface {
// Decrypt decrypts ciphertext with private key.
Decrypt(data []byte) ([]byte, error)
+
+ // DecryptWithEphemeralKey decrypts ciphertext using additional sender material.
+ DecryptWithEphemeralKey(data, ephemeral []byte) ([]byte, error)
+}
+
+type MLKEMDecryptor768 struct {
+ decap *mlkem.DecapsulationKey768
+}
+
+type MLKEMDecryptor1024 struct {
+ decap *mlkem.DecapsulationKey1024
+}
+
+type HybridXWingDecryptorWrapper struct {
+ decap *HybridXWingDecryptor
}
// FromPrivatePEM creates and returns a new AsymDecryption.
@@ -44,6 +60,26 @@ func FromPrivatePEMWithSalt(privateKeyInPem string, salt, info []byte) (PrivateK
return AsymDecryption{}, errors.New("failed to parse PEM formatted private key")
}
+ if block.Type == "MLKEM DECAPSULATION KEY" {
+ decap768, err := mlkem.NewDecapsulationKey768(block.Bytes)
+ if err == nil {
+ return &MLKEMDecryptor768{decap: decap768}, nil
+ }
+ decap1024, err1024 := mlkem.NewDecapsulationKey1024(block.Bytes)
+ if err1024 != nil {
+ return nil, fmt.Errorf("mlkem.NewDecapsulationKey1024 failed after mlkem.NewDecapsulationKey768 failed: %w / %w", err, err1024)
+ }
+ return &MLKEMDecryptor1024{decap: decap1024}, nil
+ }
+
+ if block.Type == "HYBRID X-WING PRIVATE KEY" {
+ decap, err := NewHybridXWingDecryptor(block.Bytes)
+ if err != nil {
+ return nil, err
+ }
+ return &HybridXWingDecryptorWrapper{decap: decap}, nil
+ }
+
priv, err := x509.ParsePKCS8PrivateKey(block.Bytes)
switch {
case err == nil:
@@ -109,6 +145,13 @@ func (asymDecryption AsymDecryption) Decrypt(data []byte) ([]byte, error) {
return bytes, nil
}
+func (asymDecryption AsymDecryption) DecryptWithEphemeralKey(data, ephemeral []byte) ([]byte, error) {
+ if len(ephemeral) > 0 {
+ return nil, errors.New("ephemeral key is not supported for RSA decryption")
+ }
+ return asymDecryption.Decrypt(data)
+}
+
type ECDecryptor struct {
sk *ecdh.PrivateKey
salt []byte
@@ -196,6 +239,129 @@ func (e ECDecryptor) DecryptWithEphemeralKey(data, ephemeral []byte) ([]byte, er
return plaintext, nil
}
+func (d MLKEMDecryptor768) Decrypt(_ []byte) ([]byte, error) {
+ return nil, errors.New("ciphertext encapsulation is required for ML-KEM decryption")
+}
+
+func (d MLKEMDecryptor1024) Decrypt(_ []byte) ([]byte, error) {
+ return nil, errors.New("ciphertext encapsulation is required for ML-KEM decryption")
+}
+
+func (d MLKEMDecryptor768) DecryptWithEphemeralKey(data, ephemeral []byte) ([]byte, error) {
+ if d.decap == nil {
+ return nil, errors.New("mlkem decapsulation key is nil")
+ }
+ if len(ephemeral) == 0 {
+ return nil, errors.New("ciphertext encapsulation is required for ML-KEM decryption")
+ }
+
+ sharedSecret, err := d.decap.Decapsulate(ephemeral)
+ if err != nil {
+ return nil, fmt.Errorf("mlkem.Decapsulate failed: %w", err)
+ }
+
+ block, err := aes.NewCipher(sharedSecret)
+ if err != nil {
+ return nil, fmt.Errorf("aes.NewCipher failure: %w", err)
+ }
+
+ gcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return nil, fmt.Errorf("cipher.NewGCM failure: %w", err)
+ }
+
+ nonceSize := gcm.NonceSize()
+ if len(data) < nonceSize {
+ return nil, errors.New("ciphertext too short")
+ }
+
+ nonce, ciphertext := data[:nonceSize], data[nonceSize:]
+ plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
+ if err != nil {
+ return nil, fmt.Errorf("gcm.Open failure: %w", err)
+ }
+
+ return plaintext, nil
+}
+
+func (d MLKEMDecryptor1024) DecryptWithEphemeralKey(data, ephemeral []byte) ([]byte, error) {
+ if d.decap == nil {
+ return nil, errors.New("mlkem decapsulation key is nil")
+ }
+ if len(ephemeral) == 0 {
+ return nil, errors.New("ciphertext encapsulation is required for ML-KEM decryption")
+ }
+
+ sharedSecret, err := d.decap.Decapsulate(ephemeral)
+ if err != nil {
+ return nil, fmt.Errorf("mlkem.Decapsulate failed: %w", err)
+ }
+
+ block, err := aes.NewCipher(sharedSecret)
+ if err != nil {
+ return nil, fmt.Errorf("aes.NewCipher failure: %w", err)
+ }
+
+ gcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return nil, fmt.Errorf("cipher.NewGCM failure: %w", err)
+ }
+
+ nonceSize := gcm.NonceSize()
+ if len(data) < nonceSize {
+ return nil, errors.New("ciphertext too short")
+ }
+
+ nonce, ciphertext := data[:nonceSize], data[nonceSize:]
+ plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
+ if err != nil {
+ return nil, fmt.Errorf("gcm.Open failure: %w", err)
+ }
+
+ return plaintext, nil
+}
+
+func (d HybridXWingDecryptorWrapper) Decrypt(_ []byte) ([]byte, error) {
+ return nil, errors.New("ciphertext encapsulation is required for Hybrid X-Wing decryption")
+}
+
+func (d HybridXWingDecryptorWrapper) DecryptWithEphemeralKey(data, ephemeral []byte) ([]byte, error) {
+ if d.decap == nil {
+ return nil, errors.New("hybrid x-wing decapsulation key is nil")
+ }
+ if len(ephemeral) == 0 {
+ return nil, errors.New("ciphertext encapsulation is required for Hybrid X-Wing decryption")
+ }
+
+ sharedSecret, err := d.decap.Decapsulate(ephemeral)
+ if err != nil {
+ return nil, fmt.Errorf("hybrid x-wing Decapsulate failed: %w", err)
+ }
+
+ block, err := aes.NewCipher(sharedSecret)
+ if err != nil {
+ return nil, fmt.Errorf("aes.NewCipher failure: %w", err)
+ }
+
+ gcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return nil, fmt.Errorf("cipher.NewGCM failure: %w", err)
+ }
+
+ nonceSize := gcm.NonceSize()
+ if len(data) < nonceSize {
+ return nil, errors.New("ciphertext too short")
+ }
+
+ nonce, ciphertext := data[:nonceSize], data[nonceSize:]
+ plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
+ if err != nil {
+ return nil, fmt.Errorf("gcm.Open failure: %w", err)
+ }
+
+ return plaintext, nil
+}
+
func convCurve(c ecdh.Curve) elliptic.Curve {
switch c {
case ecdh.P256():
diff --git a/lib/ocrypto/asym_encryption.go b/lib/ocrypto/asym_encryption.go
index c44aa64cce..1b054ba5df 100644
--- a/lib/ocrypto/asym_encryption.go
+++ b/lib/ocrypto/asym_encryption.go
@@ -5,11 +5,13 @@ import (
"crypto/cipher"
"crypto/ecdh"
"crypto/ecdsa"
+ "crypto/mlkem"
"crypto/rand"
"crypto/rsa"
"crypto/sha1" //nolint:gosec // used for padding which is safe
"crypto/sha256"
"crypto/x509"
+ "encoding/asn1"
"encoding/pem"
"errors"
"fmt"
@@ -23,8 +25,10 @@ import (
type SchemeType string
const (
- RSA SchemeType = "wrapped"
- EC SchemeType = "ec-wrapped"
+ RSA SchemeType = "wrapped"
+ EC SchemeType = "ec-wrapped"
+ MLKEM SchemeType = "mlkem-wrapped"
+ Hybrid SchemeType = "hybrid"
)
type PublicKeyEncryptor interface {
@@ -40,7 +44,8 @@ type PublicKeyEncryptor interface {
// KeyType returns the key type, e.g. RSA or EC.
KeyType() KeyType
- // For EC schemes, this method returns the public part of the ephemeral key.
+ // For EC and ML-KEM schemes, this method returns the public part of the ephemeral key.
+ // For Hybrid scheme, it returns the ASN.1 marshaled ciphertext.
// Otherwise, it returns nil.
EphemeralKey() []byte
@@ -59,6 +64,24 @@ type ECEncryptor struct {
info []byte
}
+type MLKEMEncryptor768 struct {
+ pub *mlkem.EncapsulationKey768
+ cipherText []byte
+ sharedSecret []byte
+}
+
+type MLKEMEncryptor1024 struct {
+ pub *mlkem.EncapsulationKey1024
+ cipherText []byte
+ sharedSecret []byte
+}
+
+type HybridXWingEncryptorWrapper struct {
+ enc *HybridXWingEncryptor
+ sharedSecret []byte
+ ciphertext []byte
+}
+
func FromPublicPEM(publicKeyInPem string) (PublicKeyEncryptor, error) {
// TK Move salt and info out of library, into API option functions
digest := sha256.New()
@@ -85,6 +108,12 @@ func FromPublicPEMWithSalt(publicKeyInPem string, salt, info []byte) (PublicKeyE
return newECIES(e, salt, info)
case *ecdh.PublicKey:
return newECIES(pub, salt, info)
+ case *mlkem.EncapsulationKey768:
+ return newMLKEM768(pub), nil
+ case *mlkem.EncapsulationKey1024:
+ return newMLKEM1024(pub), nil
+ case *HybridXWingEncryptor:
+ return newHybridXWing(pub)
default:
break
}
@@ -97,6 +126,24 @@ func newECIES(pub *ecdh.PublicKey, salt, info []byte) (ECEncryptor, error) {
return ECEncryptor{pub, ek, salt, info}, err
}
+func newMLKEM768(pub *mlkem.EncapsulationKey768) *MLKEMEncryptor768 {
+ sharedSecret, cipherText := pub.Encapsulate()
+ return &MLKEMEncryptor768{pub: pub, cipherText: cipherText, sharedSecret: sharedSecret}
+}
+
+func newMLKEM1024(pub *mlkem.EncapsulationKey1024) *MLKEMEncryptor1024 {
+ sharedSecret, cipherText := pub.Encapsulate()
+ return &MLKEMEncryptor1024{pub: pub, cipherText: cipherText, sharedSecret: sharedSecret}
+}
+
+func newHybridXWing(pub *HybridXWingEncryptor) (*HybridXWingEncryptorWrapper, error) {
+ sharedSecret, ciphertext, err := pub.Encapsulate()
+ if err != nil {
+ return nil, err
+ }
+ return &HybridXWingEncryptorWrapper{enc: pub, sharedSecret: sharedSecret, ciphertext: ciphertext}, nil
+}
+
// NewAsymEncryption creates and returns a new AsymEncryption.
//
// Deprecated: Use FromPublicPEM instead.
@@ -123,15 +170,32 @@ func getPublicPart(publicKeyInPem string) (any, error) {
}
var pub any
- if strings.Contains(publicKeyInPem, "BEGIN CERTIFICATE") {
+ var err error
+ switch {
+ case strings.Contains(publicKeyInPem, "BEGIN CERTIFICATE"):
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, fmt.Errorf("x509.ParseCertificate failed: %w", err)
}
pub = cert.PublicKey
- } else {
- var err error
+ case block.Type == "MLKEM ENCAPSULATOR":
+ encap768, err := mlkem.NewEncapsulationKey768(block.Bytes)
+ if err == nil {
+ pub = encap768
+ break
+ }
+ encap1024, err1024 := mlkem.NewEncapsulationKey1024(block.Bytes)
+ if err1024 != nil {
+ return nil, fmt.Errorf("mlkem.NewEncapsulationKey1024 failed after mlkem.NewEncapsulationKey768 failed: %w / %w", err, err1024)
+ }
+ pub = encap1024
+ case block.Type == "HYBRID X-WING PUBLIC KEY":
+ pub, err = NewHybridXWingEncryptor(block.Bytes)
+ if err != nil {
+ return nil, err
+ }
+ default:
pub, err = x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("x509.ParsePKIXPublicKey failed: %w", err)
@@ -160,6 +224,18 @@ func (e ECEncryptor) Type() SchemeType {
return EC
}
+func (e MLKEMEncryptor768) Type() SchemeType {
+ return MLKEM
+}
+
+func (e MLKEMEncryptor1024) Type() SchemeType {
+ return MLKEM
+}
+
+func (e *HybridXWingEncryptorWrapper) Type() SchemeType {
+ return Hybrid
+}
+
func (e ECEncryptor) KeyType() KeyType {
switch e.pub.Curve() {
case ecdh.P256():
@@ -176,6 +252,18 @@ func (e ECEncryptor) KeyType() KeyType {
}
}
+func (e MLKEMEncryptor768) KeyType() KeyType {
+ return MLKEM768Key
+}
+
+func (e MLKEMEncryptor1024) KeyType() KeyType {
+ return MLKEM1024Key
+}
+
+func (e *HybridXWingEncryptorWrapper) KeyType() KeyType {
+ return HybridXWingKey
+}
+
func (e AsymEncryption) EphemeralKey() []byte {
return nil
}
@@ -188,6 +276,18 @@ func (e ECEncryptor) EphemeralKey() []byte {
return publicKeyBytes
}
+func (e MLKEMEncryptor768) EphemeralKey() []byte {
+ return e.cipherText
+}
+
+func (e MLKEMEncryptor1024) EphemeralKey() []byte {
+ return e.cipherText
+}
+
+func (e *HybridXWingEncryptorWrapper) EphemeralKey() []byte {
+ return e.ciphertext
+}
+
func (e AsymEncryption) Metadata() (map[string]string, error) {
return make(map[string]string), nil
}
@@ -198,6 +298,24 @@ func (e ECEncryptor) Metadata() (map[string]string, error) {
return m, nil
}
+func (e MLKEMEncryptor768) Metadata() (map[string]string, error) {
+ m := make(map[string]string)
+ m["encapsulatedKey"] = string(e.EphemeralKey())
+ return m, nil
+}
+
+func (e MLKEMEncryptor1024) Metadata() (map[string]string, error) {
+ m := make(map[string]string)
+ m["encapsulatedKey"] = string(e.EphemeralKey())
+ return m, nil
+}
+
+func (e *HybridXWingEncryptorWrapper) Metadata() (map[string]string, error) {
+ m := make(map[string]string)
+ m["encapsulatedKey"] = string(e.EphemeralKey())
+ return m, nil
+}
+
func (e AsymEncryption) Encrypt(data []byte) ([]byte, error) {
if e.PublicKey == nil {
return nil, errors.New("failed to encrypt, public key is empty")
@@ -269,7 +387,95 @@ func (e ECEncryptor) Encrypt(data []byte) ([]byte, error) {
return ciphertext, nil
}
+func (e MLKEMEncryptor768) Encrypt(data []byte) ([]byte, error) {
+ block, err := aes.NewCipher(e.sharedSecret)
+ if err != nil {
+ return nil, fmt.Errorf("aes.NewCipher failed: %w", err)
+ }
+
+ gcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return nil, fmt.Errorf("cipher.NewGCM failed: %w", err)
+ }
+
+ nonce := make([]byte, gcm.NonceSize())
+ if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
+ return nil, fmt.Errorf("nonce generation failed: %w", err)
+ }
+
+ return gcm.Seal(nonce, nonce, data, nil), nil
+}
+
+func (e MLKEMEncryptor1024) Encrypt(data []byte) ([]byte, error) {
+ block, err := aes.NewCipher(e.sharedSecret)
+ if err != nil {
+ return nil, fmt.Errorf("aes.NewCipher failed: %w", err)
+ }
+
+ gcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return nil, fmt.Errorf("cipher.NewGCM failed: %w", err)
+ }
+
+ nonce := make([]byte, gcm.NonceSize())
+ if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
+ return nil, fmt.Errorf("nonce generation failed: %w", err)
+ }
+
+ return gcm.Seal(nonce, nonce, data, nil), nil
+}
+
+func (e *HybridXWingEncryptorWrapper) Encrypt(data []byte) ([]byte, error) {
+ block, err := aes.NewCipher(e.sharedSecret)
+ if err != nil {
+ return nil, fmt.Errorf("aes.NewCipher failed: %w", err)
+ }
+
+ gcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return nil, fmt.Errorf("cipher.NewGCM failed: %w", err)
+ }
+
+ nonce := make([]byte, gcm.NonceSize())
+ if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
+ return nil, fmt.Errorf("nonce generation failed: %w", err)
+ }
+
+ return gcm.Seal(nonce, nonce, data, nil), nil
+}
+
// PublicKeyInPemFormat Returns public key in pem format.
func (e ECEncryptor) PublicKeyInPemFormat() (string, error) {
return publicKeyInPemFormat(e.ek.Public())
}
+
+func (e MLKEMEncryptor768) PublicKeyInPemFormat() (string, error) {
+ return string(pem.EncodeToMemory(&pem.Block{
+ Type: "MLKEM ENCAPSULATOR",
+ Bytes: e.pub.Bytes(),
+ })), nil
+}
+
+func (e MLKEMEncryptor1024) PublicKeyInPemFormat() (string, error) {
+ return string(pem.EncodeToMemory(&pem.Block{
+ Type: "MLKEM ENCAPSULATOR",
+ Bytes: e.pub.Bytes(),
+ })), nil
+}
+
+func (e *HybridXWingEncryptorWrapper) PublicKeyInPemFormat() (string, error) {
+ pk := hybridXWingPublicKeyASN1{
+ X25519: e.enc.pkX,
+ MLKEM768: e.enc.pkM.Bytes(),
+ }
+
+ bytes, err := asn1.Marshal(pk)
+ if err != nil {
+ return "", fmt.Errorf("failed to marshal hybrid public key: %w", err)
+ }
+
+ return string(pem.EncodeToMemory(&pem.Block{
+ Type: "HYBRID X-WING PUBLIC KEY",
+ Bytes: bytes,
+ })), nil
+}
diff --git a/lib/ocrypto/ec_key_pair.go b/lib/ocrypto/ec_key_pair.go
index f9a9554d4f..7be2225cc7 100644
--- a/lib/ocrypto/ec_key_pair.go
+++ b/lib/ocrypto/ec_key_pair.go
@@ -4,6 +4,7 @@ import (
"crypto/ecdh"
"crypto/ecdsa"
"crypto/elliptic"
+ "crypto/mlkem"
"crypto/rand"
"crypto/sha256"
"crypto/x509"
@@ -19,16 +20,6 @@ import (
type ECCMode uint8
-type KeyType string
-
-const (
- RSA2048Key KeyType = "rsa:2048"
- RSA4096Key KeyType = "rsa:4096"
- EC256Key KeyType = "ec:secp256r1"
- EC384Key KeyType = "ec:secp384r1"
- EC521Key KeyType = "ec:secp521r1"
-)
-
const (
ECCModeSecp256r1 ECCMode = 0
ECCModeSecp384r1 ECCMode = 1
@@ -36,14 +27,6 @@ const (
ECCModeSecp256k1 ECCMode = 3
)
-const (
- ECCurveP256Size = 256
- ECCurveP384Size = 384
- ECCurveP521Size = 521
- RSA2048Size = 2048
- RSA4096Size = 4096
-)
-
type KeyPair interface {
PublicKeyInPemFormat() (string, error)
PrivateKeyInPemFormat() (string, error)
@@ -64,6 +47,12 @@ func NewKeyPair(kt KeyType) (KeyPair, error) {
return nil, err
}
return NewECKeyPair(mode)
+ case MLKEM768Key:
+ return NewMLKEMKeyPair()
+ case MLKEM1024Key:
+ return NewMLKEM1024KeyPair()
+ case HybridXWingKey:
+ return NewHybridXWingKeyPair()
default:
return nil, fmt.Errorf("unsupported key type: %v", kt)
}
@@ -73,6 +62,14 @@ type ECKeyPair struct {
PrivateKey *ecdsa.PrivateKey
}
+type MLKEMKeyPair struct {
+ PrivateKey *mlkem.DecapsulationKey768
+}
+
+type MLKEM1024KeyPair struct {
+ PrivateKey *mlkem.DecapsulationKey1024
+}
+
func IsECKeyType(kt KeyType) bool {
switch kt { //nolint:exhaustive // only handle ec types
case EC256Key, EC384Key, EC521Key:
@@ -184,6 +181,24 @@ func NewECKeyPair(mode ECCMode) (ECKeyPair, error) {
return ecKeyPair, nil
}
+func NewMLKEMKeyPair() (MLKEMKeyPair, error) {
+ privateKey, err := mlkem.GenerateKey768()
+ if err != nil {
+ return MLKEMKeyPair{}, fmt.Errorf("mlkem.GenerateKey768 failed: %w", err)
+ }
+
+ return MLKEMKeyPair{PrivateKey: privateKey}, nil
+}
+
+func NewMLKEM1024KeyPair() (MLKEM1024KeyPair, error) {
+ privateKey, err := mlkem.GenerateKey1024()
+ if err != nil {
+ return MLKEM1024KeyPair{}, fmt.Errorf("mlkem.GenerateKey1024 failed: %w", err)
+ }
+
+ return MLKEM1024KeyPair{PrivateKey: privateKey}, nil
+}
+
// PrivateKeyInPemFormat Returns private key in pem format.
func (keyPair ECKeyPair) PrivateKeyInPemFormat() (string, error) {
if keyPair.PrivateKey == nil {
@@ -224,6 +239,62 @@ func (keyPair ECKeyPair) PublicKeyInPemFormat() (string, error) {
return string(publicKeyPem), nil
}
+func (keyPair MLKEMKeyPair) PrivateKeyInPemFormat() (string, error) {
+ if keyPair.PrivateKey == nil {
+ return "", errors.New("failed to generate PEM formatted private key")
+ }
+
+ privateKeyPEM := pem.EncodeToMemory(
+ &pem.Block{
+ Type: "MLKEM DECAPSULATION KEY",
+ Bytes: keyPair.PrivateKey.Bytes(),
+ },
+ )
+ return string(privateKeyPEM), nil
+}
+
+func (keyPair MLKEMKeyPair) PublicKeyInPemFormat() (string, error) {
+ if keyPair.PrivateKey == nil {
+ return "", errors.New("failed to generate PEM formatted public key")
+ }
+
+ publicKeyPEM := pem.EncodeToMemory(
+ &pem.Block{
+ Type: "MLKEM ENCAPSULATOR",
+ Bytes: keyPair.PrivateKey.EncapsulationKey().Bytes(),
+ },
+ )
+ return string(publicKeyPEM), nil
+}
+
+func (keyPair MLKEM1024KeyPair) PrivateKeyInPemFormat() (string, error) {
+ if keyPair.PrivateKey == nil {
+ return "", errors.New("failed to generate PEM formatted private key")
+ }
+
+ privateKeyPEM := pem.EncodeToMemory(
+ &pem.Block{
+ Type: "MLKEM DECAPSULATION KEY",
+ Bytes: keyPair.PrivateKey.Bytes(),
+ },
+ )
+ return string(privateKeyPEM), nil
+}
+
+func (keyPair MLKEM1024KeyPair) PublicKeyInPemFormat() (string, error) {
+ if keyPair.PrivateKey == nil {
+ return "", errors.New("failed to generate PEM formatted public key")
+ }
+
+ publicKeyPEM := pem.EncodeToMemory(
+ &pem.Block{
+ Type: "MLKEM ENCAPSULATOR",
+ Bytes: keyPair.PrivateKey.EncapsulationKey().Bytes(),
+ },
+ )
+ return string(publicKeyPEM), nil
+}
+
// KeySize Return the size of this ec key pair.
func (keyPair ECKeyPair) KeySize() (int, error) {
if keyPair.PrivateKey == nil {
@@ -494,3 +565,11 @@ func GetECKeySize(pemData []byte) (int, error) {
func (keyPair ECKeyPair) GetKeyType() KeyType {
return EC256Key
}
+
+func (keyPair MLKEMKeyPair) GetKeyType() KeyType {
+ return MLKEM768Key
+}
+
+func (keyPair MLKEM1024KeyPair) GetKeyType() KeyType {
+ return MLKEM1024Key
+}
diff --git a/lib/ocrypto/hybrid.go b/lib/ocrypto/hybrid.go
new file mode 100644
index 0000000000..cd8f42d8ee
--- /dev/null
+++ b/lib/ocrypto/hybrid.go
@@ -0,0 +1,234 @@
+package ocrypto
+
+import (
+ "crypto/ecdh"
+ "crypto/mlkem"
+ "crypto/rand"
+ "encoding/asn1"
+ "encoding/pem"
+ "errors"
+ "fmt"
+
+ "golang.org/x/crypto/sha3"
+)
+
+// HybridXWingKeyPair combines X25519 and ML-KEM-768
+type HybridXWingKeyPair struct {
+ X25519 *ecdh.PrivateKey
+ MLKEM768 *mlkem.DecapsulationKey768
+}
+
+type hybridXWingPublicKeyASN1 struct {
+ X25519 []byte
+ MLKEM768 []byte
+}
+
+type hybridXWingPrivateKeyASN1 struct {
+ X25519 []byte
+ MLKEM768 []byte
+}
+
+type hybridXWingCiphertextASN1 struct {
+ X25519 []byte
+ MLKEM768 []byte
+}
+
+func NewHybridXWingKeyPair() (*HybridXWingKeyPair, error) {
+ x25519, err := ecdh.X25519().GenerateKey(rand.Reader)
+ if err != nil {
+ return nil, fmt.Errorf("ecdh.X25519.GenerateKey failed: %w", err)
+ }
+
+ mlkem768, err := mlkem.GenerateKey768()
+ if err != nil {
+ return nil, fmt.Errorf("mlkem.GenerateKey768 failed: %w", err)
+ }
+
+ return &HybridXWingKeyPair{
+ X25519: x25519,
+ MLKEM768: mlkem768,
+ }, nil
+}
+
+func (kp *HybridXWingKeyPair) GetKeyType() KeyType {
+ return HybridXWingKey
+}
+
+func (kp *HybridXWingKeyPair) PublicKeyInPemFormat() (string, error) {
+ pk := hybridXWingPublicKeyASN1{
+ X25519: kp.X25519.PublicKey().Bytes(),
+ MLKEM768: kp.MLKEM768.EncapsulationKey().Bytes(),
+ }
+
+ bytes, err := asn1.Marshal(pk)
+ if err != nil {
+ return "", fmt.Errorf("failed to marshal hybrid public key: %w", err)
+ }
+
+ return string(pem.EncodeToMemory(&pem.Block{
+ Type: "HYBRID X-WING PUBLIC KEY",
+ Bytes: bytes,
+ })), nil
+}
+
+func (kp *HybridXWingKeyPair) PrivateKeyInPemFormat() (string, error) {
+ sk := hybridXWingPrivateKeyASN1{
+ X25519: kp.X25519.Bytes(),
+ MLKEM768: kp.MLKEM768.Bytes(),
+ }
+
+ bytes, err := asn1.Marshal(sk)
+ if err != nil {
+ return "", fmt.Errorf("failed to marshal hybrid private key: %w", err)
+ }
+
+ return string(pem.EncodeToMemory(&pem.Block{
+ Type: "HYBRID X-WING PRIVATE KEY",
+ Bytes: bytes,
+ })), nil
+}
+
+// X-Wing KEM Shared Secret computation as per draft-connolly-cfrg-xwing-kem-10
+// Shared Secret: SHA3-256("\X-Wing" || ss_X || ss_M || X25519_pk || ML-KEM-768_pk || X25519_ct || ML-KEM-768_ct)
+func computeXWingSharedSecret(ssX, ssM, pkX, pkM, ctX, ctM []byte) []byte {
+ h := sha3.New256()
+ h.Write([]byte("\\X-Wing"))
+ h.Write(ssX)
+ h.Write(ssM)
+ h.Write(pkX)
+ h.Write(pkM)
+ h.Write(ctX)
+ h.Write(ctM)
+ return h.Sum(nil)
+}
+
+type HybridXWingEncryptor struct {
+ pkX []byte
+ pkM *mlkem.EncapsulationKey768
+}
+
+func NewHybridXWingEncryptor(pk []byte) (*HybridXWingEncryptor, error) {
+ var pkASN hybridXWingPublicKeyASN1
+ if _, err := asn1.Unmarshal(pk, &pkASN); err != nil {
+ return nil, fmt.Errorf("failed to unmarshal hybrid public key: %w", err)
+ }
+
+ pkM, err := mlkem.NewEncapsulationKey768(pkASN.MLKEM768)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create MLKEM encapsulation key: %w", err)
+ }
+
+ return &HybridXWingEncryptor{
+ pkX: pkASN.X25519,
+ pkM: pkM,
+ }, nil
+}
+
+func (e *HybridXWingEncryptor) Encapsulate() ([]byte, []byte, error) {
+ // X25519 encapsulation
+ ekX, err := ecdh.X25519().GenerateKey(rand.Reader)
+ if err != nil {
+ return nil, nil, err
+ }
+ pkX, err := ecdh.X25519().NewPublicKey(e.pkX)
+ if err != nil {
+ return nil, nil, err
+ }
+ ssX, err := ekX.ECDH(pkX)
+ if err != nil {
+ return nil, nil, err
+ }
+ ctX := ekX.PublicKey().Bytes()
+
+ // ML-KEM-768 encapsulation
+ ssM, ctM := e.pkM.Encapsulate()
+
+ // Compute combined shared secret
+ sharedSecret := computeXWingSharedSecret(ssX, ssM, e.pkX, e.pkM.Bytes(), ctX, ctM)
+
+ // Marshal ciphertext into ASN.1
+ ctASN := hybridXWingCiphertextASN1{
+ X25519: ctX,
+ MLKEM768: ctM,
+ }
+ ciphertext, err := asn1.Marshal(ctASN)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ return sharedSecret, ciphertext, nil
+}
+
+type HybridXWingDecryptor struct {
+ skX *ecdh.PrivateKey
+ skM *mlkem.DecapsulationKey768
+}
+
+func NewHybridXWingDecryptor(sk []byte) (*HybridXWingDecryptor, error) {
+ var skASN hybridXWingPrivateKeyASN1
+ if _, err := asn1.Unmarshal(sk, &skASN); err != nil {
+ return nil, fmt.Errorf("failed to unmarshal hybrid private key: %w", err)
+ }
+
+ skX, err := ecdh.X25519().NewPrivateKey(skASN.X25519)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create X25519 private key: %w", err)
+ }
+
+ skM, err := mlkem.NewDecapsulationKey768(skASN.MLKEM768)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create MLKEM decapsulation key: %w", err)
+ }
+
+ return &HybridXWingDecryptor{
+ skX: skX,
+ skM: skM,
+ }, nil
+}
+
+func (d *HybridXWingDecryptor) Decapsulate(ciphertext []byte) ([]byte, error) {
+ var ctASN hybridXWingCiphertextASN1
+ if _, err := asn1.Unmarshal(ciphertext, &ctASN); err != nil {
+ return nil, fmt.Errorf("failed to unmarshal hybrid ciphertext: %w", err)
+ }
+
+ // X25519 decapsulation
+ pkX, err := ecdh.X25519().NewPublicKey(ctASN.X25519)
+ if err != nil {
+ return nil, err
+ }
+ ssX, err := d.skX.ECDH(pkX)
+ if err != nil {
+ return nil, err
+ }
+
+ // ML-KEM-768 decapsulation
+ ssM, err := d.skM.Decapsulate(ctASN.MLKEM768)
+ if err != nil {
+ return nil, err
+ }
+
+ // Compute combined shared secret
+ sharedSecret := computeXWingSharedSecret(ssX, ssM, d.skX.PublicKey().Bytes(), d.skM.EncapsulationKey().Bytes(), ctASN.X25519, ctASN.MLKEM768)
+
+ return sharedSecret, nil
+}
+
+// Convert from PEM format to internal encryptor/decryptor
+func HybridEncryptorFromPEM(publicKeyInPem string) (*HybridXWingEncryptor, error) {
+ block, _ := pem.Decode([]byte(publicKeyInPem))
+ if block == nil || block.Type != "HYBRID X-WING PUBLIC KEY" {
+ return nil, errors.New("failed to parse HYBRID X-WING PUBLIC KEY")
+ }
+
+ return NewHybridXWingEncryptor(block.Bytes)
+}
+
+func HybridDecryptorFromPEM(privateKeyInPem string) (*HybridXWingDecryptor, error) {
+ block, _ := pem.Decode([]byte(privateKeyInPem))
+ if block == nil || block.Type != "HYBRID X-WING PRIVATE KEY" {
+ return nil, errors.New("failed to parse HYBRID X-WING PRIVATE KEY")
+ }
+
+ return NewHybridXWingDecryptor(block.Bytes)
+}
diff --git a/lib/ocrypto/hybrid_test.go b/lib/ocrypto/hybrid_test.go
new file mode 100644
index 0000000000..f10738f410
--- /dev/null
+++ b/lib/ocrypto/hybrid_test.go
@@ -0,0 +1,81 @@
+package ocrypto
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestHybridXWingRoundtrip(t *testing.T) {
+ // Generate key pair
+ kp, err := NewHybridXWingKeyPair()
+ require.NoError(t, err)
+ require.NotNil(t, kp)
+
+ publicKeyPEM, err := kp.PublicKeyInPemFormat()
+ require.NoError(t, err)
+ require.NotEmpty(t, publicKeyPEM)
+
+ privateKeyPEM, err := kp.PrivateKeyInPemFormat()
+ require.NoError(t, err)
+ require.NotEmpty(t, privateKeyPEM)
+
+ // Create encryptor and decryptor
+ encryptor, err := HybridEncryptorFromPEM(publicKeyPEM)
+ require.NoError(t, err)
+ require.NotNil(t, encryptor)
+
+ decryptor, err := HybridDecryptorFromPEM(privateKeyPEM)
+ require.NoError(t, err)
+ require.NotNil(t, decryptor)
+
+ // Encapsulate
+ ssEnc, ct, err := encryptor.Encapsulate()
+ require.NoError(t, err)
+ require.NotEmpty(t, ssEnc)
+ require.NotEmpty(t, ct)
+
+ // Decapsulate
+ ssDec, err := decryptor.Decapsulate(ct)
+ require.NoError(t, err)
+ require.Equal(t, ssEnc, ssDec)
+}
+
+func TestHybridXWingAsymEncryptionRoundtrip(t *testing.T) {
+ // Generate key pair
+ kp, err := NewHybridXWingKeyPair()
+ require.NoError(t, err)
+
+ publicKeyPEM, err := kp.PublicKeyInPemFormat()
+ require.NoError(t, err)
+
+ privateKeyPEM, err := kp.PrivateKeyInPemFormat()
+ require.NoError(t, err)
+
+ // Create encryptor and decryptor via common interfaces
+ encryptor, err := FromPublicPEM(publicKeyPEM)
+ require.NoError(t, err)
+ assert.Equal(t, Hybrid, encryptor.Type())
+ assert.Equal(t, HybridXWingKey, encryptor.KeyType())
+
+ decryptor, err := FromPrivatePEM(privateKeyPEM)
+ require.NoError(t, err)
+
+ // Data to encrypt
+ data := []byte("hello world, hybrid style")
+
+ // Encrypt
+ ciphertext, err := encryptor.Encrypt(data)
+ require.NoError(t, err)
+ require.NotEmpty(t, ciphertext)
+
+ // Get ephemeral key (ciphertext from KEM)
+ ephemeral := encryptor.EphemeralKey()
+ require.NotEmpty(t, ephemeral)
+
+ // Decrypt
+ plaintext, err := decryptor.DecryptWithEphemeralKey(ciphertext, ephemeral)
+ require.NoError(t, err)
+ assert.Equal(t, data, plaintext)
+}
diff --git a/lib/ocrypto/key_types.go b/lib/ocrypto/key_types.go
new file mode 100644
index 0000000000..cdfb56584d
--- /dev/null
+++ b/lib/ocrypto/key_types.go
@@ -0,0 +1,25 @@
+package ocrypto
+
+type KeyType string
+
+const (
+ RSA2048Key KeyType = "rsa:2048"
+ RSA4096Key KeyType = "rsa:4096"
+ EC256Key KeyType = "ec:secp256r1"
+ EC384Key KeyType = "ec:secp384r1"
+ EC521Key KeyType = "ec:secp521r1"
+ MLKEM768Key KeyType = "mlkem:768"
+ MLKEM1024Key KeyType = "mlkem:1024"
+ HybridXWingKey KeyType = "hpqt:xwing"
+)
+
+const (
+ RSA2048Size = 2048
+ RSA4096Size = 4096
+)
+
+const (
+ ECCurveP256Size = 256
+ ECCurveP384Size = 384
+ ECCurveP521Size = 521
+)
diff --git a/protocol/go/kas/kas.pb.go b/protocol/go/kas/kas.pb.go
index 6d6fb574e3..ea24285f83 100644
--- a/protocol/go/kas/kas.pb.go
+++ b/protocol/go/kas/kas.pb.go
@@ -244,7 +244,7 @@ type KeyAccess struct {
Protocol string `protobuf:"bytes,3,opt,name=protocol,proto3" json:"protocol,omitempty"`
// Type of key wrapping used for the data encryption key
// Required: Always
- // Values: 'wrapped' (RSA-wrapped for ZTDF), 'ec-wrapped' (experimental ECDH-wrapped)
+ // Values: 'wrapped' (RSA-wrapped for ZTDF), 'ec-wrapped' (experimental ECDH-wrapped), 'mlkem-wrapped' (ML-KEM-wrapped), 'hybrid' (Hybrid X-Wing-wrapped)
KeyType string `protobuf:"bytes,4,opt,name=key_type,json=type,proto3" json:"key_type,omitempty"`
// URL of the Key Access Server that can unwrap this key
// Optional: May be omitted if KAS URL is known from context
@@ -269,10 +269,10 @@ type KeyAccess struct {
// Optional: Not used by ZTDF (policy and metadata are separate)
// Contains magic bytes, version, algorithm, policy, and ephemeral key information
Header []byte `protobuf:"bytes,9,opt,name=header,proto3" json:"header,omitempty"`
- // Ephemeral public key for ECDH key derivation (ec-wrapped type only)
- // Required: When key_type="ec-wrapped" (experimental ECDH-based ZTDF)
+ // Ephemeral public key for ECDH/ML-KEM/Hybrid key derivation
+ // Required: When key_type="ec-wrapped", "mlkem-wrapped", or "hybrid"
// Omitted: When key_type="wrapped" (RSA-based ZTDF)
- // Should be a PEM-encoded PKCS#8 (ASN.1) formatted public key
+ // Should be a PEM-encoded or Base64-encoded (for ML-KEM/Hybrid) public key material
// Used to derive the symmetric key for unwrapping the DEK
EphemeralPublicKey string `protobuf:"bytes,10,opt,name=ephemeral_public_key,json=ephemeralPublicKey,proto3" json:"ephemeral_public_key,omitempty"`
}
@@ -855,8 +855,8 @@ type RewrapResponse struct {
// Deprecated: Marked as deprecated in kas/kas.proto.
EntityWrappedKey []byte `protobuf:"bytes,2,opt,name=entity_wrapped_key,json=entityWrappedKey,proto3" json:"entity_wrapped_key,omitempty"`
// KAS's ephemeral session public key in PEM format
- // Required: For EC-based operations (key_type="ec-wrapped")
- // Optional: Empty for RSA-based ZTDF (key_type="wrapped")
+ // Required: For EC-based operations (key_type="ec-wrapped") or Hybrid
+ // Optional: Empty for RSA-based ZTDF (key_type="wrapped") or ML-KEM
// Used by client to perform ECDH key agreement and decrypt the kas_wrapped_key values
SessionPublicKey string `protobuf:"bytes,3,opt,name=session_public_key,json=sessionPublicKey,proto3" json:"session_public_key,omitempty"`
// Deprecated: Legacy schema version identifier
diff --git a/protocol/go/policy/kasregistry/key_access_server_registry.pb.go b/protocol/go/policy/kasregistry/key_access_server_registry.pb.go
index 8e5c7b58b5..5d0d36b958 100644
--- a/protocol/go/policy/kasregistry/key_access_server_registry.pb.go
+++ b/protocol/go/policy/kasregistry/key_access_server_registry.pb.go
@@ -4012,218 +4012,219 @@ var file_policy_kasregistry_key_access_server_registry_proto_rawDesc = []byte{
0x12, 0x34, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x61,
0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69,
- 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x02, 0x18, 0x01, 0x22, 0xcc, 0x0c, 0x0a, 0x10, 0x43,
+ 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x02, 0x18, 0x01, 0x22, 0xd4, 0x0c, 0x0a, 0x10, 0x43,
0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x1f, 0x0a, 0x06, 0x6b, 0x61, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42,
0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x05, 0x6b, 0x61, 0x73, 0x49, 0x64,
0x12, 0x1e, 0x0a, 0x06, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64,
- 0x12, 0xa4, 0x01, 0x0a, 0x0d, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74,
+ 0x12, 0xac, 0x01, 0x0a, 0x0d, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74,
0x68, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63,
- 0x79, 0x2e, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x42, 0x6c, 0xba, 0x48, 0x69,
- 0xba, 0x01, 0x66, 0x0a, 0x15, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74,
+ 0x79, 0x2e, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x42, 0x74, 0xba, 0x48, 0x71,
+ 0xba, 0x01, 0x6e, 0x0a, 0x15, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74,
0x68, 0x6d, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x12, 0x34, 0x54, 0x68, 0x65, 0x20,
0x6b, 0x65, 0x79, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x20, 0x6d, 0x75,
0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e,
- 0x1a, 0x17, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x5b, 0x31, 0x2c, 0x20, 0x32, 0x2c,
- 0x20, 0x33, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x35, 0x5d, 0x52, 0x0c, 0x6b, 0x65, 0x79, 0x41, 0x6c,
- 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x93, 0x01, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f,
- 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x70, 0x6f, 0x6c,
- 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x65, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x42, 0x67, 0xba, 0x48, 0x64,
- 0xba, 0x01, 0x61, 0x0a, 0x10, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x5f, 0x64, 0x65,
- 0x66, 0x69, 0x6e, 0x65, 0x64, 0x12, 0x35, 0x54, 0x68, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x5f, 0x6d,
- 0x6f, 0x64, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20,
- 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x76,
- 0x61, 0x6c, 0x75, 0x65, 0x73, 0x20, 0x28, 0x31, 0x2d, 0x34, 0x29, 0x2e, 0x1a, 0x16, 0x74, 0x68,
- 0x69, 0x73, 0x20, 0x3e, 0x3d, 0x20, 0x31, 0x20, 0x26, 0x26, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20,
- 0x3c, 0x3d, 0x20, 0x34, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x42, 0x0a,
- 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x63, 0x74, 0x78, 0x18,
- 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50,
- 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x43, 0x74, 0x78, 0x42, 0x06, 0xba, 0x48, 0x03,
- 0xc8, 0x01, 0x01, 0x52, 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x43, 0x74,
- 0x78, 0x12, 0x3d, 0x0a, 0x0f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79,
- 0x5f, 0x63, 0x74, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x6f, 0x6c,
- 0x69, 0x63, 0x79, 0x2e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x43, 0x74,
- 0x78, 0x52, 0x0d, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x43, 0x74, 0x78,
- 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e,
- 0x66, 0x69, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72,
- 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x49, 0x64, 0x12, 0x16,
- 0x0a, 0x06, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06,
- 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x12, 0x33, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
- 0x74, 0x61, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
- 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x75, 0x74, 0x61, 0x62, 0x6c,
- 0x65, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x3a, 0xbb, 0x07, 0xba, 0x48,
- 0xb7, 0x07, 0x1a, 0x97, 0x03, 0x0a, 0x23, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b,
- 0x65, 0x79, 0x5f, 0x63, 0x74, 0x78, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x6c,
- 0x79, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0xbc, 0x01, 0x54, 0x68, 0x65,
- 0x20, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x20, 0x69, 0x73, 0x20,
- 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x69, 0x66, 0x20, 0x6b, 0x65, 0x79, 0x5f,
- 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x73, 0x20, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45,
- 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x4b, 0x45, 0x59,
- 0x20, 0x6f, 0x72, 0x20, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x50, 0x52, 0x4f,
- 0x56, 0x49, 0x44, 0x45, 0x52, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x4b, 0x45, 0x59, 0x2e, 0x20,
- 0x54, 0x68, 0x65, 0x20, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x20,
- 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x20, 0x69, 0x66,
- 0x20, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x73, 0x20, 0x4b, 0x45, 0x59,
- 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x20, 0x6f, 0x72, 0x20,
- 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f,
- 0x4b, 0x45, 0x59, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x2e, 0x1a, 0xb0, 0x01, 0x28, 0x28, 0x74, 0x68,
- 0x69, 0x73, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x31,
- 0x20, 0x7c, 0x7c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64,
- 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x32, 0x29, 0x20, 0x26, 0x26, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e,
- 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x63, 0x74, 0x78, 0x2e,
- 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x20, 0x21, 0x3d, 0x20, 0x27,
- 0x27, 0x29, 0x20, 0x7c, 0x7c, 0x20, 0x28, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6b, 0x65, 0x79,
- 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x33, 0x20, 0x7c, 0x7c, 0x20, 0x74, 0x68,
- 0x69, 0x73, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x34,
- 0x29, 0x20, 0x26, 0x26, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74,
- 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x63, 0x74, 0x78, 0x2e, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65,
- 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x20, 0x3d, 0x3d, 0x20, 0x27, 0x27, 0x29, 0x1a, 0xf4, 0x02, 0x0a,
- 0x26, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
- 0x5f, 0x69, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x5f, 0x72,
- 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0xa8, 0x01, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64,
- 0x65, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, 0x69, 0x64, 0x20, 0x69, 0x73, 0x20,
- 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x69, 0x66, 0x20, 0x6b, 0x65, 0x79, 0x5f,
- 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x73, 0x20, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45,
- 0x5f, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x44, 0x45, 0x52, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x4b,
- 0x45, 0x59, 0x20, 0x6f, 0x72, 0x20, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x52,
- 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x2e, 0x20, 0x49, 0x74, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62,
- 0x65, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x4b, 0x45, 0x59, 0x5f,
- 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x5f, 0x52, 0x4f, 0x4f, 0x54,
- 0x5f, 0x4b, 0x45, 0x59, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44,
- 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x4f, 0x4e, 0x4c,
- 0x59, 0x2e, 0x1a, 0x9e, 0x01, 0x28, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6b, 0x65, 0x79, 0x5f,
- 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x31, 0x20, 0x7c, 0x7c, 0x20, 0x74, 0x68, 0x69,
- 0x73, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x34, 0x29,
- 0x20, 0x26, 0x26, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,
- 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x69, 0x64, 0x20, 0x3d, 0x3d, 0x20, 0x27,
- 0x27, 0x29, 0x20, 0x7c, 0x7c, 0x20, 0x28, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6b, 0x65, 0x79,
- 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x32, 0x20, 0x7c, 0x7c, 0x20, 0x74, 0x68,
- 0x69, 0x73, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x33,
- 0x29, 0x20, 0x26, 0x26, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64,
- 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x69, 0x64, 0x20, 0x21, 0x3d, 0x20,
- 0x27, 0x27, 0x29, 0x1a, 0xa3, 0x01, 0x0a, 0x23, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f,
- 0x6b, 0x65, 0x79, 0x5f, 0x63, 0x74, 0x78, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c,
- 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x12, 0x48, 0x70, 0x72, 0x69,
- 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x63, 0x74, 0x78, 0x20, 0x6d, 0x75, 0x73,
- 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20, 0x69, 0x66, 0x20,
- 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x73, 0x20, 0x4b, 0x45, 0x59, 0x5f,
- 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x4b, 0x45, 0x59, 0x5f,
- 0x4f, 0x4e, 0x4c, 0x59, 0x2e, 0x1a, 0x32, 0x21, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6b, 0x65,
- 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x34, 0x20, 0x26, 0x26, 0x20, 0x68,
- 0x61, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f,
- 0x6b, 0x65, 0x79, 0x5f, 0x63, 0x74, 0x78, 0x29, 0x29, 0x22, 0x3c, 0x0a, 0x11, 0x43, 0x72, 0x65,
- 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27,
- 0x0a, 0x07, 0x6b, 0x61, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x0e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x52,
- 0x06, 0x6b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x22, 0x7a, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4b, 0x65,
- 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02,
+ 0x1a, 0x1f, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x5b, 0x31, 0x2c, 0x20, 0x32, 0x2c,
+ 0x20, 0x33, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x32, 0x30, 0x2c, 0x20, 0x32, 0x31,
+ 0x5d, 0x52, 0x0c, 0x6b, 0x65, 0x79, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12,
+ 0x93, 0x01, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01,
+ 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x65, 0x79, 0x4d,
+ 0x6f, 0x64, 0x65, 0x42, 0x67, 0xba, 0x48, 0x64, 0xba, 0x01, 0x61, 0x0a, 0x10, 0x6b, 0x65, 0x79,
+ 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x12, 0x35, 0x54,
+ 0x68, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74,
+ 0x20, 0x62, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x20, 0x28, 0x31,
+ 0x2d, 0x34, 0x29, 0x2e, 0x1a, 0x16, 0x74, 0x68, 0x69, 0x73, 0x20, 0x3e, 0x3d, 0x20, 0x31, 0x20,
+ 0x26, 0x26, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x3c, 0x3d, 0x20, 0x34, 0x52, 0x07, 0x6b, 0x65,
+ 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x42, 0x0a, 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f,
+ 0x6b, 0x65, 0x79, 0x5f, 0x63, 0x74, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e,
+ 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79,
+ 0x43, 0x74, 0x78, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0c, 0x70, 0x75, 0x62,
+ 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x43, 0x74, 0x78, 0x12, 0x3d, 0x0a, 0x0f, 0x70, 0x72, 0x69,
+ 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x63, 0x74, 0x78, 0x18, 0x06, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x72, 0x69, 0x76,
+ 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x43, 0x74, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x69, 0x76, 0x61,
+ 0x74, 0x65, 0x4b, 0x65, 0x79, 0x43, 0x74, 0x78, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x76,
+ 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x07,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79,
+ 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x12, 0x33,
+ 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
+ 0x74, 0x61, 0x4d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64,
+ 0x61, 0x74, 0x61, 0x3a, 0xbb, 0x07, 0xba, 0x48, 0xb7, 0x07, 0x1a, 0x97, 0x03, 0x0a, 0x23, 0x70,
+ 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x63, 0x74, 0x78, 0x5f, 0x6f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72,
+ 0x65, 0x64, 0x12, 0xbc, 0x01, 0x54, 0x68, 0x65, 0x20, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64,
+ 0x5f, 0x6b, 0x65, 0x79, 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64,
+ 0x20, 0x69, 0x66, 0x20, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x73, 0x20,
+ 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x5f,
+ 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x4b, 0x45, 0x59, 0x20, 0x6f, 0x72, 0x20, 0x4b, 0x45, 0x59, 0x5f,
+ 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x44, 0x45, 0x52, 0x5f, 0x52, 0x4f,
+ 0x4f, 0x54, 0x5f, 0x4b, 0x45, 0x59, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x77, 0x72, 0x61, 0x70,
+ 0x70, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20,
+ 0x65, 0x6d, 0x70, 0x74, 0x79, 0x20, 0x69, 0x66, 0x20, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64,
+ 0x65, 0x20, 0x69, 0x73, 0x20, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x52, 0x45,
+ 0x4d, 0x4f, 0x54, 0x45, 0x20, 0x6f, 0x72, 0x20, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45,
+ 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x4f, 0x4e, 0x4c, 0x59,
+ 0x2e, 0x1a, 0xb0, 0x01, 0x28, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x6d,
+ 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x31, 0x20, 0x7c, 0x7c, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x32, 0x29, 0x20,
+ 0x26, 0x26, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f,
+ 0x6b, 0x65, 0x79, 0x5f, 0x63, 0x74, 0x78, 0x2e, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f,
+ 0x6b, 0x65, 0x79, 0x20, 0x21, 0x3d, 0x20, 0x27, 0x27, 0x29, 0x20, 0x7c, 0x7c, 0x20, 0x28, 0x28,
+ 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x3d,
+ 0x20, 0x33, 0x20, 0x7c, 0x7c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x6d,
+ 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x34, 0x29, 0x20, 0x26, 0x26, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x2e, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x63, 0x74,
+ 0x78, 0x2e, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x20, 0x3d, 0x3d,
+ 0x20, 0x27, 0x27, 0x29, 0x1a, 0xf4, 0x02, 0x0a, 0x26, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,
+ 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x69, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69,
+ 0x6f, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12,
+ 0xa8, 0x01, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69,
+ 0x67, 0x20, 0x69, 0x64, 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64,
+ 0x20, 0x69, 0x66, 0x20, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x73, 0x20,
+ 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x44, 0x45,
+ 0x52, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x4b, 0x45, 0x59, 0x20, 0x6f, 0x72, 0x20, 0x4b, 0x45,
+ 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x2e, 0x20, 0x49,
+ 0x74, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x43, 0x4f, 0x4e,
+ 0x46, 0x49, 0x47, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x4b, 0x45, 0x59, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43,
+ 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x2e, 0x1a, 0x9e, 0x01, 0x28, 0x28, 0x74,
+ 0x68, 0x69, 0x73, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x3d, 0x20,
+ 0x31, 0x20, 0x7c, 0x7c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f,
+ 0x64, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x34, 0x29, 0x20, 0x26, 0x26, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x5f, 0x69, 0x64, 0x20, 0x3d, 0x3d, 0x20, 0x27, 0x27, 0x29, 0x20, 0x7c, 0x7c, 0x20, 0x28, 0x28,
+ 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x3d,
+ 0x20, 0x32, 0x20, 0x7c, 0x7c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x6d,
+ 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x33, 0x29, 0x20, 0x26, 0x26, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
+ 0x67, 0x5f, 0x69, 0x64, 0x20, 0x21, 0x3d, 0x20, 0x27, 0x27, 0x29, 0x1a, 0xa3, 0x01, 0x0a, 0x23,
+ 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x63, 0x74, 0x78, 0x5f,
+ 0x66, 0x6f, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x6f,
+ 0x6e, 0x6c, 0x79, 0x12, 0x48, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79,
+ 0x5f, 0x63, 0x74, 0x78, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65,
+ 0x20, 0x73, 0x65, 0x74, 0x20, 0x69, 0x66, 0x20, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65,
+ 0x20, 0x69, 0x73, 0x20, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x50, 0x55, 0x42,
+ 0x4c, 0x49, 0x43, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x2e, 0x1a, 0x32, 0x21,
+ 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x3d,
+ 0x3d, 0x20, 0x34, 0x20, 0x26, 0x26, 0x20, 0x68, 0x61, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e,
+ 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x63, 0x74, 0x78, 0x29,
+ 0x29, 0x22, 0x3c, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x07, 0x6b, 0x61, 0x73, 0x5f, 0x6b, 0x65,
+ 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79,
+ 0x2e, 0x4b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x52, 0x06, 0x6b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x22,
+ 0x7a, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x12, 0x1a, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48,
+ 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x12, 0x38, 0x0a, 0x03,
+ 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x6f, 0x6c, 0x69,
+ 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4b,
+ 0x61, 0x73, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x48,
+ 0x00, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x42, 0x13, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69,
+ 0x66, 0x69, 0x65, 0x72, 0x12, 0x05, 0xba, 0x48, 0x02, 0x08, 0x01, 0x22, 0x39, 0x0a, 0x0e, 0x47,
+ 0x65, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a,
+ 0x07, 0x6b, 0x61, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e,
+ 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x52, 0x06,
+ 0x6b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x22, 0x96, 0x03, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4b,
+ 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0xa7, 0x01, 0x0a, 0x0d, 0x6b,
+ 0x65, 0x79, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x6c, 0x67, 0x6f,
+ 0x72, 0x69, 0x74, 0x68, 0x6d, 0x42, 0x6f, 0xba, 0x48, 0x6c, 0xba, 0x01, 0x69, 0x0a, 0x15, 0x6b,
+ 0x65, 0x79, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x5f, 0x64, 0x65, 0x66,
+ 0x69, 0x6e, 0x65, 0x64, 0x12, 0x34, 0x54, 0x68, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x6c,
+ 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20,
+ 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e,
+ 0x65, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x1a, 0x1a, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x69, 0x6e, 0x20, 0x5b, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x2c,
+ 0x20, 0x34, 0x2c, 0x20, 0x35, 0x5d, 0x52, 0x0c, 0x6b, 0x65, 0x79, 0x41, 0x6c, 0x67, 0x6f, 0x72,
+ 0x69, 0x74, 0x68, 0x6d, 0x12, 0x21, 0x0a, 0x06, 0x6b, 0x61, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x48, 0x00,
- 0x52, 0x02, 0x69, 0x64, 0x12, 0x38, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65,
- 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x65,
- 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x48, 0x00, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x42, 0x13,
- 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x05, 0xba, 0x48,
- 0x02, 0x08, 0x01, 0x22, 0x39, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x07, 0x6b, 0x61, 0x73, 0x5f, 0x6b, 0x65, 0x79,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
- 0x4b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x52, 0x06, 0x6b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x22, 0x96,
- 0x03, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x12, 0xa7, 0x01, 0x0a, 0x0d, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72,
- 0x69, 0x74, 0x68, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c,
- 0x69, 0x63, 0x79, 0x2e, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x42, 0x6f, 0xba,
- 0x48, 0x6c, 0xba, 0x01, 0x69, 0x0a, 0x15, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72,
- 0x69, 0x74, 0x68, 0x6d, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x12, 0x34, 0x54, 0x68,
- 0x65, 0x20, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x20,
- 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
- 0x68, 0x65, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65,
- 0x73, 0x2e, 0x1a, 0x1a, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x5b, 0x30, 0x2c, 0x20,
- 0x31, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x35, 0x5d, 0x52, 0x0c,
- 0x6b, 0x65, 0x79, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x21, 0x0a, 0x06,
- 0x6b, 0x61, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48,
- 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x48, 0x00, 0x52, 0x05, 0x6b, 0x61, 0x73, 0x49, 0x64, 0x12,
- 0x24, 0x0a, 0x08, 0x6b, 0x61, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x07, 0x6b, 0x61,
- 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x07, 0x6b, 0x61, 0x73, 0x5f, 0x75, 0x72, 0x69,
- 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0x72, 0x05, 0x10, 0x01, 0x88,
- 0x01, 0x01, 0x48, 0x00, 0x52, 0x06, 0x6b, 0x61, 0x73, 0x55, 0x72, 0x69, 0x12, 0x1b, 0x0a, 0x06,
- 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x48, 0x01, 0x52, 0x06,
- 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x88, 0x01, 0x01, 0x12, 0x33, 0x0a, 0x0a, 0x70, 0x61, 0x67,
- 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e,
- 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0c,
- 0x0a, 0x0a, 0x6b, 0x61, 0x73, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x42, 0x09, 0x0a, 0x07,
- 0x5f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x22, 0x73, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4b,
- 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x08, 0x6b,
- 0x61, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e,
- 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x52, 0x07, 0x6b,
- 0x61, 0x73, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x34, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x6f, 0x6c,
- 0x69, 0x63, 0x79, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
- 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x86, 0x03, 0x0a,
- 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba,
- 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x33, 0x0a, 0x08, 0x6d,
- 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
- 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d,
- 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
- 0x12, 0x54, 0x0a, 0x18, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64,
- 0x61, 0x74, 0x65, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, 0x65, 0x20, 0x01,
- 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61,
- 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x16,
- 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x65,
- 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x3a, 0xcc, 0x01, 0xba, 0x48, 0xc8, 0x01, 0x1a, 0xc5, 0x01,
- 0x0a, 0x18, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74,
- 0x65, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x52, 0x4d, 0x65, 0x74, 0x61,
- 0x64, 0x61, 0x74, 0x61, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x62, 0x65, 0x68, 0x61,
- 0x76, 0x69, 0x6f, 0x72, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x65, 0x69, 0x74,
- 0x68, 0x65, 0x72, 0x20, 0x41, 0x50, 0x50, 0x45, 0x4e, 0x44, 0x20, 0x6f, 0x72, 0x20, 0x52, 0x45,
- 0x50, 0x4c, 0x41, 0x43, 0x45, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x75, 0x70, 0x64, 0x61,
- 0x74, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x1a, 0x55,
- 0x28, 0x28, 0x21, 0x68, 0x61, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x65, 0x74, 0x61,
- 0x64, 0x61, 0x74, 0x61, 0x29, 0x29, 0x20, 0x7c, 0x7c, 0x20, 0x28, 0x68, 0x61, 0x73, 0x28, 0x74,
- 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x29, 0x20, 0x26, 0x26,
- 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75,
- 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x20, 0x21,
- 0x3d, 0x20, 0x30, 0x29, 0x29, 0x22, 0x3c, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b,
- 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x07, 0x6b, 0x61,
- 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6f,
- 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x52, 0x06, 0x6b, 0x61, 0x73,
- 0x4b, 0x65, 0x79, 0x22, 0xa4, 0x01, 0x0a, 0x10, 0x4b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x49, 0x64,
- 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x06, 0x6b, 0x61, 0x73, 0x5f,
- 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0,
- 0x01, 0x01, 0x48, 0x00, 0x52, 0x05, 0x6b, 0x61, 0x73, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x04, 0x6e,
+ 0x52, 0x05, 0x6b, 0x61, 0x73, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x08, 0x6b, 0x61, 0x73, 0x5f, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02,
- 0x10, 0x01, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x03, 0x75, 0x72,
- 0x69, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0x72, 0x05, 0x10, 0x01,
- 0x88, 0x01, 0x01, 0x48, 0x00, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x19, 0x0a, 0x03, 0x6b, 0x69,
- 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01,
- 0x52, 0x03, 0x6b, 0x69, 0x64, 0x42, 0x13, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66,
- 0x69, 0x65, 0x72, 0x12, 0x05, 0xba, 0x48, 0x02, 0x08, 0x01, 0x22, 0xe5, 0x0e, 0x0a, 0x10, 0x52,
- 0x6f, 0x74, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
- 0x1a, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05,
- 0x72, 0x03, 0xb0, 0x01, 0x01, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x12, 0x38, 0x0a, 0x03, 0x6b,
- 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63,
- 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4b, 0x61,
- 0x73, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x48, 0x00,
- 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x44, 0x0a, 0x07, 0x6e, 0x65, 0x77, 0x5f, 0x6b, 0x65, 0x79,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
- 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x6f, 0x74, 0x61,
- 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4e, 0x65, 0x77,
- 0x4b, 0x65, 0x79, 0x52, 0x06, 0x6e, 0x65, 0x77, 0x4b, 0x65, 0x79, 0x1a, 0xcf, 0x04, 0x0a, 0x06,
- 0x4e, 0x65, 0x77, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x06, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52,
- 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x9d, 0x01, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72,
- 0x69, 0x74, 0x68, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c,
- 0x69, 0x63, 0x79, 0x2e, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x42, 0x6c, 0xba,
- 0x48, 0x69, 0xba, 0x01, 0x66, 0x0a, 0x15, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72,
- 0x69, 0x74, 0x68, 0x6d, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x12, 0x34, 0x54, 0x68,
- 0x65, 0x20, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x20,
- 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
- 0x68, 0x65, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65,
- 0x73, 0x2e, 0x1a, 0x17, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x5b, 0x31, 0x2c, 0x20,
- 0x32, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x35, 0x5d, 0x52, 0x09, 0x61, 0x6c, 0x67,
+ 0x10, 0x01, 0x48, 0x00, 0x52, 0x07, 0x6b, 0x61, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a,
+ 0x07, 0x6b, 0x61, 0x73, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a,
+ 0xba, 0x48, 0x07, 0x72, 0x05, 0x10, 0x01, 0x88, 0x01, 0x01, 0x48, 0x00, 0x52, 0x06, 0x6b, 0x61,
+ 0x73, 0x55, 0x72, 0x69, 0x12, 0x1b, 0x0a, 0x06, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x18, 0x08,
+ 0x20, 0x01, 0x28, 0x08, 0x48, 0x01, 0x52, 0x06, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x88, 0x01,
+ 0x01, 0x12, 0x33, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,
+ 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50,
+ 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69,
+ 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0c, 0x0a, 0x0a, 0x6b, 0x61, 0x73, 0x5f, 0x66, 0x69,
+ 0x6c, 0x74, 0x65, 0x72, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x22,
+ 0x73, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x08, 0x6b, 0x61, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18,
+ 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b,
+ 0x61, 0x73, 0x4b, 0x65, 0x79, 0x52, 0x07, 0x6b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x34,
+ 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x61, 0x67, 0x65,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x86, 0x03, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b,
+ 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52,
+ 0x02, 0x69, 0x64, 0x12, 0x33, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18,
+ 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d,
+ 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x08,
+ 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x54, 0x0a, 0x18, 0x6d, 0x65, 0x74, 0x61,
+ 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x62, 0x65, 0x68, 0x61,
+ 0x76, 0x69, 0x6f, 0x72, 0x18, 0x65, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x6d,
+ 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61,
+ 0x74, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x16, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x3a, 0xcc,
+ 0x01, 0xba, 0x48, 0xc8, 0x01, 0x1a, 0xc5, 0x01, 0x0a, 0x18, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
+ 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69,
+ 0x6f, 0x72, 0x12, 0x52, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, 0x75, 0x70, 0x64,
+ 0x61, 0x74, 0x65, 0x20, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x20, 0x6d, 0x75, 0x73,
+ 0x74, 0x20, 0x62, 0x65, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x41, 0x50, 0x50, 0x45,
+ 0x4e, 0x44, 0x20, 0x6f, 0x72, 0x20, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x2c, 0x20, 0x77,
+ 0x68, 0x65, 0x6e, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65, 0x74,
+ 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x1a, 0x55, 0x28, 0x28, 0x21, 0x68, 0x61, 0x73, 0x28, 0x74,
+ 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x29, 0x29, 0x20, 0x7c,
+ 0x7c, 0x20, 0x28, 0x68, 0x61, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x65, 0x74, 0x61,
+ 0x64, 0x61, 0x74, 0x61, 0x29, 0x20, 0x26, 0x26, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x65,
+ 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x62, 0x65,
+ 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x29, 0x29, 0x22, 0x3c, 0x0a,
+ 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x12, 0x27, 0x0a, 0x07, 0x6b, 0x61, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4b, 0x61, 0x73,
+ 0x4b, 0x65, 0x79, 0x52, 0x06, 0x6b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x22, 0xa4, 0x01, 0x0a, 0x10,
+ 0x4b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72,
+ 0x12, 0x21, 0x0a, 0x06, 0x6b, 0x61, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x48, 0x00, 0x52, 0x05, 0x6b, 0x61,
+ 0x73, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61,
+ 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42,
+ 0x0a, 0xba, 0x48, 0x07, 0x72, 0x05, 0x10, 0x01, 0x88, 0x01, 0x01, 0x48, 0x00, 0x52, 0x03, 0x75,
+ 0x72, 0x69, 0x12, 0x19, 0x0a, 0x03, 0x6b, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42,
+ 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x03, 0x6b, 0x69, 0x64, 0x42, 0x13, 0x0a,
+ 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x05, 0xba, 0x48, 0x02,
+ 0x08, 0x01, 0x22, 0xed, 0x0e, 0x0a, 0x10, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x48, 0x00, 0x52,
+ 0x02, 0x69, 0x64, 0x12, 0x38, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x24, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67,
+ 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x4b, 0x61, 0x73, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x65, 0x6e,
+ 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x48, 0x00, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x44, 0x0a,
+ 0x07, 0x6e, 0x65, 0x77, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b,
+ 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x6b, 0x61, 0x73, 0x72, 0x65, 0x67, 0x69, 0x73,
+ 0x74, 0x72, 0x79, 0x2e, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4e, 0x65, 0x77, 0x4b, 0x65, 0x79, 0x52, 0x06, 0x6e, 0x65, 0x77,
+ 0x4b, 0x65, 0x79, 0x1a, 0xd7, 0x04, 0x0a, 0x06, 0x4e, 0x65, 0x77, 0x4b, 0x65, 0x79, 0x12, 0x1e,
+ 0x0a, 0x06, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07,
+ 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64, 0x12, 0xa5,
+ 0x01, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x6c, 0x67, 0x6f,
+ 0x72, 0x69, 0x74, 0x68, 0x6d, 0x42, 0x74, 0xba, 0x48, 0x71, 0xba, 0x01, 0x6e, 0x0a, 0x15, 0x6b,
+ 0x65, 0x79, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x5f, 0x64, 0x65, 0x66,
+ 0x69, 0x6e, 0x65, 0x64, 0x12, 0x34, 0x54, 0x68, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x6c,
+ 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20,
+ 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e,
+ 0x65, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x1a, 0x1f, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x69, 0x6e, 0x20, 0x5b, 0x31, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x34, 0x2c,
+ 0x20, 0x35, 0x2c, 0x20, 0x32, 0x30, 0x2c, 0x20, 0x32, 0x31, 0x5d, 0x52, 0x09, 0x61, 0x6c, 0x67,
0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x9e, 0x01, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6d,
0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x70, 0x6f, 0x6c, 0x69,
0x63, 0x79, 0x2e, 0x4b, 0x65, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x42, 0x72, 0xba, 0x48, 0x6f, 0xba,
diff --git a/protocol/go/policy/objects.pb.go b/protocol/go/policy/objects.pb.go
index d2c0921c8b..6efbf9b0f1 100644
--- a/protocol/go/policy/objects.pb.go
+++ b/protocol/go/policy/objects.pb.go
@@ -243,17 +243,23 @@ const (
KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1 KasPublicKeyAlgEnum = 5
KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1 KasPublicKeyAlgEnum = 6
KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1 KasPublicKeyAlgEnum = 7
+ KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768 KasPublicKeyAlgEnum = 20
+ KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024 KasPublicKeyAlgEnum = 21
+ KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING KasPublicKeyAlgEnum = 30
)
// Enum value maps for KasPublicKeyAlgEnum.
var (
KasPublicKeyAlgEnum_name = map[int32]string{
- 0: "KAS_PUBLIC_KEY_ALG_ENUM_UNSPECIFIED",
- 1: "KAS_PUBLIC_KEY_ALG_ENUM_RSA_2048",
- 2: "KAS_PUBLIC_KEY_ALG_ENUM_RSA_4096",
- 5: "KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1",
- 6: "KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1",
- 7: "KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1",
+ 0: "KAS_PUBLIC_KEY_ALG_ENUM_UNSPECIFIED",
+ 1: "KAS_PUBLIC_KEY_ALG_ENUM_RSA_2048",
+ 2: "KAS_PUBLIC_KEY_ALG_ENUM_RSA_4096",
+ 5: "KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1",
+ 6: "KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1",
+ 7: "KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1",
+ 20: "KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768",
+ 21: "KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024",
+ 30: "KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING",
}
KasPublicKeyAlgEnum_value = map[string]int32{
"KAS_PUBLIC_KEY_ALG_ENUM_UNSPECIFIED": 0,
@@ -262,6 +268,9 @@ var (
"KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1": 5,
"KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1": 6,
"KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1": 7,
+ "KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768": 20,
+ "KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024": 21,
+ "KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING": 30,
}
)
@@ -296,31 +305,40 @@ func (KasPublicKeyAlgEnum) EnumDescriptor() ([]byte, []int) {
type Algorithm int32
const (
- Algorithm_ALGORITHM_UNSPECIFIED Algorithm = 0
- Algorithm_ALGORITHM_RSA_2048 Algorithm = 1
- Algorithm_ALGORITHM_RSA_4096 Algorithm = 2
- Algorithm_ALGORITHM_EC_P256 Algorithm = 3
- Algorithm_ALGORITHM_EC_P384 Algorithm = 4
- Algorithm_ALGORITHM_EC_P521 Algorithm = 5
+ Algorithm_ALGORITHM_UNSPECIFIED Algorithm = 0
+ Algorithm_ALGORITHM_RSA_2048 Algorithm = 1
+ Algorithm_ALGORITHM_RSA_4096 Algorithm = 2
+ Algorithm_ALGORITHM_EC_P256 Algorithm = 3
+ Algorithm_ALGORITHM_EC_P384 Algorithm = 4
+ Algorithm_ALGORITHM_EC_P521 Algorithm = 5
+ Algorithm_ALGORITHM_MLKEM_768 Algorithm = 20
+ Algorithm_ALGORITHM_MLKEM_1024 Algorithm = 21
+ Algorithm_ALGORITHM_HYBRID_XWING Algorithm = 30
)
// Enum value maps for Algorithm.
var (
Algorithm_name = map[int32]string{
- 0: "ALGORITHM_UNSPECIFIED",
- 1: "ALGORITHM_RSA_2048",
- 2: "ALGORITHM_RSA_4096",
- 3: "ALGORITHM_EC_P256",
- 4: "ALGORITHM_EC_P384",
- 5: "ALGORITHM_EC_P521",
+ 0: "ALGORITHM_UNSPECIFIED",
+ 1: "ALGORITHM_RSA_2048",
+ 2: "ALGORITHM_RSA_4096",
+ 3: "ALGORITHM_EC_P256",
+ 4: "ALGORITHM_EC_P384",
+ 5: "ALGORITHM_EC_P521",
+ 20: "ALGORITHM_MLKEM_768",
+ 21: "ALGORITHM_MLKEM_1024",
+ 30: "ALGORITHM_HYBRID_XWING",
}
Algorithm_value = map[string]int32{
- "ALGORITHM_UNSPECIFIED": 0,
- "ALGORITHM_RSA_2048": 1,
- "ALGORITHM_RSA_4096": 2,
- "ALGORITHM_EC_P256": 3,
- "ALGORITHM_EC_P384": 4,
- "ALGORITHM_EC_P521": 5,
+ "ALGORITHM_UNSPECIFIED": 0,
+ "ALGORITHM_RSA_2048": 1,
+ "ALGORITHM_RSA_4096": 2,
+ "ALGORITHM_EC_P256": 3,
+ "ALGORITHM_EC_P384": 4,
+ "ALGORITHM_EC_P521": 5,
+ "ALGORITHM_MLKEM_768": 20,
+ "ALGORITHM_MLKEM_1024": 21,
+ "ALGORITHM_HYBRID_XWING": 30,
}
)
@@ -3697,7 +3715,7 @@ var file_policy_objects_proto_rawDesc = []byte{
0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x45,
0x52, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45,
0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x10, 0x02,
- 0x2a, 0x88, 0x02, 0x0a, 0x13, 0x4b, 0x61, 0x73, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65,
+ 0x2a, 0x81, 0x03, 0x0a, 0x13, 0x4b, 0x61, 0x73, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65,
0x79, 0x41, 0x6c, 0x67, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x27, 0x0a, 0x23, 0x4b, 0x41, 0x53, 0x5f,
0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x41, 0x4c, 0x47, 0x5f, 0x45,
0x4e, 0x55, 0x4d, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
@@ -3713,41 +3731,53 @@ var file_policy_objects_proto_rawDesc = []byte{
0x55, 0x4d, 0x5f, 0x45, 0x43, 0x5f, 0x53, 0x45, 0x43, 0x50, 0x33, 0x38, 0x34, 0x52, 0x31, 0x10,
0x06, 0x12, 0x28, 0x0a, 0x24, 0x4b, 0x41, 0x53, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f,
0x4b, 0x45, 0x59, 0x5f, 0x41, 0x4c, 0x47, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x45, 0x43, 0x5f,
- 0x53, 0x45, 0x43, 0x50, 0x35, 0x32, 0x31, 0x52, 0x31, 0x10, 0x07, 0x2a, 0x9b, 0x01, 0x0a, 0x09,
- 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x4c, 0x47,
- 0x4f, 0x52, 0x49, 0x54, 0x48, 0x4d, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
- 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x41, 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54, 0x48,
- 0x4d, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x32, 0x30, 0x34, 0x38, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12,
- 0x41, 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54, 0x48, 0x4d, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x34, 0x30,
- 0x39, 0x36, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x41, 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54, 0x48,
- 0x4d, 0x5f, 0x45, 0x43, 0x5f, 0x50, 0x32, 0x35, 0x36, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x41,
- 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54, 0x48, 0x4d, 0x5f, 0x45, 0x43, 0x5f, 0x50, 0x33, 0x38, 0x34,
- 0x10, 0x04, 0x12, 0x15, 0x0a, 0x11, 0x41, 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54, 0x48, 0x4d, 0x5f,
- 0x45, 0x43, 0x5f, 0x50, 0x35, 0x32, 0x31, 0x10, 0x05, 0x2a, 0x56, 0x0a, 0x09, 0x4b, 0x65, 0x79,
- 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x16, 0x4b, 0x45, 0x59, 0x5f, 0x53, 0x54,
- 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44,
- 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x4b, 0x45, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53,
- 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x4b, 0x45, 0x59,
- 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, 0x4f, 0x54, 0x41, 0x54, 0x45, 0x44, 0x10,
- 0x02, 0x2a, 0x94, 0x01, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a,
- 0x14, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43,
- 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x4b, 0x45, 0x59, 0x5f, 0x4d,
- 0x4f, 0x44, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x5f,
- 0x4b, 0x45, 0x59, 0x10, 0x01, 0x12, 0x1e, 0x0a, 0x1a, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44,
- 0x45, 0x5f, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x44, 0x45, 0x52, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x5f,
- 0x4b, 0x45, 0x59, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44,
- 0x45, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x10, 0x03, 0x12, 0x1c, 0x0a, 0x18, 0x4b, 0x45,
- 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x4b, 0x45,
- 0x59, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x04, 0x42, 0x82, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d,
- 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x0c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73,
- 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
- 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74,
- 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f,
- 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0xa2, 0x02, 0x03, 0x50, 0x58, 0x58, 0xaa, 0x02, 0x06,
- 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0xca, 0x02, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0xe2,
- 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61,
- 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x62, 0x06, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x33,
+ 0x53, 0x45, 0x43, 0x50, 0x35, 0x32, 0x31, 0x52, 0x31, 0x10, 0x07, 0x12, 0x25, 0x0a, 0x21, 0x4b,
+ 0x41, 0x53, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x41, 0x4c,
+ 0x47, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x4d, 0x4c, 0x4b, 0x45, 0x4d, 0x5f, 0x37, 0x36, 0x38,
+ 0x10, 0x14, 0x12, 0x26, 0x0a, 0x22, 0x4b, 0x41, 0x53, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43,
+ 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x41, 0x4c, 0x47, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x4d, 0x4c,
+ 0x4b, 0x45, 0x4d, 0x5f, 0x31, 0x30, 0x32, 0x34, 0x10, 0x15, 0x12, 0x28, 0x0a, 0x24, 0x4b, 0x41,
+ 0x53, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x41, 0x4c, 0x47,
+ 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x48, 0x59, 0x42, 0x52, 0x49, 0x44, 0x5f, 0x58, 0x57, 0x49,
+ 0x4e, 0x47, 0x10, 0x1e, 0x2a, 0xea, 0x01, 0x0a, 0x09, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74,
+ 0x68, 0x6d, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54, 0x48, 0x4d, 0x5f,
+ 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a,
+ 0x12, 0x41, 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54, 0x48, 0x4d, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x32,
+ 0x30, 0x34, 0x38, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x41, 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54,
+ 0x48, 0x4d, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x34, 0x30, 0x39, 0x36, 0x10, 0x02, 0x12, 0x15, 0x0a,
+ 0x11, 0x41, 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54, 0x48, 0x4d, 0x5f, 0x45, 0x43, 0x5f, 0x50, 0x32,
+ 0x35, 0x36, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x41, 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54, 0x48,
+ 0x4d, 0x5f, 0x45, 0x43, 0x5f, 0x50, 0x33, 0x38, 0x34, 0x10, 0x04, 0x12, 0x15, 0x0a, 0x11, 0x41,
+ 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54, 0x48, 0x4d, 0x5f, 0x45, 0x43, 0x5f, 0x50, 0x35, 0x32, 0x31,
+ 0x10, 0x05, 0x12, 0x17, 0x0a, 0x13, 0x41, 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54, 0x48, 0x4d, 0x5f,
+ 0x4d, 0x4c, 0x4b, 0x45, 0x4d, 0x5f, 0x37, 0x36, 0x38, 0x10, 0x14, 0x12, 0x18, 0x0a, 0x14, 0x41,
+ 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54, 0x48, 0x4d, 0x5f, 0x4d, 0x4c, 0x4b, 0x45, 0x4d, 0x5f, 0x31,
+ 0x30, 0x32, 0x34, 0x10, 0x15, 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54,
+ 0x48, 0x4d, 0x5f, 0x48, 0x59, 0x42, 0x52, 0x49, 0x44, 0x5f, 0x58, 0x57, 0x49, 0x4e, 0x47, 0x10,
+ 0x1e, 0x2a, 0x56, 0x0a, 0x09, 0x4b, 0x65, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a,
+ 0x0a, 0x16, 0x4b, 0x45, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53,
+ 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x4b, 0x45,
+ 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10,
+ 0x01, 0x12, 0x16, 0x0a, 0x12, 0x4b, 0x45, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f,
+ 0x52, 0x4f, 0x54, 0x41, 0x54, 0x45, 0x44, 0x10, 0x02, 0x2a, 0x94, 0x01, 0x0a, 0x07, 0x4b, 0x65,
+ 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44,
+ 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12,
+ 0x1c, 0x0a, 0x18, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x46,
+ 0x49, 0x47, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x01, 0x12, 0x1e, 0x0a,
+ 0x1a, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x44,
+ 0x45, 0x52, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x02, 0x12, 0x13, 0x0a,
+ 0x0f, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45,
+ 0x10, 0x03, 0x12, 0x1c, 0x0a, 0x18, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x50,
+ 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x04,
+ 0x42, 0x82, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42,
+ 0x0c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a,
+ 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e,
+ 0x74, 0x64, 0x66, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0xa2,
+ 0x02, 0x03, 0x50, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0xca, 0x02,
+ 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0xe2, 0x02, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79,
+ 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x06, 0x50,
+ 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
diff --git a/sdk/basekey.go b/sdk/basekey.go
index 5f3cc12004..ea091914d9 100644
--- a/sdk/basekey.go
+++ b/sdk/basekey.go
@@ -33,6 +33,12 @@ func getKasKeyAlg(alg string) policy.Algorithm {
return policy.Algorithm_ALGORITHM_EC_P384
case string(ocrypto.EC521Key):
return policy.Algorithm_ALGORITHM_EC_P521
+ case string(ocrypto.MLKEM768Key):
+ return policy.Algorithm_ALGORITHM_MLKEM_768
+ case string(ocrypto.MLKEM1024Key):
+ return policy.Algorithm_ALGORITHM_MLKEM_1024
+ case string(ocrypto.HybridXWingKey):
+ return policy.Algorithm_ALGORITHM_HYBRID_XWING
default:
return policy.Algorithm_ALGORITHM_UNSPECIFIED
}
@@ -51,6 +57,12 @@ func formatAlg(alg policy.Algorithm) (string, error) {
return string(ocrypto.EC384Key), nil
case policy.Algorithm_ALGORITHM_EC_P521:
return string(ocrypto.EC521Key), nil
+ case policy.Algorithm_ALGORITHM_MLKEM_768:
+ return string(ocrypto.MLKEM768Key), nil
+ case policy.Algorithm_ALGORITHM_MLKEM_1024:
+ return string(ocrypto.MLKEM1024Key), nil
+ case policy.Algorithm_ALGORITHM_HYBRID_XWING:
+ return string(ocrypto.HybridXWingKey), nil
case policy.Algorithm_ALGORITHM_UNSPECIFIED:
fallthrough
default:
diff --git a/sdk/codegen/runner/generate.go b/sdk/codegen/runner/generate.go
index 211cedfdc4..0a8a88e197 100644
--- a/sdk/codegen/runner/generate.go
+++ b/sdk/codegen/runner/generate.go
@@ -177,12 +177,11 @@ func New%s%s%sConnectWrapper(httpClient connect.HTTPClient, baseURL string, opts
func generateInterfaceType(interfaceName string, methods []string, packageName, prefix, suffix string) string {
// Generate the interface type definition
var builder strings.Builder
- builder.WriteString(fmt.Sprintf(`
+ fmt.Fprintf(&builder, `
type %s%s%s interface {
-`, prefix, interfaceName, suffix))
+`, prefix, interfaceName, suffix)
for _, method := range methods {
- builder.WriteString(fmt.Sprintf(` %s(ctx context.Context, req *%s.%sRequest) (*%s.%sResponse, error)
-`, method, packageName, method, packageName, method))
+ fmt.Fprintf(&builder, " %s(ctx context.Context, req *%s.%sRequest) (*%s.%sResponse, error)\n", method, packageName, method, packageName, method)
}
builder.WriteString("}\n")
return builder.String()
diff --git a/sdk/experimental/tdf/keysplit/attributes.go b/sdk/experimental/tdf/keysplit/attributes.go
index e12d838e97..31ec8b2f4a 100644
--- a/sdk/experimental/tdf/keysplit/attributes.go
+++ b/sdk/experimental/tdf/keysplit/attributes.go
@@ -199,6 +199,12 @@ func formatAlgorithm(alg policy.Algorithm) string {
return "rsa:2048"
case policy.Algorithm_ALGORITHM_RSA_4096:
return "rsa:4096"
+ case policy.Algorithm_ALGORITHM_MLKEM_768:
+ return "mlkem:768"
+ case policy.Algorithm_ALGORITHM_MLKEM_1024:
+ return "mlkem:1024"
+ case policy.Algorithm_ALGORITHM_HYBRID_XWING:
+ return "hpqt:xwing"
default:
return unknownAlgorithm
}
@@ -217,6 +223,12 @@ func convertAlgEnum2Simple(a policy.KasPublicKeyAlgEnum) policy.Algorithm {
return policy.Algorithm_ALGORITHM_RSA_2048
case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_RSA_4096:
return policy.Algorithm_ALGORITHM_RSA_4096
+ case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768:
+ return policy.Algorithm_ALGORITHM_MLKEM_768
+ case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024:
+ return policy.Algorithm_ALGORITHM_MLKEM_1024
+ case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING:
+ return policy.Algorithm_ALGORITHM_HYBRID_XWING
case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_UNSPECIFIED:
return policy.Algorithm_ALGORITHM_UNSPECIFIED
default:
diff --git a/sdk/granter.go b/sdk/granter.go
index 8275a04f42..e309f648bd 100644
--- a/sdk/granter.go
+++ b/sdk/granter.go
@@ -286,6 +286,12 @@ func convertAlgEnum2Simple(a policy.KasPublicKeyAlgEnum) policy.Algorithm {
return policy.Algorithm_ALGORITHM_RSA_2048
case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_RSA_4096:
return policy.Algorithm_ALGORITHM_RSA_4096
+ case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768:
+ return policy.Algorithm_ALGORITHM_MLKEM_768
+ case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024:
+ return policy.Algorithm_ALGORITHM_MLKEM_1024
+ case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING:
+ return policy.Algorithm_ALGORITHM_HYBRID_XWING
case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_UNSPECIFIED:
return policy.Algorithm_ALGORITHM_UNSPECIFIED
default:
@@ -306,6 +312,12 @@ func convertStringToAlgorithm(alg string) policy.Algorithm {
return policy.Algorithm_ALGORITHM_RSA_2048
case ocrypto.RSA4096Key:
return policy.Algorithm_ALGORITHM_RSA_4096
+ case ocrypto.MLKEM768Key:
+ return policy.Algorithm_ALGORITHM_MLKEM_768
+ case ocrypto.MLKEM1024Key:
+ return policy.Algorithm_ALGORITHM_MLKEM_1024
+ case ocrypto.HybridXWingKey:
+ return policy.Algorithm_ALGORITHM_HYBRID_XWING
default:
return policy.Algorithm_ALGORITHM_UNSPECIFIED
}
@@ -490,6 +502,12 @@ func algProto2String(e policy.KasPublicKeyAlgEnum) string {
return string(ocrypto.RSA2048Key)
case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_RSA_4096:
return string(ocrypto.RSA4096Key)
+ case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768:
+ return string(ocrypto.MLKEM768Key)
+ case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024:
+ return string(ocrypto.MLKEM1024Key)
+ case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING:
+ return string(ocrypto.HybridXWingKey)
case policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_UNSPECIFIED:
return ""
}
@@ -508,6 +526,12 @@ func algProto2OcryptoKeyType(e policy.Algorithm) ocrypto.KeyType {
return ocrypto.RSA2048Key
case policy.Algorithm_ALGORITHM_RSA_4096:
return ocrypto.RSA4096Key
+ case policy.Algorithm_ALGORITHM_MLKEM_768:
+ return ocrypto.MLKEM768Key
+ case policy.Algorithm_ALGORITHM_MLKEM_1024:
+ return ocrypto.MLKEM1024Key
+ case policy.Algorithm_ALGORITHM_HYBRID_XWING:
+ return ocrypto.HybridXWingKey
case policy.Algorithm_ALGORITHM_UNSPECIFIED:
return ocrypto.KeyType("")
default:
diff --git a/sdk/schema/manifest.schema.json b/sdk/schema/manifest.schema.json
index 6488623fa2..983747a394 100644
--- a/sdk/schema/manifest.schema.json
+++ b/sdk/schema/manifest.schema.json
@@ -52,7 +52,7 @@
"type": {
"description": "The type of key access object.",
"type": "string",
- "enum": ["ec-wrapped", "remote", "wrapped"]
+ "enum": ["ec-wrapped", "remote", "wrapped", "mlkem-wrapped", "hybrid"]
},
"url": {
"description": "A fully qualified URL pointing to a key access service responsible for managing access to the encryption keys.",
diff --git a/sdk/tdf.go b/sdk/tdf.go
index db22208b5f..82b82e2f58 100644
--- a/sdk/tdf.go
+++ b/sdk/tdf.go
@@ -43,6 +43,8 @@ const (
kKeySize = 32
kWrapped = "wrapped"
kECWrapped = "ec-wrapped"
+ kMLKEMWrapped = "mlkem-wrapped"
+ kHybridWrapped = "hybrid"
kKasProtocol = "kas"
kSplitKeyType = "split"
kGCMCipherAlgorithm = "AES-256-GCM"
@@ -674,7 +676,8 @@ func createKeyAccess(kasInfo KASInfo, symKey []byte, policyBinding PolicyBinding
}
ktype := ocrypto.KeyType(kasInfo.Algorithm)
- if ocrypto.IsECKeyType(ktype) {
+ switch {
+ case ocrypto.IsECKeyType(ktype):
mode, err := ocrypto.ECKeyTypeToMode(ktype)
if err != nil {
return KeyAccess{}, err
@@ -686,7 +689,23 @@ func createKeyAccess(kasInfo KASInfo, symKey []byte, policyBinding PolicyBinding
keyAccess.KeyType = kECWrapped
keyAccess.WrappedKey = wrappedKeyInfo.wrappedKey
keyAccess.EphemeralPublicKey = wrappedKeyInfo.publicKey
- } else {
+ case ktype == ocrypto.MLKEM768Key, ktype == ocrypto.MLKEM1024Key:
+ wrappedKey, encapsulatedKey, err := generateWrapKeyWithMLKEM(kasInfo.PublicKey, symKey)
+ if err != nil {
+ return KeyAccess{}, err
+ }
+ keyAccess.KeyType = kMLKEMWrapped
+ keyAccess.WrappedKey = wrappedKey
+ keyAccess.EphemeralPublicKey = encapsulatedKey
+ case ktype == ocrypto.HybridXWingKey:
+ wrappedKey, encapsulatedKey, err := generateWrapKeyWithHybrid(kasInfo.PublicKey, symKey)
+ if err != nil {
+ return KeyAccess{}, err
+ }
+ keyAccess.KeyType = kHybridWrapped
+ keyAccess.WrappedKey = wrappedKey
+ keyAccess.EphemeralPublicKey = encapsulatedKey
+ default:
wrappedKey, err := generateWrapKeyWithRSA(kasInfo.PublicKey, symKey)
if err != nil {
return KeyAccess{}, err
@@ -761,6 +780,44 @@ func generateWrapKeyWithRSA(publicKey string, symKey []byte) (string, error) {
return string(ocrypto.Base64Encode(wrappedKey)), nil
}
+func generateWrapKeyWithMLKEM(publicKey string, symKey []byte) (string, string, error) {
+ publicKeyEncryptor, err := ocrypto.FromPublicPEM(publicKey)
+ if err != nil {
+ return "", "", fmt.Errorf("generateWrapKeyWithMLKEM: ocrypto.FromPublicPEM failed:%w", err)
+ }
+
+ wrappedKey, err := publicKeyEncryptor.Encrypt(symKey)
+ if err != nil {
+ return "", "", fmt.Errorf("generateWrapKeyWithMLKEM: encrypt failed:%w", err)
+ }
+
+ encapsulatedKey := publicKeyEncryptor.EphemeralKey()
+ if len(encapsulatedKey) == 0 {
+ return "", "", errors.New("generateWrapKeyWithMLKEM: encapsulated key missing")
+ }
+
+ return string(ocrypto.Base64Encode(wrappedKey)), string(ocrypto.Base64Encode(encapsulatedKey)), nil
+}
+
+func generateWrapKeyWithHybrid(publicKey string, symKey []byte) (string, string, error) {
+ publicKeyEncryptor, err := ocrypto.FromPublicPEM(publicKey)
+ if err != nil {
+ return "", "", fmt.Errorf("generateWrapKeyWithHybrid: ocrypto.FromPublicPEM failed:%w", err)
+ }
+
+ wrappedKey, err := publicKeyEncryptor.Encrypt(symKey)
+ if err != nil {
+ return "", "", fmt.Errorf("generateWrapKeyWithHybrid: encrypt failed:%w", err)
+ }
+
+ encapsulatedKey := publicKeyEncryptor.EphemeralKey()
+ if len(encapsulatedKey) == 0 {
+ return "", "", errors.New("generateWrapKeyWithHybrid: encapsulated key missing")
+ }
+
+ return string(ocrypto.Base64Encode(wrappedKey)), string(ocrypto.Base64Encode(encapsulatedKey)), nil
+}
+
// create policy object
func createPolicyObject(attributes []AttributeValueFQN) (PolicyObject, error) {
uuidObj, err := uuid.NewUUID()
diff --git a/service/internal/security/basic_manager.go b/service/internal/security/basic_manager.go
index 6197e50eb3..2080b8ccda 100644
--- a/service/internal/security/basic_manager.go
+++ b/service/internal/security/basic_manager.go
@@ -97,6 +97,26 @@ func (b *BasicManager) Decrypt(ctx context.Context, keyDetails trust.KeyDetails,
return nil, fmt.Errorf("failed to create protected key: %w", err)
}
return protectedKey, nil
+ case ocrypto.MLKEM768Key, ocrypto.MLKEM1024Key:
+ plaintext, err := decrypter.DecryptWithEphemeralKey(ciphertext, ephemeralPublicKey)
+ if err != nil {
+ return nil, fmt.Errorf("failed to decrypt with ML-KEM: %w", err)
+ }
+ protectedKey, err := ocrypto.NewAESProtectedKey(plaintext)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create protected key: %w", err)
+ }
+ return protectedKey, nil
+ case ocrypto.HybridXWingKey:
+ plaintext, err := decrypter.DecryptWithEphemeralKey(ciphertext, ephemeralPublicKey)
+ if err != nil {
+ return nil, fmt.Errorf("failed to decrypt with Hybrid X-Wing: %w", err)
+ }
+ protectedKey, err := ocrypto.NewAESProtectedKey(plaintext)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create protected key: %w", err)
+ }
+ return protectedKey, nil
}
return nil, fmt.Errorf("unsupported algorithm: %s", keyDetails.Algorithm())
diff --git a/service/internal/security/crypto_provider.go b/service/internal/security/crypto_provider.go
index 24f0f3c2ea..5c32948667 100644
--- a/service/internal/security/crypto_provider.go
+++ b/service/internal/security/crypto_provider.go
@@ -11,4 +11,11 @@ const (
// Used for encryption with RSA of the KAO
AlgorithmRSA2048 = "rsa:2048"
AlgorithmRSA4096 = "rsa:4096"
+
+ // Used for encryption with ML-KEM of the KAO
+ AlgorithmMLKEM768 = "mlkem:768"
+ AlgorithmMLKEM1024 = "mlkem:1024"
+
+ // Used for encryption with Hybrid X-Wing of the KAO
+ AlgorithmHybridXWing = "hpqt:xwing"
)
diff --git a/service/internal/security/in_process_provider.go b/service/internal/security/in_process_provider.go
index 67c86487aa..0ac95ad5f0 100644
--- a/service/internal/security/in_process_provider.go
+++ b/service/internal/security/in_process_provider.go
@@ -2,7 +2,6 @@ package security
import (
"context"
- "crypto"
"crypto/elliptic"
"crypto/x509"
"encoding/pem"
@@ -80,11 +79,7 @@ func (k *KeyDetailsAdapter) ExportPublicKey(_ context.Context, format trust.KeyT
return jwkKey, nil
case trust.KeyTypePKCS8:
- // Try to get the key as an RSA key first
- if rsaKey, err := k.cryptoProvider.RSAPublicKey(kid); err == nil {
- return rsaKey, nil
- }
- return k.cryptoProvider.ECPublicKey(kid)
+ return k.cryptoProvider.PublicKey(kid)
default:
return "", ErrCertNotFound
}
@@ -92,8 +87,11 @@ func (k *KeyDetailsAdapter) ExportPublicKey(_ context.Context, format trust.KeyT
func (k *KeyDetailsAdapter) ExportCertificate(_ context.Context) (string, error) {
kid := string(k.id)
- if k.algorithm == AlgorithmECP256R1 {
+ switch k.algorithm {
+ case AlgorithmECP256R1, AlgorithmECP384R1, AlgorithmECP521R1:
return k.cryptoProvider.ECCertificate(kid)
+ case ocrypto.RSA2048Key, ocrypto.RSA4096Key, ocrypto.MLKEM768Key, ocrypto.MLKEM1024Key, ocrypto.HybridXWingKey:
+ return "", errors.New("certificates only available for EC keys")
}
return "", errors.New("certificates only available for EC keys")
}
@@ -170,31 +168,29 @@ func (a *InProcessProvider) FindKeyByAlgorithm(_ context.Context, algorithm stri
// FindKeyByID finds a key by ID
func (a *InProcessProvider) FindKeyByID(_ context.Context, id trust.KeyIdentifier) (trust.KeyDetails, error) {
- // Try to determine the algorithm by checking if the key works with known algorithms
- for _, alg := range []string{AlgorithmECP256R1, AlgorithmRSA2048} {
- // This is a hack since the original provider doesn't have a way to check if a key exists
- switch alg {
- case AlgorithmECP256R1:
- if _, err := a.cryptoProvider.ECPublicKey(string(id)); err == nil {
- return &KeyDetailsAdapter{
- id: id,
- algorithm: ocrypto.KeyType(alg),
- legacy: a.legacyKeys[string(id)],
- cryptoProvider: a.cryptoProvider,
- }, nil
- }
- case AlgorithmRSA2048:
- if _, err := a.cryptoProvider.RSAPublicKey(string(id)); err == nil {
- return &KeyDetailsAdapter{
- id: id,
- algorithm: ocrypto.KeyType(alg),
- legacy: a.legacyKeys[string(id)],
- cryptoProvider: a.cryptoProvider,
- }, nil
- }
- }
+ key, ok := a.cryptoProvider.keysByID[string(id)]
+ if !ok {
+ return nil, ErrCertNotFound
+ }
+
+ switch key := key.(type) {
+ case StandardECCrypto:
+ return &KeyDetailsAdapter{
+ id: id,
+ algorithm: ocrypto.KeyType(key.Algorithm),
+ legacy: a.legacyKeys[string(id)],
+ cryptoProvider: a.cryptoProvider,
+ }, nil
+ case PrivateKeyCrypto:
+ return &KeyDetailsAdapter{
+ id: id,
+ algorithm: ocrypto.KeyType(key.Algorithm),
+ legacy: a.legacyKeys[string(id)],
+ cryptoProvider: a.cryptoProvider,
+ }, nil
+ default:
+ return nil, ErrCertNotFound
}
- return nil, ErrCertNotFound
}
// ListKeys lists all available keys
@@ -203,32 +199,36 @@ func (a *InProcessProvider) ListKeys(ctx context.Context) ([]trust.KeyDetails, e
}
func (a *InProcessProvider) ListKeysWith(ctx context.Context, opts trust.ListKeyOptions) ([]trust.KeyDetails, error) {
- // This is a limited implementation as CryptoProvider doesn't expose a list of all keys
var keys []trust.KeyDetails
- // Try to find keys for known algorithms
- for _, alg := range []string{AlgorithmRSA2048, AlgorithmECP256R1} {
- if kids, err := a.cryptoProvider.ListKIDsByAlgorithm(alg); err == nil && len(kids) > 0 {
- for _, kid := range kids {
- if opts.LegacyOnly && !a.legacyKeys[kid] {
- continue // Skip non-legacy keys if LegacyOnly is true
- }
- keys = append(keys, &KeyDetailsAdapter{
- id: trust.KeyIdentifier(kid),
- algorithm: ocrypto.KeyType(alg),
- cryptoProvider: a.cryptoProvider,
- legacy: a.legacyKeys[kid],
- })
- }
- } else if err != nil {
+ for kid, key := range a.cryptoProvider.keysByID {
+ if opts.LegacyOnly && !a.legacyKeys[kid] {
+ continue
+ }
+
+ var algorithm ocrypto.KeyType
+ switch key := key.(type) {
+ case StandardECCrypto:
+ algorithm = ocrypto.KeyType(key.Algorithm)
+ case PrivateKeyCrypto:
+ algorithm = ocrypto.KeyType(key.Algorithm)
+ default:
if a.logger != nil {
a.logger.WarnContext(ctx,
- "failed to list keys by algorithm",
- slog.String("algorithm", alg),
- slog.Any("error", err),
+ "failed to list key with unsupported type",
+ slog.String("kid", kid),
+ slog.Any("type", fmt.Sprintf("%T", key)),
)
}
+ continue
}
+
+ keys = append(keys, &KeyDetailsAdapter{
+ id: trust.KeyIdentifier(kid),
+ algorithm: algorithm,
+ cryptoProvider: a.cryptoProvider,
+ legacy: a.legacyKeys[kid],
+ })
}
return keys, nil
@@ -237,30 +237,25 @@ func (a *InProcessProvider) ListKeysWith(ctx context.Context, opts trust.ListKey
// Decrypt implements the unified decryption method for both RSA and EC
func (a *InProcessProvider) Decrypt(ctx context.Context, keyDetails trust.KeyDetails, ciphertext []byte, ephemeralPublicKey []byte) (ocrypto.ProtectedKey, error) {
kid := string(keyDetails.ID())
-
- var protectedKey ocrypto.ProtectedKey
- var err error
-
- // Try to determine the key type
- keyType, err := a.determineKeyType(ctx, kid)
- if err != nil {
- return nil, err
+ key, ok := a.cryptoProvider.keysByID[kid]
+ if !ok {
+ return nil, ErrCertNotFound
}
var rawKey []byte
- switch keyType {
- case AlgorithmRSA2048:
- if len(ephemeralPublicKey) > 0 {
- return nil, errors.New("ephemeral public key should not be provided for RSA decryption")
- }
- rawKey, err = a.cryptoProvider.RSADecrypt(crypto.SHA1, kid, "", ciphertext)
-
- case AlgorithmECP256R1:
+ var err error
+ switch key := key.(type) {
+ case StandardECCrypto:
if len(ephemeralPublicKey) == 0 {
return nil, errors.New("ephemeral public key is required for EC decryption")
}
- protectedKey, err = a.cryptoProvider.ECDecrypt(ctx, kid, ephemeralPublicKey, ciphertext)
-
+ protectedKey, err := a.cryptoProvider.ECDecrypt(ctx, kid, ephemeralPublicKey, ciphertext)
+ if err != nil {
+ return nil, err
+ }
+ return protectedKey, nil
+ case PrivateKeyCrypto:
+ rawKey, err = key.dec.DecryptWithEphemeralKey(ciphertext, ephemeralPublicKey)
default:
return nil, errors.New("unsupported key algorithm")
}
@@ -268,15 +263,7 @@ func (a *InProcessProvider) Decrypt(ctx context.Context, keyDetails trust.KeyDet
if err != nil {
return nil, err
}
-
- if protectedKey == nil {
- protectedKey, err = ocrypto.NewAESProtectedKey(rawKey)
- if err != nil {
- return nil, fmt.Errorf("failed to create protected key: %w", err)
- }
- }
-
- return protectedKey, nil
+ return ocrypto.NewAESProtectedKey(rawKey)
}
// DeriveKey computes an ECDH shared secret and derives an AES key via HKDF.
@@ -334,19 +321,3 @@ func (a *InProcessProvider) GenerateECSessionKey(_ context.Context, ephemeralPub
func (a *InProcessProvider) Close() {
a.cryptoProvider.Close()
}
-
-// determineKeyType tries to determine the algorithm of a key based on its ID
-// This is a helper method for the Decrypt method
-func (a *InProcessProvider) determineKeyType(_ context.Context, kid string) (string, error) {
- // First try RSA
- if _, err := a.cryptoProvider.RSAPublicKey(kid); err == nil {
- return AlgorithmRSA2048, nil
- }
-
- // Then try EC
- if _, err := a.cryptoProvider.ECPublicKey(kid); err == nil {
- return AlgorithmECP256R1, nil
- }
-
- return "", errors.New("could not determine key type")
-}
diff --git a/service/internal/security/standard_crypto.go b/service/internal/security/standard_crypto.go
index 6b86abdcbe..2c3805fbe3 100644
--- a/service/internal/security/standard_crypto.go
+++ b/service/internal/security/standard_crypto.go
@@ -52,10 +52,10 @@ type StandardKeyInfo struct {
PublicKeyPath string `mapstructure:"public_key_path" json:"public_key_path"`
}
-type StandardRSACrypto struct {
+type PrivateKeyCrypto struct {
KeyPairInfo
- asymDecryption ocrypto.AsymDecryption
- asymEncryption ocrypto.AsymEncryption
+ dec ocrypto.PrivateKeyDecryptor
+ enc ocrypto.PublicKeyEncryptor
}
type StandardECCrypto struct {
@@ -150,23 +150,19 @@ func loadKey(k KeyPairInfo) (any, error) {
ecPrivateKeyPem: string(privatePEM),
ecCertificatePEM: string(certPEM),
}, nil
- case AlgorithmRSA2048, AlgorithmRSA4096:
- asymDecryption, err := ocrypto.NewAsymDecryption(string(privatePEM))
+ case AlgorithmRSA2048, AlgorithmRSA4096, AlgorithmMLKEM768, AlgorithmMLKEM1024, AlgorithmHybridXWing:
+ decrypter, err := ocrypto.FromPrivatePEM(string(privatePEM))
if err != nil {
- return nil, fmt.Errorf("ocrypto.NewAsymDecryption failed: %w", err)
+ return nil, fmt.Errorf("ocrypto.FromPrivatePEM failed: %w", err)
}
publicKeyEncryptor, err := ocrypto.FromPublicPEM(string(certPEM))
if err != nil {
return nil, fmt.Errorf("ocrypto.FromPublicPEM failed: %w", err)
}
- asymEncryption, ok := publicKeyEncryptor.(*ocrypto.AsymEncryption)
- if !ok {
- return nil, fmt.Errorf("unexpected public key encryptor type: %T", publicKeyEncryptor)
- }
- return StandardRSACrypto{
- KeyPairInfo: k,
- asymDecryption: asymDecryption,
- asymEncryption: *asymEncryption,
+ return PrivateKeyCrypto{
+ KeyPairInfo: k,
+ dec: decrypter,
+ enc: publicKeyEncryptor,
}, nil
default:
return nil, errors.New("unsupported algorithm [" + k.Algorithm + "]")
@@ -199,25 +195,20 @@ func loadDeprecatedKeys(rsaKeys map[string]StandardKeyInfo, ecKeys map[string]St
if err != nil {
return nil, fmt.Errorf("failed to rsa public key file: %w", err)
}
-
publicKeyEncryptor, err := ocrypto.FromPublicPEM(string(publicPemData))
if err != nil {
return nil, fmt.Errorf("ocrypto.FromPublicPEM failed: %w", err)
}
- asymEncryption, ok := publicKeyEncryptor.(*ocrypto.AsymEncryption)
- if !ok {
- return nil, fmt.Errorf("unexpected public key encryptor type: %T", publicKeyEncryptor)
- }
- k := StandardRSACrypto{
+ k := PrivateKeyCrypto{
KeyPairInfo: KeyPairInfo{
Algorithm: AlgorithmRSA2048,
KID: id,
Private: kasInfo.PrivateKeyPath,
Certificate: kasInfo.PublicKeyPath,
},
- asymDecryption: asymDecryption,
- asymEncryption: *asymEncryption,
+ dec: asymDecryption,
+ enc: publicKeyEncryptor,
}
keysByAlg[AlgorithmRSA2048][id] = k
keysByID[id] = k
@@ -266,22 +257,26 @@ func (s StandardCrypto) FindKID(alg string) string {
return ""
}
-func (s StandardCrypto) RSAPublicKey(kid string) (string, error) {
+func (s StandardCrypto) PublicKey(kid string) (string, error) {
k, ok := s.keysByID[kid]
if !ok {
- return "", fmt.Errorf("no rsa key with id [%s]: %w", kid, ErrCertNotFound)
- }
- rsa, ok := k.(StandardRSACrypto)
- if !ok {
- return "", fmt.Errorf("key with id [%s] is not an RSA key: %w", kid, ErrCertNotFound)
+ return "", fmt.Errorf("no public key with id [%s]: %w", kid, ErrCertNotFound)
}
-
- pem, err := rsa.asymEncryption.PublicKeyInPemFormat()
- if err != nil {
- return "", fmt.Errorf("failed to retrieve rsa public key file: %w", err)
+ switch key := k.(type) {
+ case PrivateKeyCrypto:
+ publicKeyPEM, err := key.enc.PublicKeyInPemFormat()
+ if err != nil {
+ return "", fmt.Errorf("failed to retrieve public key file: %w", err)
+ }
+ return publicKeyPEM, nil
+ case StandardECCrypto:
+ if key.ecCertificatePEM != "" {
+ return key.ecCertificatePEM, nil
+ }
+ return s.ECPublicKey(kid)
+ default:
+ return "", fmt.Errorf("key with id [%s] does not expose a public key: %w", kid, ErrCertNotFound)
}
-
- return pem, nil
}
func (s StandardCrypto) ECCertificate(kid string) (string, error) {
@@ -334,12 +329,12 @@ func (s StandardCrypto) RSADecrypt(_ crypto.Hash, kid string, _ string, cipherte
if !ok {
return nil, ErrCertNotFound
}
- rsa, ok := k.(StandardRSACrypto)
+ rsa, ok := k.(PrivateKeyCrypto)
if !ok {
return nil, ErrCertNotFound
}
- data, err := rsa.asymDecryption.Decrypt(ciphertext)
+ data, err := rsa.dec.Decrypt(ciphertext)
if err != nil {
return nil, fmt.Errorf("error decrypting data: %w", err)
}
@@ -355,12 +350,17 @@ func (s StandardCrypto) RSAPublicKeyAsJSON(kid string) (string, error) {
if !ok {
return "", ErrCertNotFound
}
- rsa, ok := k.(StandardRSACrypto)
+ rsa, ok := k.(PrivateKeyCrypto)
if !ok {
return "", ErrCertNotFound
}
- rsaPublicKeyJwk, err := jwk.FromRaw(rsa.asymEncryption.PublicKey)
+ asymEncryption, ok := rsa.enc.(*ocrypto.AsymEncryption)
+ if !ok {
+ return "", fmt.Errorf("key with id [%s] does not support JWK export: %w", kid, ErrCertNotFound)
+ }
+
+ rsaPublicKeyJwk, err := jwk.FromRaw(asymEncryption.PublicKey)
if err != nil {
return "", fmt.Errorf("jwk.FromRaw: %w", err)
}
@@ -429,12 +429,8 @@ func (s *StandardCrypto) Decrypt(_ context.Context, keyID trust.KeyIdentifier, c
return nil, fmt.Errorf("failed to decrypt with ephemeral key: %w", err)
}
- case StandardRSACrypto:
- if len(ephemeralPublicKey) > 0 {
- return nil, errors.New("ephemeral public key should not be provided for RSA decryption")
- }
-
- rawKey, err = key.asymDecryption.Decrypt(ciphertext)
+ case PrivateKeyCrypto:
+ rawKey, err = key.dec.DecryptWithEphemeralKey(ciphertext, ephemeralPublicKey)
if err != nil {
return nil, fmt.Errorf("error decrypting data: %w", err)
}
diff --git a/service/kas/access/publicKey.go b/service/kas/access/publicKey.go
index eb5b1fe780..98c5721e8a 100644
--- a/service/kas/access/publicKey.go
+++ b/service/kas/access/publicKey.go
@@ -149,11 +149,11 @@ func (p *Provider) PublicKey(ctx context.Context, req *connect.Request[kaspb.Pub
}
switch algorithm {
- case security.AlgorithmECP256R1:
+ case security.AlgorithmECP256R1, security.AlgorithmECP384R1, security.AlgorithmECP521R1:
// For EC keys, export the public key
ecPublicKeyPem, err := keyDetails.ExportPublicKey(ctx, trust.KeyTypePKCS8)
return r(ecPublicKeyPem, kid, err)
- case security.AlgorithmRSA2048:
+ case security.AlgorithmMLKEM768, security.AlgorithmMLKEM1024, security.AlgorithmRSA2048, security.AlgorithmRSA4096, security.AlgorithmHybridXWing:
fallthrough
case "":
switch fmt {
diff --git a/service/kas/access/rewrap.go b/service/kas/access/rewrap.go
index d62975a480..f771b5e9bf 100644
--- a/service/kas/access/rewrap.go
+++ b/service/kas/access/rewrap.go
@@ -667,6 +667,50 @@ func (p *Provider) verifyRewrapRequests(ctx context.Context, req *kaspb.Unsigned
var dek ocrypto.ProtectedKey
var err error
switch kao.GetKeyAccessObject().GetKeyType() {
+ case string(ocrypto.MLKEM):
+ ephemeralCiphertext := kao.GetKeyAccessObject().GetEphemeralPublicKey()
+ if ephemeralCiphertext == "" {
+ p.Logger.WarnContext(ctx, "missing encapsulated key for ml-kem rewrap")
+ failedKAORewrap(results, kao, err400("bad request"))
+ continue
+ }
+
+ encapsulatedKey, err := ocrypto.Base64Decode([]byte(ephemeralCiphertext))
+ if err != nil {
+ p.Logger.WarnContext(ctx, "failed to decode encapsulated key for ml-kem rewrap", slog.Any("error", err))
+ failedKAORewrap(results, kao, err400("bad request"))
+ continue
+ }
+
+ kid := trust.KeyIdentifier(kao.GetKeyAccessObject().GetKid())
+ dek, err = p.KeyDelegator.Decrypt(ctx, kid, kao.GetKeyAccessObject().GetWrappedKey(), encapsulatedKey)
+ if err != nil {
+ p.Logger.WarnContext(ctx, "failed to decrypt ML-KEM key", slog.Any("error", err))
+ failedKAORewrap(results, kao, err400("bad request"))
+ continue
+ }
+ case string(ocrypto.Hybrid):
+ ephemeralCiphertext := kao.GetKeyAccessObject().GetEphemeralPublicKey()
+ if ephemeralCiphertext == "" {
+ p.Logger.WarnContext(ctx, "missing encapsulated key for hybrid rewrap")
+ failedKAORewrap(results, kao, err400("bad request"))
+ continue
+ }
+
+ encapsulatedKey, err := ocrypto.Base64Decode([]byte(ephemeralCiphertext))
+ if err != nil {
+ p.Logger.WarnContext(ctx, "failed to decode encapsulated key for hybrid rewrap", slog.Any("error", err))
+ failedKAORewrap(results, kao, err400("bad request"))
+ continue
+ }
+
+ kid := trust.KeyIdentifier(kao.GetKeyAccessObject().GetKid())
+ dek, err = p.KeyDelegator.Decrypt(ctx, kid, kao.GetKeyAccessObject().GetWrappedKey(), encapsulatedKey)
+ if err != nil {
+ p.Logger.WarnContext(ctx, "failed to decrypt hybrid key", slog.Any("error", err))
+ failedKAORewrap(results, kao, err400("bad request"))
+ continue
+ }
case "ec-wrapped":
if !p.ECTDFEnabled && !p.Preview.ECTDFEnabled {
@@ -920,11 +964,11 @@ func (p *Provider) tdf3Rewrap(ctx context.Context, requests []*kaspb.UnsignedRew
encap := security.OCEncapsulator{PublicKeyEncryptor: asymEncrypt}
var sessionKey string
- if e, ok := asymEncrypt.(ocrypto.ECEncryptor); ok {
+ switch e := asymEncrypt.(type) {
+ case ocrypto.ECEncryptor:
sessionKey, err = e.PublicKeyInPemFormat()
if err != nil {
p.Logger.ErrorContext(ctx, "unable to serialize ephemeral key", slog.Any("error", err))
- // This may be a 500, but could also be caused by a bad clientPublicKey
failAllKaos(requests, results, err400("invalid request"))
return "", results, nil
}
@@ -933,6 +977,13 @@ func (p *Provider) tdf3Rewrap(ctx context.Context, requests []*kaspb.UnsignedRew
failAllKaos(requests, results, err400("invalid request"))
return "", results, nil
}
+ case *ocrypto.HybridXWingEncryptorWrapper:
+ sessionKey, err = e.PublicKeyInPemFormat()
+ if err != nil {
+ p.Logger.ErrorContext(ctx, "unable to serialize hybrid session key", slog.Any("error", err))
+ failAllKaos(requests, results, err400("invalid request"))
+ return "", results, nil
+ }
}
for _, pdpAccess := range pdpAccessResults {
diff --git a/service/kas/kas.proto b/service/kas/kas.proto
index 7563a25e49..d9ddc6de09 100644
--- a/service/kas/kas.proto
+++ b/service/kas/kas.proto
@@ -68,7 +68,7 @@ message KeyAccess {
// Type of key wrapping used for the data encryption key
// Required: Always
- // Values: 'wrapped' (RSA-wrapped for ZTDF), 'ec-wrapped' (experimental ECDH-wrapped)
+ // Values: 'wrapped' (RSA-wrapped for ZTDF), 'ec-wrapped' (experimental ECDH-wrapped), 'mlkem-wrapped' (ML-KEM-wrapped), 'hybrid' (Hybrid X-Wing-wrapped)
string key_type = 4 [json_name = "type"];
// URL of the Key Access Server that can unwrap this key
@@ -99,10 +99,10 @@ message KeyAccess {
// Contains magic bytes, version, algorithm, policy, and ephemeral key information
bytes header = 9;
- // Ephemeral public key for ECDH key derivation (ec-wrapped type only)
- // Required: When key_type="ec-wrapped" (experimental ECDH-based ZTDF)
+ // Ephemeral public key for ECDH/ML-KEM/Hybrid key derivation
+ // Required: When key_type="ec-wrapped", "mlkem-wrapped", or "hybrid"
// Omitted: When key_type="wrapped" (RSA-based ZTDF)
- // Should be a PEM-encoded PKCS#8 (ASN.1) formatted public key
+ // Should be a PEM-encoded or Base64-encoded (for ML-KEM/Hybrid) public key material
// Used to derive the symmetric key for unwrapping the DEK
string ephemeral_public_key = 10;
}
@@ -257,8 +257,8 @@ message RewrapResponse {
bytes entity_wrapped_key = 2 [deprecated = true];
// KAS's ephemeral session public key in PEM format
- // Required: For EC-based operations (key_type="ec-wrapped")
- // Optional: Empty for RSA-based ZTDF (key_type="wrapped")
+ // Required: For EC-based operations (key_type="ec-wrapped") or Hybrid
+ // Optional: Empty for RSA-based ZTDF (key_type="wrapped") or ML-KEM
// Used by client to perform ECDH key agreement and decrypt the kas_wrapped_key values
string session_public_key = 3;
diff --git a/service/kas/key_indexer.go b/service/kas/key_indexer.go
index 021b3f418a..99e785e311 100644
--- a/service/kas/key_indexer.go
+++ b/service/kas/key_indexer.go
@@ -58,6 +58,12 @@ func convertEnumToAlg(alg policy.Algorithm) ocrypto.KeyType {
return ocrypto.EC384Key
case policy.Algorithm_ALGORITHM_EC_P521:
return ocrypto.EC521Key
+ case policy.Algorithm_ALGORITHM_MLKEM_768:
+ return ocrypto.MLKEM768Key
+ case policy.Algorithm_ALGORITHM_MLKEM_1024:
+ return ocrypto.MLKEM1024Key
+ case policy.Algorithm_ALGORITHM_HYBRID_XWING:
+ return ocrypto.HybridXWingKey
case policy.Algorithm_ALGORITHM_UNSPECIFIED:
fallthrough
default:
@@ -77,6 +83,12 @@ func convertAlgToEnum(alg string) (policy.Algorithm, error) {
return policy.Algorithm_ALGORITHM_EC_P384, nil
case string(ocrypto.EC521Key):
return policy.Algorithm_ALGORITHM_EC_P521, nil
+ case string(ocrypto.MLKEM768Key):
+ return policy.Algorithm_ALGORITHM_MLKEM_768, nil
+ case string(ocrypto.MLKEM1024Key):
+ return policy.Algorithm_ALGORITHM_MLKEM_1024, nil
+ case string(ocrypto.HybridXWingKey):
+ return policy.Algorithm_ALGORITHM_HYBRID_XWING, nil
default:
return policy.Algorithm_ALGORITHM_UNSPECIFIED, fmt.Errorf("unsupported algorithm: %s", alg)
}
diff --git a/service/pkg/db/marshalHelpers.go b/service/pkg/db/marshalHelpers.go
index 667ab27e21..1b10c1d4f5 100644
--- a/service/pkg/db/marshalHelpers.go
+++ b/service/pkg/db/marshalHelpers.go
@@ -157,6 +157,12 @@ func FormatAlg(alg policy.Algorithm) (string, error) {
return "ec:secp384r1", nil
case policy.Algorithm_ALGORITHM_EC_P521:
return "ec:secp521r1", nil
+ case policy.Algorithm_ALGORITHM_MLKEM_768:
+ return "mlkem:768", nil
+ case policy.Algorithm_ALGORITHM_MLKEM_1024:
+ return "mlkem:1024", nil
+ case policy.Algorithm_ALGORITHM_HYBRID_XWING:
+ return "hpqt:xwing", nil
case policy.Algorithm_ALGORITHM_UNSPECIFIED:
fallthrough
default:
diff --git a/service/policy/db/grant_mappings.go b/service/policy/db/grant_mappings.go
index 7c3688af58..e498c63b6c 100644
--- a/service/policy/db/grant_mappings.go
+++ b/service/policy/db/grant_mappings.go
@@ -22,6 +22,12 @@ func mapAlgorithmToKasPublicKeyAlg(alg policy.Algorithm) policy.KasPublicKeyAlgE
return policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1
case policy.Algorithm_ALGORITHM_EC_P521: // ALGORITHM_EC_P521 is an alias
return policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1
+ case policy.Algorithm_ALGORITHM_MLKEM_768:
+ return policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768
+ case policy.Algorithm_ALGORITHM_MLKEM_1024:
+ return policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024
+ case policy.Algorithm_ALGORITHM_HYBRID_XWING:
+ return policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING
case policy.Algorithm_ALGORITHM_UNSPECIFIED:
return policy.KasPublicKeyAlgEnum_KAS_PUBLIC_KEY_ALG_ENUM_UNSPECIFIED
default:
diff --git a/service/policy/kasregistry/key_access_server_registry.proto b/service/policy/kasregistry/key_access_server_registry.proto
index f7c4bdf7f8..ae65fa19f9 100644
--- a/service/policy/kasregistry/key_access_server_registry.proto
+++ b/service/policy/kasregistry/key_access_server_registry.proto
@@ -403,7 +403,7 @@ message CreateKeyRequest {
Algorithm key_algorithm = 3 [(buf.validate.field).cel = {
id: "key_algorithm_defined"
message: "The key_algorithm must be one of the defined values."
- expression: "this in [1, 2, 3, 4, 5]" // Allow ALGORITHM_RSA_2048, ALGORITHM_RSA_4096, ALGORITHM_EC_P256, ALGORITHM_EC_P384, ALGORITHM_EC_P521
+ expression: "this in [1, 2, 3, 4, 5, 20, 21]" // Allow RSA, EC, and ML-KEM algorithms
}]; // The algorithm to be used for the key
// Required
KeyMode key_mode = 4 [(buf.validate.field).cel = {
@@ -550,7 +550,7 @@ message RotateKeyRequest {
Algorithm algorithm = 2 [(buf.validate.field).cel = {
id: "key_algorithm_defined"
message: "The key_algorithm must be one of the defined values."
- expression: "this in [1, 2, 3, 4, 5]" // Allow ALGORITHM_RSA_2048, ALGORITHM_RSA_4096, ALGORITHM_EC_P256, ALGORITHM_EC_P384, ALGORITHM_EC_P521
+ expression: "this in [1, 2, 3, 4, 5, 20, 21]" // Allow RSA, EC, and ML-KEM algorithms
}];
// Required
KeyMode key_mode = 3 [
diff --git a/service/policy/objects.proto b/service/policy/objects.proto
index a54bc2517a..5d45585f84 100644
--- a/service/policy/objects.proto
+++ b/service/policy/objects.proto
@@ -388,6 +388,9 @@ enum KasPublicKeyAlgEnum {
KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP256R1 = 5;
KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP384R1 = 6;
KAS_PUBLIC_KEY_ALG_ENUM_EC_SECP521R1 = 7;
+ KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768 = 20;
+ KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_1024 = 21;
+ KAS_PUBLIC_KEY_ALG_ENUM_HYBRID_XWING = 30;
}
// Deprecated
@@ -553,6 +556,9 @@ enum Algorithm {
ALGORITHM_EC_P256 = 3;
ALGORITHM_EC_P384 = 4;
ALGORITHM_EC_P521 = 5;
+ ALGORITHM_MLKEM_768 = 20;
+ ALGORITHM_MLKEM_1024 = 21;
+ ALGORITHM_HYBRID_XWING = 30;
}
// The status of the key