def rsassa_pkcs1_v1_5_verify(cls, key, hash_cls, msg, sig, crypto=None): """Verifies an RSSA-PKCS1-v1_5 Signature :param key: public key for sign check :type key: :class:`versile.crypto.VAsymmetricKey` :param hash_cls: hash type for signature :type hash_cls: :class:`versile.crypto.VHash` :param msg: message to verify :type msg: bytes :param sig: signature to verify against message :type sig: bytes :param crypto: crypto provider (default if None) :type crypto: :class:`versile.crypto.VCrypto` :returns: True if signature verifies :rtype: bool Verifies a signature as defined by :term:`PKCS#1`\ . """ crypto = VCrypto.lazy(crypto) enc_len = len(posint_to_bytes(key.keydata[0])) encoder = cls.emsa_pkcs1_v1_5_encode # Create digest and convert both sig and digest to integer format sig = bytes_to_posint(sig) digest = bytes_to_posint(encoder(msg, enc_len, hash_cls)) # Decipher signature and compare with computed digest orig = crypto.num_cipher(key.cipher_name).encrypter(key)(sig) return (digest == orig)
def rsassa_pkcs1_v1_5_sign(cls, key, hash_cls, msg, crypto=None): """Sign message with a RSSA PKCS #1 v1.5 Signature :param key: private key for signing :type key: :class:`versile.crypto.VAsymmetricKey` :param hash_cls: hash type for signature :type hash_cls: :class:`versile.crypto.VHash` :param msg: message to sign :type msg: bytes :param crypto: crypto provider (default if None) :type crypto: :class:`versile.crypto.VCrypto` :raises: :exc:`versile.crypto.VCryptoException` :returns: signature :rtype: bytes Produces a signature as defined by :term:`PKCS#1`\ . Raises an exception if a signature cannot be produced for the combination of the provided *key* and *hash_cls*\ . .. note:: Signatures require using a hash method which has an associated registered :meth:`versile.crypto.VHash.oid`\ . Also, key length must be sufficient to hold signature data. """ crypto = VCrypto.lazy(crypto) # Create a digest enc_len = len(posint_to_bytes(key.keydata[0])) encoder = cls.emsa_pkcs1_v1_5_encode digest = bytes_to_posint(encoder(msg, enc_len, hash_cls)) # Create the signature sig = crypto.num_cipher(key.cipher_name).decrypter(key)(digest) sig = posint_to_bytes(sig) return sig
def __init__(self, gw_factory, auth, key=None, identity=None, certificates=None, p_auth=None, processor=None, sock=None, node=None, internal=False, buf_size=None, conf=None, reactor=None, crypto=None): if p_auth is None: p_auth = VAuth() if conf is None: conf = VOPServiceConfig() if (key is None and (conf.enable_vts or conf.enable_tls)): raise ValueError('Key cannot be None if VTS or TLS enabled') s_init = super(VOPService, self).__init__ s_init(gw_factory=gw_factory, auth=auth, key=key, identity=identity, certificates=certificates, p_auth=p_auth, processor=processor, sock=sock, node=node, internal=internal, buf_size=buf_size, conf=conf, reactor=reactor) self._crypto = VCrypto.lazy(crypto)
def __create_vop_agent(self, is_client, key, identity, certificates, p_auth, vts, tls, insecure, crypto, internal, buf_size, vec_conf, vts_conf): if p_auth is None: p_auth = VAuth() if not key: if identity is not None or certificates is not None: raise VUrlException('VOP credentials requires a key') elif not is_client and (vts or tls): raise VUrlException('server mode with VTS/TLS requires key') # Set up default crypto crypto = VCrypto.lazy(crypto) rand = VUrandom() bsize = buf_size if internal and bsize is None: bsize = VLinkAgent.DEFAULT_INT_LINK_BUFSIZE # Get VEC byte interface to link vec_io = self.create_byte_agent(internal=internal, buf_size=buf_size, conf=vec_conf) # Set up VOP multiplexer vts_factory = tls_factory = None if (vts): def _factory(reactor): if is_client: Cls = VSecureClient else: Cls = VSecureServer _vts = Cls(reactor=reactor, crypto=crypto, rand=rand, keypair=key, identity=identity, certificates=certificates, p_auth=p_auth, conf=vts_conf) ext_c = _vts.cipher_consume ext_p = _vts.cipher_produce int_c = _vts.plain_consume int_p = _vts.plain_produce return (ext_c, ext_p, int_c, int_p) vts_factory = _factory if (tls): def _factory(reactor): if is_client: Cls = VTLSClient else: Cls = VTLSServer _tls = Cls(reactor=reactor, key=key, identity=identity, certificates=certificates, p_auth=p_auth) ext_c = _tls.cipher_consume ext_p = _tls.cipher_produce int_c = _tls.plain_consume int_p = _tls.plain_produce return (ext_c, ext_p, int_c, int_p) tls_factory = _factory if is_client: Cls = VOPClientBridge else: Cls = VOPServerBridge vop = Cls(reactor=self.reactor, vec=vec_io, vts=vts_factory, tls=tls_factory, insecure=insecure) # Return transport end-points return VByteIOPair(vop.external_consume, vop.external_produce)
def connect(self, gw=None, key=None, identity=None, certificates=None, auth=None, p_auth=None, crypto=None, internal=False, buf_size=None, conf=None, nowait=False, reactor=None, processor=None): if not nowait: _res = self.connect call = _res(gw=gw, key=key, identity=identity, certificates=certificates, auth=auth, p_auth=p_auth, crypto=crypto, internal=internal, buf_size=buf_size, conf=conf, reactor=reactor, processor=processor, nowait=True) return call.result() if p_auth is None: p_auth = VAuth() if conf is None: conf = VOPUrlConfig() if not key and (identity is not None or certificates is not None): raise VUrlException('VOP credentials requires sending a key') link_config = conf.link_config # Add the VEC config as a property on the link configuration # so it can be also accessed via the link config object link_config.vec_config = conf.vec_config link = VLinkAgent(gateway=gw, auth=auth, conf=link_config, reactor=reactor, processor=processor) # Set up default crypto crypto = VCrypto.lazy(crypto) rand = VUrandom() bsize = buf_size if internal and bsize is None: bsize = VLinkAgent.DEFAULT_INT_LINK_BUFSIZE # Get VEC byte interface to link vec_io = link.create_byte_agent(internal=internal, buf_size=buf_size, conf=conf.vec_config) # Set up VOP multiplexer vts_factory = tls_factory = None if (conf.enable_vts): def _factory(reactor): Cls = VSecureClient vts = Cls(reactor=reactor, crypto=crypto, rand=rand, keypair=key, identity=identity, certificates=certificates, p_auth=p_auth, conf=conf.vts_config) ext_c = vts.cipher_consume ext_p = vts.cipher_produce int_c = vts.plain_consume int_p = vts.plain_produce return (ext_c, ext_p, int_c, int_p) vts_factory = _factory if (conf.enable_tls): def _factory(reactor): Cls = VTLSClient tls = Cls(reactor=reactor, key=key, identity=identity, certificates=certificates, p_auth=p_auth) ext_c = tls.cipher_consume ext_p = tls.cipher_produce int_c = tls.plain_consume int_p = tls.plain_produce return (ext_c, ext_p, int_c, int_p) tls_factory = _factory allow_insecure = conf.allow_insecure Cls = VOPClientBridge vop = Cls(reactor=link.reactor, vec=vec_io, vts=vts_factory, tls=tls_factory, insecure=allow_insecure) if bsize is None: sock = VClientSocketAgent(reactor=link.reactor) else: sock = VClientSocketAgent(reactor=link.reactor, max_read=bsize, max_write=bsize) def _connecter(peer): sock.connect(peer) sock.byte_io.attach(vop.external_io) return VUrlResolver(link, self._urldata) result = _ConnectResult(link) def _cback(peer): if not result.cancelled: result.push_result(_connecter(peer)) def _fback(exc): result.cancel() peer_res = VSocketPeer.lookup(host=self._address[0], port=self._address[1], socktype=socket.SOCK_STREAM, nowait=True) peer_res.add_callpair(_cback, _fback) return result
def import_spki_public_key(cls, data, fmt=VX509Format.PEM_BLOCK, keytype='rsa', crypto=None): """Imports a X.509 SPKI public key. :param data: keydata to import :param fmt: format to import from :type fmt: :class:`VX509Format` constant :param keytype: key type to import (or None) :param keytype: unicode :param crypto: crypto provider (default if None) :type crypto: :class:`versile.crypto.VCrypto` :returns: imported key :rtype: :class:`versile.crypto.VAsymmetricKey` Imports an encoding of the key's :term:`ASN.1` representation defined by X.509 SubjectPublicKeyInfo encoding format, associated with the PEM header 'BEGIN PUBLIC KEY'. .. note:: For the :term:`PKCS#1`\ encoding format (PEM header 'BEGIN RSA PUBLIC KEY'), see :meth:`import_public_key`\ . """ crypto = VCrypto.lazy(crypto) if fmt == VX509Format.PEM_BLOCK: heading, data = decode_pem_block(data) if heading == b'PUBLIC KEY': if keytype is None: keytype = 'rsa' elif keytype != 'rsa': raise VCryptoException('Key type mismatch') else: raise VCryptoException('Key type not supported') fmt = VX509Format.DER elif fmt == VX509Format.PEM: if keytype != 'rsa': raise VCryptoException('Key type not supported') if _pyver == 2: data = _s2b(base64.decodestring(_b2s(data))) else: data = base64.decodebytes(data) fmt = VX509Format.DER if fmt == VX509Format.DER: from versile.crypto.x509.asn1def.cert import SubjectPublicKeyInfo spki, len_read = SubjectPublicKeyInfo().parse_der(data) if len_read != len(data): raise VCryptoException('Public Key DER data overflow') data = spki fmt = VX509Format.ASN1 if fmt == VX509Format.ASN1: if keytype != 'rsa': raise VCryptoException('Key type not supported') spki = data.native(deep=True) _alg, keydata = spki # Verify supported key type alg, _params = _alg if alg != VObjectIdentifier(1, 2, 840, 113549, 1, 1, 1): raise VCryptoException('Unsupported key algorithm') # Import key from embedded DER data pub_key = cls.import_public_key(keydata.as_octets(), VX509Format.DER) return pub_key
def import_private_key(cls, data, fmt=VX509Format.PEM_BLOCK, keytype='rsa', crypto=None): """Imports a PKCS#1 private key (i.e. a complete keypair). :param data: keydata to import :param fmt: format to import from :type fmt: :class:`VX509Format` constant :param keytype: key type to import (or None) :param keytype: unicode :param crypto: crypto provider (default if None) :type crypto: :class:`versile.crypto.VCrypto` :returns: imported key :rtype: :class:`versile.crypto.VAsymmetricKey` Imports an encoding of the key's :term:`ASN.1` representation defined by :term:`PKCS#1`\, associated with the PEM header 'BEGIN RSA PRIVATE KEY'. .. note:: Whereas :term:`VPy` refers to complete keys as 'key pairs' and private keys as only the private component of the key, private keys in :term:`PKCS#1` refer to the complete key - thus the naming convention for this method. .. note:: Importing from the PKCS#8 PrivateKeyInfo encoding format (PEM header 'BEGIN PRIVATE KEY') is not supported. """ crypto = VCrypto.lazy(crypto) if fmt == VX509Format.PEM_BLOCK: heading, data = decode_pem_block(data) if heading == b'RSA PRIVATE KEY': if keytype is None: keytype = 'rsa' elif keytype != 'rsa': raise VCryptoException('Key type mismatch') else: raise VCryptoException('Key type not supported') fmt = VX509Format.DER elif fmt == VX509Format.PEM: if keytype != 'rsa': raise VCryptoException('Key type not supported') if _pyver == 2: data = _s2b(base64.decodestring(_b2s(data))) else: data = base64.decodebytes(data) fmt = VX509Format.DER if fmt == VX509Format.DER: asn1key, len_read = RSAPrivateKey().parse_der(data) if len_read != len(data): raise VCryptoException('Public Key DER data overflow') data = asn1key fmt = VX509Format.ASN1 if fmt == VX509Format.ASN1: if keytype != 'rsa': raise VCryptoException('Key type not supported') data = data.native(deep=True) version, n, e, d, p, q, exp1, exp2, coeff = data[:9] for _param in (e, d, p, q, exp1, exp2, coeff): if not 0 < _param < n: raise VCryptoException('Invalid key parameter(s)') key_params = (n, e, d, p, q) return crypto.num_rsa.key_factory.load(key_params)
def import_public_key(cls, data, fmt=VX509Format.PEM_BLOCK, keytype='rsa', crypto=None): """Imports a PKCS#1 public key. :param data: keydata to import :param fmt: format to import from :type fmt: :class:`VX509Format` constant :param keytype: key type to import (or None) :param keytype: unicode :param crypto: crypto provider (default if None) :type crypto: :class:`versile.crypto.VCrypto` :returns: imported key :rtype: :class:`versile.crypto.VAsymmetricKey` Imports an encoding of the key's :term:`ASN.1` representation defined by :term:`PKCS#1`\, associated with the PEM header 'BEGIN RSA PUBLIC KEY'. .. note:: For the X.509 SubjectPublicKeyInfo encoding format (PEM header 'BEGIN PUBLIC KEY'), see :meth:`import_spki_public_key`\ . """ crypto = VCrypto.lazy(crypto) if fmt == VX509Format.PEM_BLOCK: heading, data = decode_pem_block(data) if heading == b'RSA PUBLIC KEY': if keytype is None: keytype = 'rsa' elif keytype != 'rsa': raise VCryptoException('Key type mismatch') else: raise VCryptoException('Key type not supported') fmt = VX509Format.DER elif fmt == VX509Format.PEM: if keytype != 'rsa': raise VCryptoException('Key type not supported') if _pyver == 2: data = _s2b(base64.decodestring(_b2s(data))) else: data = base64.decodebytes(data) fmt = VX509Format.DER if fmt == VX509Format.DER: asn1key, len_read = RSAPublicKey().parse_der(data) if len_read != len(data): raise VCryptoException('Public Key DER data overflow') data = asn1key fmt = VX509Format.ASN1 if fmt == VX509Format.ASN1: if keytype != 'rsa': raise VCryptoException('Key type not supported') n = data.modulus.native() e = data.publicExponent.native() if not 0 < e < n: raise VCryptoException('Invalid key parameters') key_params = (n, e, None, None, None) return crypto.num_rsa.key_factory.load(key_params)