Esempio n. 1
0
def EMSA_PKCS1_V1_5_ENCODE(hash, emLen):
    """
    Implement the ``EMSA-PKCS1-V1_5-ENCODE`` function, as defined
    in PKCS#1 v2.1 (RFC3447, 9.2).

    ``EMSA-PKCS1-V1_5-ENCODE`` actually accepts the message ``M`` as input,
    and hash it internally. Here, we expect that the message has already
    been hashed instead.

    :Parameters:
     hash : hash object
            The hash object that holds the digest of the message being signed.
     emLen : int
            The length the final encoding must have, in bytes.

    :attention: the early standard (RFC2313) stated that ``DigestInfo``
        had to be BER-encoded. This means that old signatures
        might have length tags in indefinite form, which
        is not supported in DER. Such encoding cannot be
        reproduced by this function.

    :attention: the same standard defined ``DigestAlgorithm`` to be
        of ``AlgorithmIdentifier`` type, where the PARAMETERS
        item is optional. Encodings for ``MD2/4/5`` without
        ``PARAMETERS`` cannot be reproduced by this function.

    :Return: An ``emLen`` byte long string that encodes the hash.
    """

    # First, build the ASN.1 DER object DigestInfo:
    #
    #   DigestInfo ::= SEQUENCE {
    #       digestAlgorithm AlgorithmIdentifier,
    #       digest OCTET STRING
    #   }
    #
    # where digestAlgorithm identifies the hash function and shall be an
    # algorithm ID with an OID in the set PKCS1-v1-5DigestAlgorithms.
    #
    #   PKCS1-v1-5DigestAlgorithms    ALGORITHM-IDENTIFIER ::= {
    #       { OID id-md2 PARAMETERS NULL    }|
    #       { OID id-md5 PARAMETERS NULL    }|
    #       { OID id-sha1 PARAMETERS NULL   }|
    #       { OID id-sha256 PARAMETERS NULL }|
    #       { OID id-sha384 PARAMETERS NULL }|
    #       { OID id-sha512 PARAMETERS NULL }
    #   }
    #
    digestAlgo = DerSequence([hash.oid, DerNull().encode()])
    digest = DerOctetString(hash.digest())
    digestInfo = DerSequence([digestAlgo.encode(), digest.encode()]).encode()

    # We need at least 11 bytes for the remaining data: 3 fixed bytes and
    # at least 8 bytes of padding).
    if emLen < len(digestInfo) + 11:
        raise ValueError(
            "Selected hash algorith has a too long digest (%d bytes)." %
            len(digest))
    PS = bchr(0xFF) * (emLen - len(digestInfo) - 3)
    return b("\x00\x01") + PS + bchr(0x00) + digestInfo
Esempio n. 2
0
 def testDecode4(self):
     # One very long integer
     der = DerSequence()
     der.decode(
         b('0\x82\x01\x05') +
         b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
     self.assertEqual(len(der), 1)
     self.assertEqual(der[0], 2**2048)
Esempio n. 3
0
 def testDecode8(self):
     # Only 2 other types
     der = DerSequence()
     der.decode(b('0\x06\x24\x02\xb6\x63\x12\x00'))
     self.assertEqual(len(der), 2)
     self.assertEqual(der[0], b('\x24\x02\xb6\x63'))
     self.assertEqual(der[1], b('\x12\x00'))
Esempio n. 4
0
 def testEncode4(self):
     # One very long integer
     der = DerSequence()
     der.append(2**2048)
     self.assertEqual(
         der.encode(),
         b('0\x82\x01\x05') +
         b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +
         b('\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
Esempio n. 5
0
 def testErrDecode4(self):
     # Wrong integer format
     der = DerSequence()
     # Multi-byte encoding for zero
     #self.assertRaises(ValueError, der.decode, '\x30\x04\x02\x02\x00\x00')
     # Negative integer
     self.assertRaises(ValueError, der.decode, b('\x30\x04\x02\x01\xFF'))
Esempio n. 6
0
 def testDecode6(self):
     # Two integers
     der = DerSequence()
     der.decode(b('0\x08\x02\x02\x01\x80\x02\x02\x00\xff'))
     self.assertEqual(len(der), 2)
     self.assertEqual(der[0], 0x180)
     self.assertEqual(der[1], 0xFF)
Esempio n. 7
0
 def testDecode7(self):
     # One integer and 2 other types
     der = DerSequence()
     der.decode(b('0\x0A\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00'))
     self.assertEqual(len(der), 3)
     self.assertEqual(der[0], 0x180)
     self.assertEqual(der[1], b('\x24\x02\xb6\x63'))
     self.assertEqual(der[2], b('\x12\x00'))
Esempio n. 8
0
 def testEncode6(self):
     # One integer and another type (no matter what it is)
     der = DerSequence()
     der.append(0x180)
     der.append(b('\x00\x02\x00\x00'))
     self.assertEqual(der.encode(),
                      b('0\x08\x02\x02\x01\x80\x00\x02\x00\x00'))
     self.assertFalse(der.hasOnlyInts())
Esempio n. 9
0
 def testErrDecode3(self):
     # Wrong length format
     der = DerSequence()
     self.assertRaises(ValueError, der.decode,
                       b('\x30\x04\x02\x01\x01\x00'))
     self.assertRaises(ValueError, der.decode,
                       b('\x30\x81\x03\x02\x01\x01'))
     self.assertRaises(ValueError, der.decode,
                       b('\x30\x04\x02\x81\x01\x01'))
Esempio n. 10
0
 def testEncode1(self):
     # Empty sequence
     der = DerSequence()
     self.assertEqual(der.encode(), b('0\x00'))
     self.assertFalse(der.hasOnlyInts())
     # One single-byte integer (zero)
     der.append(0)
     self.assertEqual(der.encode(), b('0\x03\x02\x01\x00'))
     self.assertTrue(der.hasOnlyInts())
     # Invariant
     self.assertEqual(der.encode(), b('0\x03\x02\x01\x00'))
Esempio n. 11
0
 def testDecode1(self):
     # Empty sequence
     der = DerSequence()
     der.decode(b('0\x00'))
     self.assertEqual(len(der), 0)
     # One single-byte integer (zero)
     der.decode(b('0\x03\x02\x01\x00'))
     self.assertEqual(len(der), 1)
     self.assertEqual(der[0], 0)
     # Invariant
     der.decode(b('0\x03\x02\x01\x00'))
     self.assertEqual(len(der), 1)
     self.assertEqual(der[0], 0)
Esempio n. 12
0
    def _importKeyDER(self, externKey):
        """Import an RSA key (public or private half), encoded in DER form."""

        try:

            der = DerSequence()
            der.decode(externKey, True)

            # Try PKCS#1 first, for a private key
            if len(der) == 9 and der.hasOnlyInts() and der[0] == 0:
                # ASN.1 RSAPrivateKey element
                del der[
                    6:]  # Remove d mod (p-1), d mod (q-1), and q^{-1} mod p
                der.append(inverse(der[4], der[5]))  # Add p^{-1} mod q
                del der[0]  # Remove version
                return self.construct(der[:])

            # Keep on trying PKCS#1, but now for a public key
            if len(der) == 2:
                # The DER object is an RSAPublicKey SEQUENCE with two elements
                if der.hasOnlyInts():
                    return self.construct(der[:])
                # The DER object is a SubjectPublicKeyInfo SEQUENCE with two elements:
                # an 'algorithm' (or 'algorithmIdentifier') SEQUENCE and a 'subjectPublicKey' BIT STRING.
                # 'algorithm' takes the value given a few lines above.
                # 'subjectPublicKey' encapsulates the actual ASN.1 RSAPublicKey element.
                if der[0] == algorithmIdentifier:
                    bitmap = DerObject()
                    bitmap.decode(der[1], True)
                    if bitmap.isType('BIT STRING') and bord(
                            bitmap.payload[0]) == 0x00:
                        der.decode(bitmap.payload[1:], True)
                        if len(der) == 2 and der.hasOnlyInts():
                            return self.construct(der[:])

            # Try unencrypted PKCS#8
            if der[0] == 0:
                # The second element in the SEQUENCE is algorithmIdentifier.
                # It must say RSA (see above for description).
                if der[1] == algorithmIdentifier:
                    privateKey = DerObject()
                    privateKey.decode(der[2], True)
                    if privateKey.isType('OCTET STRING'):
                        return self._importKeyDER(privateKey.payload)

        except ValueError as IndexError:
            pass

        raise ValueError("RSA key format is not supported")
Esempio n. 13
0
 def testEncode6(self):
     # Two integers
     der = DerSequence()
     der.append(0x180)
     der.append(0xFF)
     self.assertEqual(der.encode(),
                      b('0\x08\x02\x02\x01\x80\x02\x02\x00\xff'))
     self.assertTrue(der.hasOnlyInts())
     #
     der.append(0x01)
     der[1:] = [9, 8]
     self.assertEqual(len(der), 3)
     self.assertEqual(der[1:], [9, 8])
     self.assertEqual(der[1:-1], [9])
     self.assertEqual(der.encode(),
                      b('0\x0A\x02\x02\x01\x80\x02\x01\x09\x02\x01\x08'))
Esempio n. 14
0
 def testEncode2(self):
     # One single-byte integer (non-zero)
     der = DerSequence()
     der.append(127)
     self.assertEqual(der.encode(), b('0\x03\x02\x01\x7f'))
     # Indexing
     der[0] = 1
     self.assertEqual(len(der), 1)
     self.assertEqual(der[0], 1)
     self.assertEqual(der[-1], 1)
     self.assertEqual(der.encode(), b('0\x03\x02\x01\x01'))
     #
     der[:] = [1]
     self.assertEqual(len(der), 1)
     self.assertEqual(der[0], 1)
     self.assertEqual(der.encode(), b('0\x03\x02\x01\x01'))
Esempio n. 15
0
    def exportKey(self, format='PEM', passphrase=None, pkcs=1):
        """Export this RSA key.

        :Parameter format: The format to use for wrapping the key.

            - *'DER'*. Binary encoding, always unencrypted.
            - *'PEM'*. Textual encoding, done according to `RFC1421`_/`RFC1423`_.
              Unencrypted (default) or encrypted.
            - *'OpenSSH'*. Textual encoding, done according to OpenSSH specification.
              Only suitable for public keys (not private keys).
        :Type format: string

        :Parameter passphrase: In case of PEM, the pass phrase to derive the encryption key from.
        :Type passphrase: string 

        :Parameter pkcs: The PKCS standard to follow for assembling the key.
         You have two choices:

          - with **1**, the public key is embedded into an X.509 `SubjectPublicKeyInfo` DER SEQUENCE.
            The private key is embedded into a `PKCS#1`_ `RSAPrivateKey` DER SEQUENCE.
            This mode is the default.
          - with **8**, the private key is embedded into a `PKCS#8`_ `PrivateKeyInfo` DER SEQUENCE.
            This mode is not available for public keys.

         PKCS standards are not relevant for the *OpenSSH* format.
        :Type pkcs: integer

        :Return: A byte string with the encoded public or private half.
        :Raise ValueError:
            When the format is unknown.

        .. _RFC1421:    http://www.ietf.org/rfc/rfc1421.txt
        .. _RFC1423:    http://www.ietf.org/rfc/rfc1423.txt
        .. _`PKCS#1`:   http://www.ietf.org/rfc/rfc3447.txt
        .. _`PKCS#8`:   http://www.ietf.org/rfc/rfc5208.txt
        """
        if passphrase is not None:
            passphrase = tobytes(passphrase)
        if format == 'OpenSSH':
            eb = long_to_bytes(self.e)
            nb = long_to_bytes(self.n)
            if bord(eb[0]) & 0x80: eb = bchr(0x00) + eb
            if bord(nb[0]) & 0x80: nb = bchr(0x00) + nb
            keyparts = ['ssh-rsa', eb, nb]
            keystring = ''.join(
                [struct.pack(">I", len(kp)) + kp for kp in keyparts])
            return 'ssh-rsa ' + binascii.b2a_base64(keystring)[:-1]

        # DER format is always used, even in case of PEM, which simply
        # encodes it into BASE64.
        der = DerSequence()
        if self.has_private():
            keyType = {1: 'RSA PRIVATE', 8: 'PRIVATE'}[pkcs]
            der[:] = [
                0, self.n, self.e, self.d, self.p, self.q,
                self.d % (self.p - 1), self.d % (self.q - 1),
                inverse(self.q, self.p)
            ]
            if pkcs == 8:
                derkey = der.encode()
                der = DerSequence([0])
                der.append(algorithmIdentifier)
                der.append(DerObject('OCTET STRING', derkey).encode())
        else:
            keyType = "PUBLIC"
            der.append(algorithmIdentifier)
            bitmap = DerObject('BIT STRING')
            derPK = DerSequence([self.n, self.e])
            bitmap.payload = bchr(0x00) + derPK.encode()
            der.append(bitmap.encode())
        if format == 'DER':
            return der.encode()
        if format == 'PEM':
            pem = b("-----BEGIN " + keyType + " KEY-----\n")
            objenc = None
            if passphrase and keyType.endswith('PRIVATE'):
                # We only support 3DES for encryption
                import Crypro.Hash.MD5
                from Crypro.Cipher import DES3
                from Crypro.Protocol.KDF import PBKDF1
                salt = self._randfunc(8)
                key = PBKDF1(passphrase, salt, 16, 1, Crypro.Hash.MD5)
                key += PBKDF1(key + passphrase, salt, 8, 1, Crypro.Hash.MD5)
                objenc = DES3.new(key, Crypro.Cipher.DES3.MODE_CBC, salt)
                pem += b('Proc-Type: 4,ENCRYPTED\n')
                pem += b('DEK-Info: DES-EDE3-CBC,') + binascii.b2a_hex(
                    salt).upper() + b('\n\n')

            binaryKey = der.encode()
            if objenc:
                # Add PKCS#7-like padding
                padding = objenc.block_size - len(
                    binaryKey) % objenc.block_size
                binaryKey = objenc.encrypt(binaryKey + bchr(padding) * padding)

            # Each BASE64 line can take up to 64 characters (=48 bytes of data)
            chunks = [
                binascii.b2a_base64(binaryKey[i:i + 48])
                for i in range(0, len(binaryKey), 48)
            ]
            pem += b('').join(chunks)
            pem += b("-----END " + keyType + " KEY-----")
            return pem
        return ValueError(
            "Unknown key format '%s'. Cannot export the RSA key." % format)
Esempio n. 16
0
 def testDecode3(self):
     # One multi-byte integer (non-zero)
     der = DerSequence()
     der.decode(b('0\x04\x02\x02\x01\x80'))
     self.assertEqual(len(der), 1)
     self.assertEqual(der[0], 0x180)
Esempio n. 17
0
 def testEncode5(self):
     # One single-byte integer (looks negative)
     der = DerSequence()
     der.append(0xFF)
     self.assertEqual(der.encode(), b('0\x04\x02\x02\x00\xff'))
Esempio n. 18
0
 def testEncode3(self):
     # One multi-byte integer (non-zero)
     der = DerSequence()
     der.append(0x180)
     self.assertEqual(der.encode(), b('0\x04\x02\x02\x01\x80'))
Esempio n. 19
0
 def testErrDecode2(self):
     # Wrong payload type
     der = DerSequence()
     self.assertRaises(ValueError, der.decode, b('\x30\x00\x00'), True)
Esempio n. 20
0
 def testErrDecode1(self):
     # Not a sequence
     der = DerSequence()
     self.assertRaises(ValueError, der.decode, b(''))
     self.assertRaises(ValueError, der.decode, b('\x00'))
     self.assertRaises(ValueError, der.decode, b('\x30'))
Esempio n. 21
0
 def testDecode2(self):
     # One single-byte integer (non-zero)
     der = DerSequence()
     der.decode(b('0\x03\x02\x01\x7f'))
     self.assertEqual(len(der), 1)
     self.assertEqual(der[0], 127)
Esempio n. 22
0
            # This is probably a DER encoded key
            return self._importKeyDER(externKey)

        raise ValueError("RSA key format is not supported")


#: This is the ASN.1 DER object that qualifies an algorithm as
#: compliant to PKCS#1 (that is, the standard RSA).
# It is found in all 'algorithm' fields (also called 'algorithmIdentifier').
# It is a SEQUENCE with the oid assigned to RSA and with its parameters (none).
#   0x06 0x09   OBJECT IDENTIFIER, 9 bytes of payload
#     0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x01 0x01
#               rsaEncryption (1 2 840 113549 1 1 1) (PKCS #1)
#   0x05 0x00   NULL
algorithmIdentifier = DerSequence(
    [b('\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01'),
     DerNull().encode()]).encode()

_impl = RSAImplementation()
#:
#: Randomly generate a fresh, new RSA key object.
#:
#: See `RSAImplementation.generate`.
#:
generate = _impl.generate
#:
#: Construct an RSA key object from a tuple of valid RSA components.
#:
#: See `RSAImplementation.construct`.
#:
construct = _impl.construct
Esempio n. 23
0
 def testDecode5(self):
     # One single-byte integer (looks negative)
     der = DerSequence()
     der.decode(b('0\x04\x02\x02\x00\xff'))
     self.assertEqual(len(der), 1)
     self.assertEqual(der[0], 0xFF)