Skip to content

fix JceNameLocalDelegatedKey.generate to always operate in bits #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/dynamodb_encryption_sdk/delegated_keys/jce.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
"""Delegated key that JCE StandardName algorithm values to determine behavior."""
from __future__ import division

import logging
import os

Expand All @@ -32,17 +34,17 @@
def _generate_symmetric_key(key_length):
"""Generate a new AES key.

:param int key_length: Required key length in bytes
:param int key_length: Required key length in bits
:returns: raw key, symmetric key identifier, and RAW encoding identifier
:rtype: tuple of bytes, EncryptionKeyType, and KeyEncodingType
"""
return os.urandom(key_length), EncryptionKeyType.SYMMETRIC, KeyEncodingType.RAW
return os.urandom(key_length // 8), EncryptionKeyType.SYMMETRIC, KeyEncodingType.RAW


def _generate_rsa_key(key_length):
"""Generate a new RSA private key.

:param int key_length: Required key length in bytes
:param int key_length: Required key length in bits
:returns: DER-encoded private key, private key identifier, and DER encoding identifier
:rtype: tuple of bytes, EncryptionKeyType, and KeyEncodingType
"""
Expand Down Expand Up @@ -151,7 +153,7 @@ def generate(cls, algorithm, key_length=None):
"""Generate an instance of this DelegatedKey using the specified algorithm and key length.

:param str algorithm: Text description of algorithm to be used
:param int key_length: Size of key to generate
:param int key_length: Size in bits of key to generate
:returns: Generated delegated key
:rtype: dynamodb_encryption_sdk.delegated_keys.DelegatedKey
"""
Expand Down
4 changes: 1 addition & 3 deletions src/dynamodb_encryption_sdk/materials/wrapped.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
"""Cryptographic materials to use ephemeral content encryption keys wrapped by delegated keys."""
from __future__ import division

import base64
import copy

Expand Down Expand Up @@ -140,7 +138,7 @@ def _generate_content_key(self):
args = self._content_key_algorithm.split('/', 1)
content_algorithm = args[0]
try:
content_key_length = int(args[1]) // 8
content_key_length = int(args[1])
except IndexError:
content_key_length = None
content_key = JceNameLocalDelegatedKey.generate(
Expand Down
13 changes: 13 additions & 0 deletions test/functional/delegated_keys/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
"""Dummy stub to make linters work better."""
48 changes: 48 additions & 0 deletions test/functional/delegated_keys/test_jce.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
"""Functional test suite for ``dynamodb_encryption_sdk.delegated_keys.jce``."""
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
import pytest

from dynamodb_encryption_sdk.delegated_keys.jce import JceNameLocalDelegatedKey

pytestmark = [pytest.mark.functional, pytest.mark.local]


def _find_aes_key_length(key):
return len(key) * 8
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would write this as return len(key) << 3

Not blocking on this.



def _find_rsa_key_length(key):
loaded_key = serialization.load_der_private_key(data=key, password=None, backend=default_backend())
return loaded_key._key_size


@pytest.mark.parametrize('algorithm, requested_bits, expected_bits, length_finder', (
('AES', 256, 256, _find_aes_key_length),
('AESWrap', 256, 256, _find_aes_key_length),
('RSA', 4096, 4096, _find_rsa_key_length),
('HmacSHA512', 256, 256, _find_aes_key_length),
('HmacSHA256', 256, 256, _find_aes_key_length),
('HmacSHA384', 256, 256, _find_aes_key_length),
('HmacSHA224', 256, 256, _find_aes_key_length),
('SHA512withRSA', 4096, 4096, _find_rsa_key_length),
('SHA256withRSA', 4096, 4096, _find_rsa_key_length),
('SHA384withRSA', 4096, 4096, _find_rsa_key_length),
('SHA224withRSA', 4096, 4096, _find_rsa_key_length)
))
def test_generate_correct_key_length(algorithm, requested_bits, expected_bits, length_finder):
test = JceNameLocalDelegatedKey.generate(algorithm, requested_bits)

assert length_finder(test.key) == expected_bits
5 changes: 1 addition & 4 deletions test/functional/functional_test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def _some_algorithm_pairs():
def _all_possible_cmps(algorithm_generator):
"""Generate all possible cryptographic materials providers based on the supplied generator."""
# The AES combinations do the same thing, but this makes sure that the AESWrap name works as expected.
yield _build_wrapped_jce_cmp('AESWrap', 32, 'HmacSHA256', 32)
yield _build_wrapped_jce_cmp('AESWrap', 256, 'HmacSHA256', 256)

for builder_info, args in itertools.product(_cmp_builders.items(), algorithm_generator()):
builder_type, builder_func = builder_info
Expand All @@ -229,9 +229,6 @@ def _all_possible_cmps(algorithm_generator):
sig_key_length=signing_key_length
)

if encryption_algorithm == 'AES':
encryption_key_length //= 8

yield pytest.param(
builder_func(
encryption_algorithm,
Expand Down