diff options
-rwxr-xr-x | src/model/keywrap.py | 176 |
1 files changed, 0 insertions, 176 deletions
diff --git a/src/model/keywrap.py b/src/model/keywrap.py deleted file mode 100755 index 5524937..0000000 --- a/src/model/keywrap.py +++ /dev/null @@ -1,176 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#======================================================================= -# -# keywrap.py -# ---------- -# Python model to test AES KEY WRAP according to RFC 5649. -# -# -# Author: Joachim Strombergson, Rob Austein -# Copyright (c) 2018, NORDUnet A/S -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# - Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# - Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# - Neither the name of the NORDUnet nor the names of its contributors may -# be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -#======================================================================= - -#------------------------------------------------------------------- -# Python module imports. -#------------------------------------------------------------------- -import sys -import Crypto.Random -from Crypto.Cipher import AES -from struct import pack, unpack - - -#------------------------------------------------------------------- -# Constants. -#------------------------------------------------------------------- -VERBOSE = True - - - -#------------------------------------------------------------------- -# AESKeyWrapWithPadding -#------------------------------------------------------------------- -class AESKeyWrapWithPadding(object): - """ - Implementation of AES Key Wrap With Padding from RFC 5649. - """ - - class UnwrapError(Exception): - "Something went wrong during unwrap." - - def __init__(self, key): - self.ctx = AES.new(key, AES.MODE_ECB) - - def _encrypt(self, b1, b2): - aes_block = self.ctx.encrypt(b1 + b2) - return aes_block[:8], aes_block[8:] - - def _decrypt(self, b1, b2): - aes_block = self.ctx.decrypt(b1 + b2) - return aes_block[:8], aes_block[8:] - - @staticmethod - def _start_stop(start, stop): # Syntactic sugar - step = -1 if start > stop else 1 - return xrange(start, stop + step, step) - - @staticmethod - def _xor(R0, t): - return pack(">Q", unpack(">Q", R0)[0] ^ t) - - def wrap(self, Q): - "RFC 5649 section 4.1." - m = len(Q) # Plaintext length - if m % 8 != 0: # Pad Q if needed - Q += "\x00" * (8 - (m % 8)) - R = [pack(">LL", 0xa65959a6, m)] # Magic MSB(32,A), build LSB(32,A) - R.extend(Q[i : i + 8] # Append Q - for i in xrange(0, len(Q), 8)) - n = len(R) - 1 - if n == 1: - R[0], R[1] = self._encrypt(R[0], R[1]) - else: - # RFC 3394 section 2.2.1 - for j in self._start_stop(0, 5): - for i in self._start_stop(1, n): - R[0], R[i] = self._encrypt(R[0], R[i]) - R[0] = self._xor(R[0], n * j + i) - assert len(R) == (n + 1) and all(len(r) == 8 for r in R) - return "".join(R) - - def unwrap(self, C): - "RFC 5649 section 4.2." - if len(C) % 8 != 0: - raise self.UnwrapError("Ciphertext length {} is not an integral number of blocks" - .format(len(C))) - n = (len(C) / 8) - 1 - R = [C[i : i + 8] for i in xrange(0, len(C), 8)] - if n == 1: - R[0], R[1] = self._decrypt(R[0], R[1]) - else: - # RFC 3394 section 2.2.2 steps (1), (2), and part of (3) - for j in self._start_stop(5, 0): - for i in self._start_stop(n, 1): - R[0] = self._xor(R[0], n * j + i) - R[0], R[i] = self._decrypt(R[0], R[i]) - magic, m = unpack(">LL", R[0]) - if magic != 0xa65959a6: - raise self.UnwrapError("Magic value in AIV should have been 0xa65959a6, was 0x{:02x}" - .format(magic)) - if m <= 8 * (n - 1) or m > 8 * n: - raise self.UnwrapError("Length encoded in AIV out of range: m {}, n {}".format(m, n)) - R = "".join(R[1:]) - assert len(R) == 8 * n - if any(r != "\x00" for r in R[m:]): - raise self.UnwrapError("Nonzero trailing bytes {}".format(R[m:].encode("hex"))) - return R[:m] - - -#------------------------------------------------------------------- -# wrap_test1 -# -# First, simplest test from NIST test vectors. -#------------------------------------------------------------------- -def wrap_test1(): - my_key = Crypto.Random.new().read(256/8) - my_keywrap = AESKeyWrapWithPadding(my_key) - - my_plaintext = "\x31\x32\x33" - my_wrap = my_keywrap.wrap(my_plaintext) - print(type(my_wrap)) - my_unwrap = my_keywrap.wrap(my_wrap) - print(type(my_unwrap)) - print("plaintext: %s wrapped: %s unwrapped: %s" % - (my_plaintext, my_wrap, my_unwrap)) - - -#------------------------------------------------------------------- -#------------------------------------------------------------------- -def main(): - print("Testing the Key Wrap Python model") - print("=================================") - print - # keywrap_aes_test() - wrap_test1() - - -#------------------------------------------------------------------- -# __name__ -# Python thingy which allows the file to be run standalone as -# well as parsed from within a Python interpreter. -#------------------------------------------------------------------- -if __name__=="__main__": - # Run the main function. - sys.exit(main()) - -#======================================================================= -# EOF keywrap.py -#======================================================================= |