Example #1
0
    def _do_tdes_test(self, file_name):
        test_vectors = load_tests(("Crypto", "SelfTest", "Cipher", "test_vectors", "TDES"),
                                  file_name,
                                  "TDES CBC KAT",
                                  { "count" : lambda x: int(x) } )
        assert(test_vectors)

        direction = None
        for tv in test_vectors:

            # The test vector file contains some directive lines
            if is_string(tv):
                direction = tv
                continue

            self.description = tv.desc
            if hasattr(tv, "keys"):
                cipher = DES.new(tv.keys, self.des_mode, tv.iv)
            else:
                if tv.key1 != tv.key3:
                    key = tv.key1 + tv.key2 + tv.key3  # Option 3
                else:
                    key = tv.key1 + tv.key2            # Option 2
                cipher = DES3.new(key, self.des3_mode, tv.iv)

            if direction == "[ENCRYPT]":
                self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext)
            elif direction == "[DECRYPT]":
                self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext)
            else:
                assert False
Example #2
0
    def _do_kat_aes_test(self, file_name, segment_size):

        test_vectors = load_test_vectors(("Cipher", "AES"),
                            file_name,
                            "AES CFB%d KAT" % segment_size,
                            { "count" : lambda x: int(x) } )
        if test_vectors is None:
            return

        direction = None
        for tv in test_vectors:

            # The test vector file contains some directive lines
            if is_string(tv):
                direction = tv
                continue

            self.description = tv.desc
            cipher = AES.new(tv.key, AES.MODE_CFB, tv.iv,
                             segment_size=segment_size)
            if direction == "[ENCRYPT]":
                self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext)
            elif direction == "[DECRYPT]":
                self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext)
            else:
                assert False
Example #3
0
    def _do_mct_aes_test(self, file_name):
        test_vectors = load_tests(("Crypto", "SelfTest", "Cipher", "test_vectors", "AES"),
                                  file_name,
                                  "AES Montecarlo",
                                  { "count" : lambda x: int(x) } )
        assert(test_vectors)

        direction = None
        for tv in test_vectors:

            # The test vector file contains some directive lines
            if is_string(tv):
                direction = tv
                continue

            self.description = tv.desc
            cipher = AES.new(tv.key, self.aes_mode, tv.iv)

            if direction == '[ENCRYPT]':
                cts = [ tv.iv ]
                for count in range(1000):
                    cts.append(cipher.encrypt(tv.plaintext))
                    tv.plaintext = cts[-2]
                self.assertEqual(cts[-1], tv.ciphertext)
            elif direction == '[DECRYPT]':
                pts = [ tv.iv]
                for count in range(1000):
                    pts.append(cipher.decrypt(tv.ciphertext))
                    tv.ciphertext = pts[-2]
                self.assertEqual(pts[-1], tv.plaintext)
            else:
                assert False
Example #4
0
    def _do_tdes_test(self, file_name, segment_size):

        test_vectors = load_test_vectors(("Cipher", "TDES"),
                            file_name,
                            "TDES CFB%d KAT" % segment_size,
                            { "count" : lambda x: int(x) } )
        if test_vectors is None:
            return

        direction = None
        for tv in test_vectors:

            # The test vector file contains some directive lines
            if is_string(tv):
                direction = tv
                continue

            self.description = tv.desc
            if hasattr(tv, "keys"):
                cipher = DES.new(tv.keys, DES.MODE_CFB, tv.iv,
                                 segment_size=segment_size)
            else:
                if tv.key1 != tv.key3:
                    key = tv.key1 + tv.key2 + tv.key3  # Option 3
                else:
                    key = tv.key1 + tv.key2            # Option 2
                cipher = DES3.new(key, DES3.MODE_CFB, tv.iv,
                                  segment_size=segment_size)
            if direction == "[ENCRYPT]":
                self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext)
            elif direction == "[DECRYPT]":
                self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext)
            else:
                assert False
Example #5
0
    def _do_tdes_test(self, file_name, segment_size):
        test_vectors = load_tests(("Crypto", "SelfTest", "Cipher", "test_vectors", "TDES"),
                                  file_name,
                                  "AES CFB%d KAT" % segment_size,
                                  { "count" : lambda x: int(x) } )
        assert(test_vectors)

        direction = None
        for tv in test_vectors:

            # The test vector file contains some directive lines
            if is_string(tv):
                direction = tv
                continue

            self.description = tv.desc
            if hasattr(tv, "keys"):
                cipher = DES.new(tv.keys, DES.MODE_CFB, tv.iv,
                                 segment_size=segment_size)
            else:
                if tv.key1 != tv.key3:
                    key = tv.key1 + tv.key2 + tv.key3  # Option 3
                else:
                    key = tv.key1 + tv.key2            # Option 2
                cipher = DES3.new(key, DES3.MODE_CFB, tv.iv,
                                  segment_size=segment_size)
            if direction == "[ENCRYPT]":
                self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext)
            elif direction == "[DECRYPT]":
                self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext)
            else:
                assert False
Example #6
0
    def _do_mct_aes_test(self, file_name, segment_size):

        test_vectors = load_test_vectors(("Cipher", "AES"), file_name,
                                         "AES CFB%d Montecarlo" % segment_size,
                                         {"count": lambda x: int(x)})
        if test_vectors is None:
            return

        assert (segment_size in (8, 128))

        direction = None
        for tv in test_vectors:

            # The test vector file contains some directive lines
            if is_string(tv):
                direction = tv
                continue

            self.description = tv.desc
            cipher = AES.new(tv.key,
                             AES.MODE_CFB,
                             tv.iv,
                             segment_size=segment_size)

            def get_input(input_text, output_seq, j):
                # CFB128
                if segment_size == 128:
                    if j >= 2:
                        return output_seq[-2]
                    return [input_text, tv.iv][j]
                # CFB8
                if j == 0:
                    return input_text
                elif j <= 16:
                    return tv.iv[j - 1:j]
                return output_seq[j - 17]

            if direction == '[ENCRYPT]':
                cts = []
                for j in range(1000):
                    plaintext = get_input(tv.plaintext, cts, j)
                    cts.append(cipher.encrypt(plaintext))
                self.assertEqual(cts[-1], tv.ciphertext)
            elif direction == '[DECRYPT]':
                pts = []
                for j in range(1000):
                    ciphertext = get_input(tv.ciphertext, pts, j)
                    pts.append(cipher.decrypt(ciphertext))
                self.assertEqual(pts[-1], tv.plaintext)
            else:
                assert False
Example #7
0
    def _do_mct_aes_test(self, file_name, segment_size):
        test_vectors = load_tests(("Crypto", "SelfTest", "Cipher", "test_vectors", "AES"),
                                  file_name,
                                  "AES CFB%d Montecarlo" % segment_size,
                                  { "count" : lambda x: int(x) } )
        assert(test_vectors)
        assert(segment_size in (8, 128))

        direction = None
        for tv in test_vectors:

            # The test vector file contains some directive lines
            if is_string(tv):
                direction = tv
                continue

            self.description = tv.desc
            cipher = AES.new(tv.key, AES.MODE_CFB, tv.iv,
                             segment_size=segment_size)

            def get_input(input_text, output_seq, j):
                # CFB128
                if segment_size == 128:
                    if j >= 2:
                        return output_seq[-2]
                    return [input_text, tv.iv][j]
                # CFB8
                if j == 0:
                    return input_text
                elif j <= 16:
                    return tv.iv[j - 1:j]
                return output_seq[j - 17]

            if direction == '[ENCRYPT]':
                cts = []
                for j in range(1000):
                    plaintext = get_input(tv.plaintext, cts, j)
                    cts.append(cipher.encrypt(plaintext))
                self.assertEqual(cts[-1], tv.ciphertext)
            elif direction == '[DECRYPT]':
                pts = []
                for j in range(1000):
                    ciphertext = get_input(tv.ciphertext, pts, j)
                    pts.append(cipher.decrypt(ciphertext))
                self.assertEqual(pts[-1], tv.plaintext)
            else:
                assert False
Example #8
0
    def _do_kat_aes_test(self, file_name):
        test_vectors = load_tests(("Crypto", "SelfTest", "Cipher", "test_vectors", "AES"),
                                  file_name,
                                  "AES KAT",
                                  { "count" : lambda x: int(x) } )
        assert(test_vectors)

        direction = None
        for tv in test_vectors:

            # The test vector file contains some directive lines
            if is_string(tv):
                direction = tv
                continue

            self.description = tv.desc

            cipher = AES.new(tv.key, self.aes_mode, tv.iv)
            if direction == "[ENCRYPT]":
                self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext)
            elif direction == "[DECRYPT]":
                self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext)
            else:
                assert False
Example #9
0
    def _do_kat_aes_test(self, file_name, segment_size):
        test_vectors = load_tests(("Crypto", "SelfTest", "Cipher", "test_vectors", "AES"),
                                  file_name,
                                  "AES CFB%d KAT" % segment_size,
                                  { "count" : lambda x: int(x) } )
        assert(test_vectors)

        direction = None
        for tv in test_vectors:

            # The test vector file contains some directive lines
            if is_string(tv):
                direction = tv
                continue

            self.description = tv.desc
            cipher = AES.new(tv.key, AES.MODE_CFB, tv.iv,
                             segment_size=segment_size)
            if direction == "[ENCRYPT]":
                self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext)
            elif direction == "[DECRYPT]":
                self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext)
            else:
                assert False
Example #10
0
    def export_key(self, **kwargs):
        """Export this ECC key.

        Args:
          format (string):
            The format to use for encoding the key:

            - ``'DER'``. The key will be encoded in ASN.1 DER format (binary).
              For a public key, the ASN.1 ``subjectPublicKeyInfo`` structure
              defined in `RFC5480`_ will be used.
              For a private key, the ASN.1 ``ECPrivateKey`` structure defined
              in `RFC5915`_ is used instead (possibly within a PKCS#8 envelope,
              see the ``use_pkcs8`` flag below).
            - ``'PEM'``. The key will be encoded in a PEM_ envelope (ASCII).
            - ``'OpenSSH'``. The key will be encoded in the OpenSSH_ format
              (ASCII, public keys only).

          passphrase (byte string or string):
            The passphrase to use for protecting the private key.

          use_pkcs8 (boolean):
            Only relevant for private keys.

            If ``True`` (default and recommended), the `PKCS#8`_ representation
            will be used.

            If ``False``, the much weaker `PEM encryption`_ mechanism will be used.

          protection (string):
            When a private key is exported with password-protection
            and PKCS#8 (both ``DER`` and ``PEM`` formats), this parameter MUST be
            present and be a valid algorithm supported by :mod:`Crypto.IO.PKCS8`.
            It is recommended to use ``PBKDF2WithHMAC-SHA1AndAES128-CBC``.

          compress (boolean):
            If ``True``, a more compact representation of the public key
            with the X-coordinate only is used.

            If ``False`` (default), the full public key will be exported.

        .. warning::
            If you don't provide a passphrase, the private key will be
            exported in the clear!

        .. note::
            When exporting a private key with password-protection and `PKCS#8`_
            (both ``DER`` and ``PEM`` formats), any extra parameters
            to ``export_key()`` will be passed to :mod:`Crypto.IO.PKCS8`.

        .. _PEM:        http://www.ietf.org/rfc/rfc1421.txt
        .. _`PEM encryption`: http://www.ietf.org/rfc/rfc1423.txt
        .. _`PKCS#8`:   http://www.ietf.org/rfc/rfc5208.txt
        .. _OpenSSH:    http://www.openssh.com/txt/rfc5656.txt
        .. _RFC5480:    https://tools.ietf.org/html/rfc5480
        .. _RFC5915:    http://www.ietf.org/rfc/rfc5915.txt

        Returns:
            A multi-line string (for PEM and OpenSSH) or bytes (for DER) with the encoded key.
        """

        args = kwargs.copy()
        ext_format = args.pop("format")
        if ext_format not in ("PEM", "DER", "OpenSSH"):
            raise ValueError("Unknown format '%s'" % ext_format)

        compress = args.pop("compress", False)

        if self.has_private():
            passphrase = args.pop("passphrase", None)
            if is_string(passphrase):
                passphrase = tobytes(passphrase)
                if not passphrase:
                    raise ValueError("Empty passphrase")
            use_pkcs8 = args.pop("use_pkcs8", True)
            if ext_format == "PEM":
                if use_pkcs8:
                    if passphrase:
                        return self._export_private_encrypted_pkcs8_in_clear_pem(
                            passphrase, **args)
                    else:
                        return self._export_private_clear_pkcs8_in_clear_pem()
                else:
                    return self._export_private_pem(passphrase, **args)
            elif ext_format == "DER":
                # DER
                if passphrase and not use_pkcs8:
                    raise ValueError(
                        "Private keys can only be encrpyted with DER using PKCS#8"
                    )
                if use_pkcs8:
                    return self._export_pkcs8(passphrase=passphrase, **args)
                else:
                    return self._export_private_der()
            else:
                raise ValueError(
                    "Private keys cannot be exported in OpenSSH format")
        else:  # Public key
            if args:
                raise ValueError("Unexpected parameters: '%s'" % args)
            if ext_format == "PEM":
                return self._export_public_pem(compress)
            elif ext_format == "DER":
                return self._export_subjectPublicKeyInfo(compress)
            else:
                return self._export_openssh(compress)
Example #11
0
    def export_key(self, **kwargs):
        """Export this ECC key.

        Args:
          format (string):
            The format to use for encoding the key:

            - ``'DER'``. The key will be encoded in ASN.1 DER format (binary).
              For a public key, the ASN.1 ``subjectPublicKeyInfo`` structure
              defined in `RFC5480`_ will be used.
              For a private key, the ASN.1 ``ECPrivateKey`` structure defined
              in `RFC5915`_ is used instead (possibly within a PKCS#8 envelope,
              see the ``use_pkcs8`` flag below).
            - ``'PEM'``. The key will be encoded in a PEM_ envelope (ASCII).
            - ``'OpenSSH'``. The key will be encoded in the OpenSSH_ format
              (ASCII, public keys only).

          passphrase (byte string or string):
            The passphrase to use for protecting the private key.

          use_pkcs8 (boolean):
            Only relevant for private keys.

            If ``True`` (default and recommended), the `PKCS#8`_ representation
            will be used.

            If ``False``, the much weaker `PEM encryption`_ mechanism will be used.

          protection (string):
            When a private key is exported with password-protection
            and PKCS#8 (both ``DER`` and ``PEM`` formats), this parameter MUST be
            present and be a valid algorithm supported by :mod:`Crypto.IO.PKCS8`.
            It is recommended to use ``PBKDF2WithHMAC-SHA1AndAES128-CBC``.

          compress (boolean):
            If ``True``, a more compact representation of the public key
            with the X-coordinate only is used.

            If ``False`` (default), the full public key will be exported.

        .. warning::
            If you don't provide a passphrase, the private key will be
            exported in the clear!

        .. note::
            When exporting a private key with password-protection and `PKCS#8`_
            (both ``DER`` and ``PEM`` formats), any extra parameters
            to ``export_key()`` will be passed to :mod:`Crypto.IO.PKCS8`.

        .. _PEM:        http://www.ietf.org/rfc/rfc1421.txt
        .. _`PEM encryption`: http://www.ietf.org/rfc/rfc1423.txt
        .. _`PKCS#8`:   http://www.ietf.org/rfc/rfc5208.txt
        .. _OpenSSH:    http://www.openssh.com/txt/rfc5656.txt
        .. _RFC5480:    https://tools.ietf.org/html/rfc5480
        .. _RFC5915:    http://www.ietf.org/rfc/rfc5915.txt

        Returns:
            A multi-line string (for PEM and OpenSSH) or bytes (for DER) with the encoded key.
        """

        args = kwargs.copy()
        ext_format = args.pop("format")
        if ext_format not in ("PEM", "DER", "OpenSSH"):
            raise ValueError("Unknown format '%s'" % ext_format)

        compress = args.pop("compress", False)

        if self.has_private():
            passphrase = args.pop("passphrase", None)
            if is_string(passphrase):
                passphrase = tobytes(passphrase)
                if not passphrase:
                    raise ValueError("Empty passphrase")
            use_pkcs8 = args.pop("use_pkcs8", True)
            if ext_format == "PEM":
                if use_pkcs8:
                    if passphrase:
                        return self._export_private_encrypted_pkcs8_in_clear_pem(passphrase, **args)
                    else:
                        return self._export_private_clear_pkcs8_in_clear_pem()
                else:
                    return self._export_private_pem(passphrase, **args)
            elif ext_format == "DER":
                # DER
                if passphrase and not use_pkcs8:
                    raise ValueError("Private keys can only be encrpyted with DER using PKCS#8")
                if use_pkcs8:
                    return self._export_pkcs8(passphrase=passphrase, **args)
                else:
                    return self._export_private_der()
            else:
                raise ValueError("Private keys cannot be exported in OpenSSH format")
        else:  # Public key
            if args:
                raise ValueError("Unexpected parameters: '%s'" % args)
            if ext_format == "PEM":
                return self._export_public_pem(compress)
            elif ext_format == "DER":
                return self._export_subjectPublicKeyInfo(compress)
            else:
                return self._export_openssh(compress)