Example #1
0
    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)
Example #2
0
    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
Example #3
0
 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)
Example #4
0
    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)
Example #5
0
    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
Example #6
0
    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
Example #7
0
    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)
Example #8
0
    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)