%PDF- %PDF-
Direktori : /home/waritko/build/Bento4/Source/Python/utils/ |
Current File : //home/waritko/build/Bento4/Source/Python/utils/skm.py |
import aes import urllib2 import os import hashlib import json KEKID_CONSTANT_1 = "KEKID_1" def WrapKey(key, kek): if len(key) > 16: # assume hex key = key.decode('hex') if len(kek) > 16: # assume hex kek = kek.decode('hex') if (len(key)% 8) or (len(kek) % 8): raise Exception('key and kek must be a multiple of 64 bits') # create a cipher with kek cipher = aes.rijndael(kek) # Inputs: Plaintext, n 64-bit values {P1, P2, ..., Pn}, and # Key, K (the KEK). # Outputs: Ciphertext, (n+1) 64-bit values {C0, C1, ..., Cn}. n = len(key)/8; if n < 1: raise Exception('key too short') # 1) Initialize variables. # # Set A = IV, an initial value (see 2.2.3) # For i = 1 to n # R[i] = P[i] A = 'A6A6A6A6A6A6A6A6'.decode('hex'); R = [key[i*8:(i+1)*8] for i in range(n)] # 2) Calculate intermediate values. # # For j = 0 to 5 # For i=1 to n # B = AES(K, A | R[i]) # A = MSB(64, B) ^ t where t = (n*j)+i # R[i] = LSB(64, B) for j in range(6): for i in range(n): B = cipher.encrypt(A+R[i]) A = B[0:7]+chr(ord(B[7]) ^ ((n*j)+i+1)) R[i] = B[8:16] # 3) Output the results. # # Set C[0] = A # For i = 1 to n # C[i] = R[i] return ''.join([A]+R) def UnwrapKey(key, kek): if len(key) > 32: # assume hex key = key.decode('hex') if len(kek) > 16: # assume hex kek = kek.decode('hex') if (len(key)% 8) or (len(kek) % 8): raise Exception('key and kek must be a multiple of 64 bits') # create a de-cipher with kek decipher = aes.rijndael(kek) # Inputs: Ciphertext, (n+1) 64-bit values {C0, C1, ..., Cn}, and # Key, K (the KEK). # Outputs: Plaintext, n 64-bit values {P0, P1, K, Pn}. n = len(key)/8 - 1; if n < 1: raise Exception('wrapped key too short'); # 1) Initialize variables. # # Set A = C[0] # For i = 1 to n # R[i] = C[i] A = key[0:8] R = [key[(i+1)*8:(i+2)*8] for i in range(n)] # 2) Compute intermediate values. # # For j = 5 to 0 # For i = n to 1 # B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i # A = MSB(64, B) # R[i] = LSB(64, B) for j in range(5, -1, -1): for i in range(n-1, -1, -1): B = decipher.decrypt(A[0:7] + chr(ord(A[7])^((n*j)+i+1))+R[i]) A = B[0:8] R[i] = B[8:16] # 3) Output results. # # If A is an appropriate initial value (see 2.2.3), # Then # For i = 1 to n # P[i] = R[i] # Else # Return an error for i in range(8): if ord(A[i]) != 0xA6: raise Exception('invalid/corrupted wrapped key or wrong kek') return ''.join(R) def ComputeKekId(kek): if len(kek) > 16: kek = kek.decode('hex') sha1 = hashlib.sha1() sha1.update(KEKID_CONSTANT_1) sha1.update(kek) return '#1.'+sha1.digest()[0:16].encode('hex') def ResolveKey(options, spec): if '#' in spec: (base_url, spec_params_str) = spec.split('#', 1) spec_params_list = spec_params_str.split('&') spec_params = dict([tuple(spec_param.split('=', 1)) for spec_param in spec_params_list]) else: base_url = spec spec_params = {} skm_mode = spec_params.get('mode', 'auto') skm_kek = spec_params.get('kek', None) key = None key_object = {} for name in ['kid', 'kekId', 'info', 'contentId']: if name in spec_params: key_object[name] = spec_params[name] # soft-import the Requests module try: import requests except: raise Exception('"Requests" python module not installed. Please install it (use "pip install requests" or "easy_install requests" in a command shell, or consult the "Requests" documentation at http://docs.python-requests.org/en/latest/)') if options.debug: print 'Key Object Input:', key_object if skm_mode == 'get': if 'kid' not in spec_params: raise Exception('kid parameter must be specified when using "get" mode') kid = spec_params['kid'] if '?' in base_url: (base_url_path, base_url_query) = tuple(base_url.split('?', 1)) base_url_query = '?'+base_url_query else: base_url_path = base_url base_url_query = '' if base_url_path.endswith('/'): base_url_path = base_url_path[:-1] base_url = base_url_path+'/'+kid+base_url_query if options.debug: print 'Request:', base_url response = requests.get(base_url) elif skm_mode == 'auto': if skm_kek: # generate a key locally and wrap it key = os.urandom(16) key_object['ek'] = WrapKey(key, skm_kek).encode('hex') if 'kekId' not in key_object: key_object['kekId'] = ComputeKekId(skm_kek) if options.verbose: print 'Generating key locally' if options.debug: print 'Request:', base_url, json.dumps(key_object) response = requests.post(base_url, headers={'content-type': 'application/json'}, data=json.dumps(key_object)) else: raise Exception('Unsupported SKM query mode') if response.status_code != 200 and response.status_code != 201: raise Exception('HTTP error while getting key: '+str(response.status_code)+', '+response.text) if options.debug: print 'Response:', response.text response_json = json.loads(response.text) kid = response_json['kid'] if skm_kek and ('ek' in response_json): received_key = UnwrapKey(response_json['ek'], skm_kek) if options.verbose: if key and (key != received_key): print 'Locally generated key was ignored because a key with the same KID already existed on the server' key = received_key if not key: key = response_json['k'] else: key = key.encode('hex') return (kid, key)