def _verify_manifest(content, manifest, content_digest=None, verify=True): # pylint: disable=too-many-locals,too-many-branches # Adapted from https://github.com/joyent/node-docker-registry-client if verify or ('signatures' in manifest): signatures = [] for sig in manifest['signatures']: protected64 = sig['protected'] protected = _urlsafe_b64decode(protected64).decode('utf-8') protected_header = json.loads(protected) format_length = protected_header['formatLength'] format_tail64 = protected_header['formatTail'] format_tail = _urlsafe_b64decode(format_tail64).decode('utf-8') alg = sig['header']['alg'] if alg.lower() == 'none': raise exceptions.DXFDisallowedSignatureAlgorithmError('none') if sig['header'].get('chain'): raise exceptions.DXFSignatureChainNotImplementedError() signatures.append({ 'alg': alg, 'signature': sig['signature'], 'protected64': protected64, 'key': _import_key(sig['header']['jwk']), 'format_length': format_length, 'format_tail': format_tail }) payload = content[:signatures[0]['format_length']] + \ signatures[0]['format_tail'] payload64 = _urlsafe_b64encode(payload) else: payload = content if content_digest: method, expected_dgst = split_digest(content_digest) hasher = hashlib.new(method) hasher.update(payload.encode('utf-8')) dgst = hasher.hexdigest() if dgst != expected_dgst: raise exceptions.DXFDigestMismatchError( method + ':' + dgst, method + ':' + expected_dgst) if verify: for sig in signatures: jwstoken = jws.JWS() jwstoken.deserialize( json.dumps({ 'payload': payload64, 'protected': sig['protected64'], 'signature': sig['signature'] }), sig['key'], sig['alg']) dgsts = [] for layer in manifest['fsLayers']: dgst = layer['blobSum'] split_digest(dgst) dgsts.append(dgst) return dgsts
def _verify_manifest(content, manifest, content_digest=None, verify=True): # pylint: disable=too-many-locals,too-many-branches # Adapted from https://github.com/joyent/node-docker-registry-client if verify or ('signatures' in manifest): signatures = [] for sig in manifest['signatures']: protected64 = sig['protected'] protected = _urlsafe_b64decode(protected64).decode('utf-8') protected_header = json.loads(protected) format_length = protected_header['formatLength'] format_tail64 = protected_header['formatTail'] format_tail = _urlsafe_b64decode(format_tail64).decode('utf-8') alg = sig['header']['alg'] if alg.lower() == 'none': raise exceptions.DXFDisallowedSignatureAlgorithmError('none') if sig['header'].get('chain'): raise exceptions.DXFSignatureChainNotImplementedError() signatures.append({ 'alg': alg, 'signature': sig['signature'], 'protected64': protected64, 'key': _jwk_to_key(sig['header']['jwk']), 'format_length': format_length, 'format_tail': format_tail }) payload = content[:signatures[0]['format_length']] + \ signatures[0]['format_tail'] payload64 = _urlsafe_b64encode(payload) else: payload = content if content_digest: method, expected_dgst = content_digest.split(':') if method != 'sha256': raise exceptions.DXFUnexpectedDigestMethodError(method, 'sha256') hasher = hashlib.new(method) hasher.update(payload.encode('utf-8')) dgst = hasher.hexdigest() if dgst != expected_dgst: raise exceptions.DXFDigestMismatchError(dgst, expected_dgst) if verify: for sig in signatures: data = {'key': sig['key'], 'header': {'alg': sig['alg']}} jws.header.process(data, 'verify') sig64 = sig['signature'] data['verifier']("%s.%s" % (sig['protected64'], payload64), _urlsafe_b64decode(sig64), sig['key']) dgsts = [] for layer in manifest['fsLayers']: method, dgst = layer['blobSum'].split(':') if method != 'sha256': raise exceptions.DXFUnexpectedDigestMethodError(method, 'sha256') dgsts.append(dgst) return dgsts