Skip to content

Commit f0205eb

Browse files
chore(testvector): Make testvectors run with MKP (#281)
1 parent c604c31 commit f0205eb

File tree

4 files changed

+229
-94
lines changed

4 files changed

+229
-94
lines changed

.github/workflows/library_interop_test_vectors.yml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
ubuntu-22.04,
2626
macos-13,
2727
]
28-
language: [java, net, rust, python]
28+
language: [java_mkp, java_keyrings, net, rust, python_mkp, python_keyrings]
2929
# https://taskei.amazon.dev/tasks/CrypTool-5284
3030
dotnet-version: ["6.0.x"]
3131
runs-on: ${{ matrix.os }}
@@ -63,14 +63,14 @@ jobs:
6363

6464
# Setup Java in Rust is needed for running polymorph
6565
- name: Setup Java 17
66-
if: matrix.language == 'java' || matrix.language == 'rust'
66+
if: matrix.language == 'java_mkp' || matrix.language == 'java_keyrings' || matrix.language == 'rust'
6767
uses: actions/setup-java@v3
6868
with:
6969
distribution: "corretto"
7070
java-version: 17
7171

7272
- name: Setup Python for running tests
73-
if: matrix.language == 'python'
73+
if: matrix.language == 'python_mkp' || matrix.language == 'python_keyrings'
7474
uses: actions/setup-python@v4
7575
with:
7676
python-version: 3.11
@@ -121,7 +121,7 @@ jobs:
121121

122122
# Build implementation for each runtime
123123
- name: Build ${{ matrix.library }} implementation in Java
124-
if: matrix.language == 'java'
124+
if: matrix.language == 'java_mkp' || matrix.language == 'java_keyrings'
125125
shell: bash
126126
working-directory: ./${{ matrix.library }}
127127
run: |
@@ -158,7 +158,7 @@ jobs:
158158
make transpile_rust CORES=$CORES
159159
160160
- name: Build ${{ matrix.library }} implementation in Python
161-
if: matrix.language == 'python'
161+
if: matrix.language == 'python_keyrings' || matrix.language == 'python_mkp'
162162
shell: bash
163163
working-directory: ./${{ matrix.library }}
164164
run: |
@@ -184,7 +184,7 @@ jobs:
184184
make purge_polymorph_code
185185
186186
- name: Setup gradle
187-
if: matrix.language == 'java'
187+
if: matrix.language == 'java_mkp' || matrix.language == 'java_keyrings'
188188
uses: gradle/gradle-build-action@v2
189189
with:
190190
gradle-version: 7.2
@@ -218,8 +218,8 @@ jobs:
218218
ubuntu-22.04,
219219
macos-13,
220220
]
221-
encrypting_language: [java, net, rust, python]
222-
decrypting_language: [java, net, rust, python]
221+
encrypting_language: [java_mkp, java_keyrings, net, rust, python_mkp, python_keyrings]
222+
decrypting_language: [java_mkp, java_keyrings, net, rust, python_mkp, python_keyrings]
223223
# https://taskei.amazon.dev/tasks/CrypTool-5284
224224
dotnet-version: ["6.0.x"]
225225
runs-on: ${{ matrix.os }}
@@ -258,14 +258,14 @@ jobs:
258258

259259
# Setup Java in Rust is needed for running polymorph
260260
- name: Setup Java 17
261-
if: matrix.decrypting_language == 'java' || matrix.decrypting_language == 'rust'
261+
if: matrix.decrypting_language == 'java_mkp' || matrix.decrypting_language == 'java_keyrings' || matrix.decrypting_language == 'rust'
262262
uses: actions/setup-java@v3
263263
with:
264264
distribution: "corretto"
265265
java-version: 17
266266

267267
- name: Setup Python for running tests
268-
if: matrix.decrypting_language == 'python'
268+
if: matrix.decrypting_language == 'python_mkp' || matrix.decrypting_language == 'python_keyrings'
269269
uses: actions/setup-python@v4
270270
with:
271271
python-version: 3.11
@@ -316,7 +316,7 @@ jobs:
316316

317317
# Build implementation for each runtime
318318
- name: Build ${{ matrix.library }} implementation in Java
319-
if: matrix.decrypting_language == 'java'
319+
if: matrix.decrypting_language == 'java_mkp' || matrix.decrypting_language == 'java_keyrings'
320320
working-directory: ./${{ matrix.library }}
321321
shell: bash
322322
run: |
@@ -370,7 +370,7 @@ jobs:
370370
make purge_polymorph_code
371371
372372
- name: Build ${{ matrix.library }} implementation in Python
373-
if: matrix.decrypting_language == 'python'
373+
if: matrix.decrypting_language == 'python_mkp' || matrix.decrypting_language == 'python_keyrings'
374374
shell: bash
375375
working-directory: ./${{ matrix.library }}
376376
run: |
@@ -385,4 +385,4 @@ jobs:
385385

386386
- name: Decrypt Encrypt Manifest
387387
working-directory: ./${{ matrix.library }}
388-
run: make test_decrypt_encrypt_vectors_${{matrix.decrypting_language}}
388+
run: make test_decrypt_encrypt_vectors_${{matrix.decrypting_language}}

TestVectors/Makefile

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ test_generate_vectors_java:
177177
gradle -p runtimes/java run --args="encrypt-manifest --encrypt-manifest-output ."
178178
gradle -p runtimes/java copyKeysJSONCurr
179179

180+
test_generate_vectors_java_mkp: test_generate_vectors_java
181+
182+
test_generate_vectors_java_keyrings: test_generate_vectors_java
183+
180184
test_generate_vectors_net: FRAMEWORK=net6.0
181185
test_generate_vectors_net:
182186
dotnet restore runtimes/net
@@ -199,7 +203,14 @@ test_generate_vectors_python:
199203
python3 -m tox -c runtimes/python --verbose -e cli -- encrypt-manifest --encrypt-manifest-output runtimes/python
200204
cp dafny/TestVectors/test/keys.json runtimes/python
201205

202-
test_encrypt_vectors_java:
206+
test_generate_vectors_python_mkp: test_generate_vectors_python
207+
208+
test_generate_vectors_python_keyrings: test_generate_vectors_python
209+
210+
test_encrypt_vectors_java_mkp:
211+
gradle -p runtimes/java run --args="encrypt --manifest-path . --decrypt-manifest-path ."
212+
213+
test_encrypt_vectors_java_keyrings:
203214
gradle -p runtimes/java run --args="encrypt --manifest-path . --decrypt-manifest-path ."
204215

205216
test_encrypt_vectors_net: FRAMEWORK=net6.0
@@ -216,11 +227,18 @@ test_encrypt_vectors_rust:
216227
test_encrypt_vectors_go:
217228
go -C runtimes/go/ImplementationFromDafny-go run ImplementationFromDafny.go encrypt --manifest-path=.. --decrypt-manifest-path=..
218229

219-
test_encrypt_vectors_python:
230+
test_encrypt_vectors_python_keyrings:
220231
rm -rf runtimes/python/.tox
221232
python3 -m tox -c runtimes/python --verbose -e cli -- encrypt --manifest-path runtimes/python --decrypt-manifest-path runtimes/python
222233

223-
test_decrypt_encrypt_vectors_java:
234+
test_encrypt_vectors_python_mkp:
235+
rm -rf runtimes/python/.tox
236+
python3 -m tox -c runtimes/python --verbose -e cli -- encrypt --manifest-path runtimes/python --decrypt-manifest-path runtimes/python MASTERKEY
237+
238+
test_decrypt_encrypt_vectors_java_mkp:
239+
gradle -p runtimes/java run --args="decrypt --manifest-path . --manifest-name decrypt-manifest.json"
240+
241+
test_decrypt_encrypt_vectors_java_keyrings:
224242
gradle -p runtimes/java run --args="decrypt --manifest-path . --manifest-name decrypt-manifest.json"
225243

226244
test_decrypt_encrypt_vectors_net: FRAMEWORK=net6.0
@@ -247,10 +265,14 @@ test_decrypt_encrypt_vectors_rust:
247265
test_decrypt_encrypt_vectors_go:
248266
go -C runtimes/go/ImplementationFromDafny-go run ImplementationFromDafny.go decrypt --manifest-path=.. --manifest-name=decrypt-manifest.json
249267

250-
test_decrypt_encrypt_vectors_python:
268+
test_decrypt_encrypt_vectors_python_keyrings:
251269
rm -rf runtimes/python/.tox
252270
python3 -m tox -c runtimes/python --verbose -e cli -- decrypt --manifest-path runtimes/python --manifest-name decrypt-manifest.json
253271

272+
test_decrypt_encrypt_vectors_python_mkp:
273+
rm -rf runtimes/python/.tox
274+
python3 -m tox -c runtimes/python --verbose -e cli -- decrypt --manifest-path runtimes/python --manifest-name decrypt-manifest.json MASTERKEY
275+
254276
_polymorph_dependencies:
255277
@echo "No polymorphing of dependency"
256278

@@ -285,4 +307,4 @@ PYTHON_DEPENDENCY_MODULE_NAMES := \
285307
--dependency-library-name=aws.cryptography.keyStore=aws_cryptographic_material_providers \
286308
--dependency-library-name=smithy.api=aws_cryptographic_material_providers \
287309
--dependency-library-name=aws.cryptography.materialProvidersTestVectorKeys=aws_cryptographic_material_providers_test_vectors \
288-
--dependency-library-name=aws.cryptography.encryptionSdk=aws_encryption_sdk_dafny
310+
--dependency-library-name=aws.cryptography.encryptionSdk=aws_encryption_sdk_dafny
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
from aws_encryption_sdk.key_providers.raw import RawMasterKeyProvider
5+
from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm
6+
from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey
7+
from aws_encryption_sdk.internal.str_ops import to_str
8+
from aws_cryptographic_material_providers.internaldafny.generated.RawAESKeyring import RawAESKeyring
9+
from aws_cryptographic_material_providers.internaldafny.generated.AwsKmsKeyring import AwsKmsKeyring
10+
from aws_cryptographic_material_providers.internaldafny.generated.AwsKmsMrkKeyring import AwsKmsMrkKeyring
11+
from aws_cryptographic_material_providers.internaldafny.generated.AwsKmsDiscoveryKeyring import AwsKmsDiscoveryKeyring
12+
from aws_cryptographic_material_providers.internaldafny.generated.AwsKmsMrkDiscoveryKeyring import AwsKmsMrkDiscoveryKeyring
13+
from aws_encryption_sdk.key_providers.kms import (
14+
MRKAwareDiscoveryAwsKmsMasterKeyProvider,
15+
MRKAwareStrictAwsKmsMasterKeyProvider,
16+
)
17+
import aws_cryptographic_material_providers.smithygenerated.aws_cryptography_materialproviders.dafny_to_smithy
18+
import aws_encryption_sdk
19+
class StaticMasterKeyProvider(RawMasterKeyProvider):
20+
"""Generates 256-bit keys for each unique key ID."""
21+
22+
def __init__(self, **kwargs): # pylint: disable=unused-argument
23+
"""Initialize empty map of keys."""
24+
self._static_keys = {}
25+
self.provider_id = ""
26+
27+
@property
28+
def static_keys(self):
29+
return self._static_keys
30+
31+
# The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field
32+
# in the Raw Master Key Providers
33+
@property
34+
def provider_id(self):
35+
return self._provider_id
36+
37+
@property
38+
def wrapping_key_type(self):
39+
return self._wrapping_key_type
40+
41+
@property
42+
def wrapping_algorithm(self):
43+
return self._wrapping_algorithm
44+
45+
@provider_id.setter
46+
def provider_id(self, value):
47+
self._provider_id = value
48+
49+
@static_keys.setter
50+
def static_keys(self, static_key_dict):
51+
self._static_keys = static_key_dict
52+
53+
@wrapping_key_type.setter
54+
def wrapping_key_type(self, wrapping_key_type):
55+
self._wrapping_key_type = wrapping_key_type
56+
57+
@wrapping_key_type.setter
58+
def wrapping_algorithm(self, wrapping_algorithm):
59+
self._wrapping_algorithm = wrapping_algorithm
60+
61+
def _get_raw_key(self, key_id):
62+
"""Returns a static, symmetric key for the specified key ID.
63+
64+
:param str key_id: Key ID
65+
:returns: Wrapping key that contains the specified static key
66+
:rtype: :class:`aws_encryption_sdk.internal.crypto.WrappingKey`
67+
"""
68+
static_key = self._static_keys[to_str(key_id)] # add_master_key changes it to bytes and we have to use internal to_str
69+
return WrappingKey(
70+
wrapping_algorithm=self._wrapping_algorithm,
71+
wrapping_key=static_key,
72+
wrapping_key_type=self._wrapping_key_type,
73+
)
74+
75+
def create_raw_aes_key_provider(key_name, key_namespace, key):
76+
# Create a Raw AES master key provider.
77+
78+
# The key name in the Raw keyrings is equivalent to the Key ID field
79+
# in the Raw Master Key Providers
80+
key_id = key_name
81+
static_key_map = {key_id: key}
82+
key_provider = StaticMasterKeyProvider()
83+
key_provider.static_keys = static_key_map
84+
key_provider.provider_id = key_namespace
85+
key_provider.wrapping_key_type = EncryptionKeyType.SYMMETRIC
86+
key_provider.wrapping_algorithm = WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING
87+
key_provider.add_master_key(key_name)
88+
89+
return key_provider
90+
91+
def keyring_to_mkp(keyring):
92+
if (isinstance(keyring, RawAESKeyring)):
93+
mkp_key_id = bytes(keyring.wrappingKey)
94+
# The key name in the Raw keyrings is equivalent to the Key ID field
95+
# in the Raw Master Key Providers
96+
mkp_key = b"".join(
97+
ord(chr(c)).to_bytes(2, "big") for c in keyring.keyName
98+
).decode("utf-16-be")
99+
mkpProvider_id = b"".join(
100+
ord(chr(c)).to_bytes(2, "big") for c in keyring.keyNamespace
101+
).decode("utf-16-be")
102+
return create_raw_aes_key_provider(mkp_key, mkpProvider_id, mkp_key_id)
103+
104+
if (isinstance(keyring, AwsKmsKeyring)):
105+
aws_kms_arn = string_to_native(keyring.awsKmsKey)
106+
return aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[
107+
aws_kms_arn,
108+
])
109+
110+
if (isinstance(keyring, AwsKmsMrkKeyring)):
111+
aws_kms_arn = string_to_native(keyring.awsKmsKey)
112+
kwargs = dict(key_ids=[aws_kms_arn])
113+
return MRKAwareStrictAwsKmsMasterKeyProvider(**kwargs)
114+
115+
if (isinstance(keyring, AwsKmsDiscoveryKeyring)):
116+
if keyring.discoveryFilter.is_Some:
117+
discovery_filter = aws_cryptographic_material_providers.smithygenerated.aws_cryptography_materialproviders.dafny_to_smithy.aws_cryptography_materialproviders_DiscoveryFilter(
118+
keyring.discoveryFilter.UnwrapOr(None)
119+
)
120+
kwargs = dict(discovery_filter=discovery_filter)
121+
aws_encryption_sdk.DiscoveryAwsKmsMasterKeyProvider(**kwargs)
122+
return aws_encryption_sdk.DiscoveryAwsKmsMasterKeyProvider()
123+
124+
if (isinstance(keyring, AwsKmsMrkDiscoveryKeyring)):
125+
region = string_to_native(keyring.region)
126+
if keyring.discoveryFilter.is_Some:
127+
discovery_filter = aws_cryptographic_material_providers.smithygenerated.aws_cryptography_materialproviders.dafny_to_smithy.aws_cryptography_materialproviders_DiscoveryFilter(
128+
keyring.discoveryFilter.UnwrapOr(None)
129+
)
130+
kwargs = dict(discovery_filter=discovery_filter, discovery_region=region)
131+
aws_encryption_sdk.MRKAwareDiscoveryAwsKmsMasterKeyProvider(**kwargs)
132+
kwargs = dict(discovery_region=region)
133+
return MRKAwareDiscoveryAwsKmsMasterKeyProvider(**kwargs)
134+
raise ValueError("No keyring matched to convert to MKP. Input keyring type: "+ str(type(keyring)))
135+
136+
137+
def string_to_native(arn):
138+
return b"".join(
139+
ord(c).to_bytes(2, "big") for c in arn
140+
).decode("utf-16-be")

0 commit comments

Comments
 (0)