slight update

This commit is contained in:
2024-12-01 04:19:04 +09:00
parent 00b0afd17a
commit 4dbe1bee11
3130 changed files with 508084 additions and 0 deletions

View File

@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
#
# SelfTest/PublicKey/__init__.py: Self-test for public key crypto
#
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
#
# ===================================================================
# The contents of this file are dedicated to the public domain. To
# the extent that dedication to the public domain is not available,
# everyone is granted a worldwide, perpetual, royalty-free,
# non-exclusive license to exercise all rights associated with the
# contents of this file for any purpose whatsoever.
# No rights are reserved.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# ===================================================================
"""Self-test for public-key crypto"""
import unittest
from Crypto.SelfTest.PublicKey import (test_DSA, test_RSA,
test_ECC_NIST,
test_ECC_Ed25519,
test_ECC_Curve25519,
test_ECC_Ed448,
test_ECC_Curve448,
test_import_DSA, test_import_RSA,
test_import_ECC, test_ElGamal,
test_import_Curve25519,
test_import_Curve448)
def get_tests(config={}):
tests = []
tests += test_DSA.get_tests(config=config)
tests += test_RSA.get_tests(config=config)
tests += test_ECC_NIST.get_tests(config=config)
tests += test_ECC_Ed25519.get_tests(config=config)
tests += test_ECC_Curve25519.get_tests(config=config)
tests += test_ECC_Ed448.get_tests(config=config)
tests += test_ECC_Curve448.get_tests(config=config)
tests += test_import_DSA.get_tests(config=config)
tests += test_import_RSA.get_tests(config=config)
tests += test_import_ECC.get_tests(config=config)
tests += test_import_Curve25519.get_tests(config=config)
tests += test_import_Curve448.get_tests(config=config)
tests += test_ElGamal.get_tests(config=config)
return tests
if __name__ == '__main__':
def suite():
return unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')

View File

@ -0,0 +1,247 @@
# -*- coding: utf-8 -*-
#
# SelfTest/PublicKey/test_DSA.py: Self-test for the DSA primitive
#
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
#
# ===================================================================
# The contents of this file are dedicated to the public domain. To
# the extent that dedication to the public domain is not available,
# everyone is granted a worldwide, perpetual, royalty-free,
# non-exclusive license to exercise all rights associated with the
# contents of this file for any purpose whatsoever.
# No rights are reserved.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# ===================================================================
"""Self-test suite for Crypto.PublicKey.DSA"""
import os
from Crypto.Util.py3compat import *
import unittest
from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex
def _sws(s):
"""Remove whitespace from a text or byte string"""
if isinstance(s,str):
return "".join(s.split())
else:
return b("").join(s.split())
class DSATest(unittest.TestCase):
# Test vector from "Appendix 5. Example of the DSA" of
# "Digital Signature Standard (DSS)",
# U.S. Department of Commerce/National Institute of Standards and Technology
# FIPS 186-2 (+Change Notice), 2000 January 27.
# http://csrc.nist.gov/publications/fips/fips186-2/fips186-2-change1.pdf
y = _sws("""19131871 d75b1612 a819f29d 78d1b0d7 346f7aa7 7bb62a85
9bfd6c56 75da9d21 2d3a36ef 1672ef66 0b8c7c25 5cc0ec74
858fba33 f44c0669 9630a76b 030ee333""")
g = _sws("""626d0278 39ea0a13 413163a5 5b4cb500 299d5522 956cefcb
3bff10f3 99ce2c2e 71cb9de5 fa24babf 58e5b795 21925c9c
c42e9f6f 464b088c c572af53 e6d78802""")
p = _sws("""8df2a494 492276aa 3d25759b b06869cb eac0d83a fb8d0cf7
cbb8324f 0d7882e5 d0762fc5 b7210eaf c2e9adac 32ab7aac
49693dfb f83724c2 ec0736ee 31c80291""")
q = _sws("""c773218c 737ec8ee 993b4f2d ed30f48e dace915f""")
x = _sws("""2070b322 3dba372f de1c0ffc 7b2e3b49 8b260614""")
k = _sws("""358dad57 1462710f 50e254cf 1a376b2b deaadfbf""")
k_inverse = _sws("""0d516729 8202e49b 4116ac10 4fc3f415 ae52f917""")
m = b2a_hex(b("abc"))
m_hash = _sws("""a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d""")
r = _sws("""8bac1ab6 6410435c b7181f95 b16ab97c 92b341c0""")
s = _sws("""41e2345f 1f56df24 58f426d1 55b4ba2d b6dcd8c8""")
def setUp(self):
global DSA, Random, bytes_to_long, size
from Crypto.PublicKey import DSA
from Crypto import Random
from Crypto.Util.number import bytes_to_long, inverse, size
self.dsa = DSA
def test_generate_1arg(self):
"""DSA (default implementation) generated key (1 argument)"""
dsaObj = self.dsa.generate(1024)
self._check_private_key(dsaObj)
pub = dsaObj.public_key()
self._check_public_key(pub)
def test_generate_2arg(self):
"""DSA (default implementation) generated key (2 arguments)"""
dsaObj = self.dsa.generate(1024, Random.new().read)
self._check_private_key(dsaObj)
pub = dsaObj.public_key()
self._check_public_key(pub)
def test_construct_4tuple(self):
"""DSA (default implementation) constructed key (4-tuple)"""
(y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)]
dsaObj = self.dsa.construct((y, g, p, q))
self._test_verification(dsaObj)
def test_construct_5tuple(self):
"""DSA (default implementation) constructed key (5-tuple)"""
(y, g, p, q, x) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q, self.x)]
dsaObj = self.dsa.construct((y, g, p, q, x))
self._test_signing(dsaObj)
self._test_verification(dsaObj)
def test_construct_bad_key4(self):
(y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)]
tup = (y, g, p+1, q)
self.assertRaises(ValueError, self.dsa.construct, tup)
tup = (y, g, p, q+1)
self.assertRaises(ValueError, self.dsa.construct, tup)
tup = (y, 1, p, q)
self.assertRaises(ValueError, self.dsa.construct, tup)
def test_construct_bad_key5(self):
(y, g, p, q, x) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q, self.x)]
tup = (y, g, p, q, x+1)
self.assertRaises(ValueError, self.dsa.construct, tup)
tup = (y, g, p, q, q+10)
self.assertRaises(ValueError, self.dsa.construct, tup)
def _check_private_key(self, dsaObj):
# Check capabilities
self.assertEqual(1, dsaObj.has_private())
self.assertEqual(1, dsaObj.can_sign())
self.assertEqual(0, dsaObj.can_encrypt())
# Sanity check key data
self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q
self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bits
self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of p-1
self.assertEqual(dsaObj.y, pow(dsaObj.g, dsaObj.x, dsaObj.p)) # y == g**x mod p
self.assertEqual(1, 0 < dsaObj.x < dsaObj.q) # 0 < x < q
def _check_public_key(self, dsaObj):
k = bytes_to_long(a2b_hex(self.k))
m_hash = bytes_to_long(a2b_hex(self.m_hash))
# Check capabilities
self.assertEqual(0, dsaObj.has_private())
self.assertEqual(1, dsaObj.can_sign())
self.assertEqual(0, dsaObj.can_encrypt())
# Check that private parameters are all missing
self.assertEqual(0, hasattr(dsaObj, 'x'))
# Sanity check key data
self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q
self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bits
self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of p-1
# Public-only key objects should raise an error when .sign() is called
self.assertRaises(TypeError, dsaObj._sign, m_hash, k)
# Check __eq__ and __ne__
self.assertEqual(dsaObj.public_key() == dsaObj.public_key(),True) # assert_
self.assertEqual(dsaObj.public_key() != dsaObj.public_key(),False) # assertFalse
self.assertEqual(dsaObj.public_key(), dsaObj.publickey())
def _test_signing(self, dsaObj):
k = bytes_to_long(a2b_hex(self.k))
m_hash = bytes_to_long(a2b_hex(self.m_hash))
r = bytes_to_long(a2b_hex(self.r))
s = bytes_to_long(a2b_hex(self.s))
(r_out, s_out) = dsaObj._sign(m_hash, k)
self.assertEqual((r, s), (r_out, s_out))
def _test_verification(self, dsaObj):
m_hash = bytes_to_long(a2b_hex(self.m_hash))
r = bytes_to_long(a2b_hex(self.r))
s = bytes_to_long(a2b_hex(self.s))
self.assertTrue(dsaObj._verify(m_hash, (r, s)))
self.assertFalse(dsaObj._verify(m_hash + 1, (r, s)))
def test_repr(self):
(y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)]
dsaObj = self.dsa.construct((y, g, p, q))
repr(dsaObj)
class DSADomainTest(unittest.TestCase):
def test_domain1(self):
"""Verify we can generate new keys in a given domain"""
dsa_key_1 = DSA.generate(1024)
domain_params = dsa_key_1.domain()
dsa_key_2 = DSA.generate(1024, domain=domain_params)
self.assertEqual(dsa_key_1.p, dsa_key_2.p)
self.assertEqual(dsa_key_1.q, dsa_key_2.q)
self.assertEqual(dsa_key_1.g, dsa_key_2.g)
self.assertEqual(dsa_key_1.domain(), dsa_key_2.domain())
def _get_weak_domain(self):
from Crypto.Math.Numbers import Integer
from Crypto.Math import Primality
p = Integer(4)
while p.size_in_bits() != 1024 or Primality.test_probable_prime(p) != Primality.PROBABLY_PRIME:
q1 = Integer.random(exact_bits=80)
q2 = Integer.random(exact_bits=80)
q = q1 * q2
z = Integer.random(exact_bits=1024-160)
p = z * q + 1
h = Integer(2)
g = 1
while g == 1:
g = pow(h, z, p)
h += 1
return (p, q, g)
def test_generate_error_weak_domain(self):
"""Verify that domain parameters with composite q are rejected"""
domain_params = self._get_weak_domain()
self.assertRaises(ValueError, DSA.generate, 1024, domain=domain_params)
def test_construct_error_weak_domain(self):
"""Verify that domain parameters with composite q are rejected"""
from Crypto.Math.Numbers import Integer
p, q, g = self._get_weak_domain()
y = pow(g, 89, p)
self.assertRaises(ValueError, DSA.construct, (y, g, p, q))
def get_tests(config={}):
tests = []
tests += list_test_cases(DSATest)
tests += list_test_cases(DSADomainTest)
return tests
if __name__ == '__main__':
suite = lambda: unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')
# vim:set ts=4 sw=4 sts=4 expandtab:

View File

@ -0,0 +1,283 @@
# ===================================================================
#
# Copyright (c) 2024, Helder Eijs <helderijs@gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
import unittest
from binascii import unhexlify
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.Math.Numbers import Integer
from Crypto.Hash import SHAKE128
from Crypto.PublicKey import ECC
from Crypto.PublicKey.ECC import EccKey, EccXPoint, _curves
# Test vectors for scalar multiplication using point with X=9 as base
# generated with nickovs' Python-only code https://gist.github.com/nickovs/cc3c22d15f239a2640c185035c06f8a3
# The order is 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed
# Each tuple is (exponent, X-coordinate)
scalar_base9_test = [
(1, 9),
(2, 0x20d342d51873f1b7d9750c687d1571148f3f5ced1e350b5c5cae469cdd684efb),
(3, 0x1c12bc1a6d57abe645534d91c21bba64f8824e67621c0859c00a03affb713c12),
(4, 0x79ce98b7e0689d7de7d1d074a15b315ffe1805dfcd5d2a230fee85e4550013ef),
(6, 0x26954ccdc99ebf34f8f1dde5e6bb080685fec73640494c28f9fe0bfa8c794531),
(9, 0x192b929197d07748db44600da41bab7499b1c2e6e2f87c6f0e337980668164ba),
(129, 0x7332096a738900085e721103fce2cbf13aee50fef0788ea0d669008eb09ceab7),
(255, 0x1534582fc2b1cea45e8cb776547e209da4fd54a9e473b50c5b8c6b0ae023a9b3),
(256, 0x4300017536976a742ec8747f7505cd6bc80e610d669acab1a1eed36f680d98e8),
(257, 0x6c410611cb484c9016adfb884d37a0e682e075daca1d46f45bb7a4afed10b125),
(0x10101, 0xa679e9d7e043bf76c03362576e2c88abe9093c5d4f6b4a202c64a8397467cf),
(0xAA55CC, 0x2cc02f84c067e3586f4278326689be163e606d69ccae505bb09488e11f295887),
(0x1B29A0E579E0A000567, 0x50c38a72d7bfd7864c8b9083fa123e8d359068e6b491a019a885036e073f6604),
(0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed + 1, 9),
]
class TestEccPoint_Curve25519(unittest.TestCase):
v1 = 0x09fa78b39b00a72930bcd8039be789a0997830bb99f79aeeb93493715390b4e8
v2 = 0x15210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493
def test_init(self):
EccXPoint(9, "curve25519")
EccXPoint(2**255 - 19 + 5, "curve25519")
def test_curve_attribute(self):
point = EccXPoint(9, "curve25519")
self.assertEqual(point.curve, "Curve25519")
def test_init_fail(self):
self.assertRaises(ValueError, EccXPoint, 3*(2**255 - 19), "curve25519")
self.assertRaises(ValueError, EccXPoint, 9, "curve25518")
def test_equal_set(self):
point1 = EccXPoint(self.v1, "curve25519")
point2 = EccXPoint(self.v2, "curve25519")
self.assertEqual(point1, point1)
self.assertNotEqual(point1, point2)
point2.set(point1)
self.assertEqual(point1.x, point2.x)
def test_copy(self):
point1 = EccXPoint(self.v1, "curve25519")
point2 = point1.copy()
self.assertEqual(point1.x, point2.x)
def test_pai(self):
point1 = EccXPoint(self.v1, "curve25519")
pai = point1.point_at_infinity()
self.assertTrue(pai.point_at_infinity())
point2 = EccXPoint(None, "curve25519")
self.assertTrue(point2.point_at_infinity())
def test_scalar_multiply(self):
base = EccXPoint(9, "curve25519")
pointH = 0 * base
self.assertTrue(pointH.point_at_infinity())
pointH = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed * base
self.assertTrue(pointH.point_at_infinity())
pointH = base * 1
self.assertEqual(pointH.x, 9)
for d, result in scalar_base9_test:
pointH = d * base
self.assertEqual(pointH.x, result)
def test_sizes(self):
point = EccXPoint(9, "curve25519")
self.assertEqual(point.size_in_bits(), 255)
self.assertEqual(point.size_in_bytes(), 32)
class TestEccKey_Curve25519(unittest.TestCase):
def test_private_key(self):
# RFC7748 Section 6.1 - Alice
alice_priv = unhexlify("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a")
alice_pub = unhexlify("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a")
alice_pub_x = Integer.from_bytes(alice_pub, byteorder='little')
key = EccKey(curve="Curve25519", seed=alice_priv)
self.assertEqual(key.seed, alice_priv)
self.assertTrue(key.has_private())
self.assertEqual(key.pointQ.x, alice_pub_x)
# RFC7748 Section 6.1 - Bob
bob_priv = unhexlify("5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb")
bob_pub = unhexlify("de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f")
bob_pub_x = Integer.from_bytes(bob_pub, byteorder='little')
key = EccKey(curve="Curve25519", seed=bob_priv)
self.assertEqual(key.seed, bob_priv)
self.assertTrue(key.has_private())
self.assertEqual(key.pointQ.x, bob_pub_x)
# Other names
key = EccKey(curve="curve25519", seed=alice_priv)
# Must not accept d parameter
self.assertRaises(ValueError, EccKey, curve="curve25519", d=1)
def test_public_key(self):
point = EccXPoint(_curves['curve25519'].Gx,
curve='curve25519')
key = EccKey(curve="curve25519", point=point)
self.assertFalse(key.has_private())
self.assertEqual(key.pointQ, point)
def test_public_key_derived(self):
priv_key = EccKey(curve="curve25519", seed=b'H'*32)
pub_key = priv_key.public_key()
self.assertFalse(pub_key.has_private())
self.assertEqual(priv_key.pointQ, pub_key.pointQ)
def test_invalid_seed(self):
self.assertRaises(ValueError, lambda: EccKey(curve="curve25519", seed=b'H' * 31))
def test_equality(self):
private_key = ECC.construct(seed=b'H'*32, curve="Curve25519")
private_key2 = ECC.construct(seed=b'H'*32, curve="curve25519")
private_key3 = ECC.construct(seed=b'C'*32, curve="Curve25519")
public_key = private_key.public_key()
public_key2 = private_key2.public_key()
public_key3 = private_key3.public_key()
self.assertEqual(private_key, private_key2)
self.assertNotEqual(private_key, private_key3)
self.assertEqual(public_key, public_key2)
self.assertNotEqual(public_key, public_key3)
self.assertNotEqual(public_key, private_key)
def test_name_consistency(self):
key = ECC.generate(curve='curve25519')
self.assertIn("curve='Curve25519'", repr(key))
self.assertEqual(key.curve, 'Curve25519')
self.assertEqual(key.public_key().curve, 'Curve25519')
class TestEccModule_Curve25519(unittest.TestCase):
def test_generate(self):
key = ECC.generate(curve="Curve25519")
self.assertTrue(key.has_private())
point = EccXPoint(_curves['Curve25519'].Gx, curve="Curve25519") * key.d
self.assertEqual(key.pointQ, point)
# Always random
key2 = ECC.generate(curve="Curve25519")
self.assertNotEqual(key, key2)
# Other names
ECC.generate(curve="curve25519")
# Random source
key1 = ECC.generate(curve="Curve25519", randfunc=SHAKE128.new().read)
key2 = ECC.generate(curve="Curve25519", randfunc=SHAKE128.new().read)
self.assertEqual(key1, key2)
def test_construct(self):
seed = unhexlify("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a")
point_hex = unhexlify("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a")
Px = Integer.from_bytes(point_hex, byteorder='little')
point = EccXPoint(Px, curve="Curve25519")
# Private key only
key = ECC.construct(curve="Curve25519", seed=seed)
self.assertEqual(key.pointQ, point)
self.assertTrue(key.has_private())
# Public key only
key = ECC.construct(curve="Curve25519", point_x=Px)
self.assertEqual(key.pointQ, point)
self.assertFalse(key.has_private())
# Private and public key
key = ECC.construct(curve="Curve25519", seed=seed, point_x=Px)
self.assertEqual(key.pointQ, point)
self.assertTrue(key.has_private())
# Other names
key = ECC.construct(curve="curve25519", seed=seed)
def test_negative_construct(self):
coordG = dict(point_x=_curves['curve25519'].Gx)
self.assertRaises(ValueError, ECC.construct, curve="Curve25519", d=2, **coordG)
self.assertRaises(ValueError, ECC.construct, curve="Curve25519", seed=b'H'*31)
# Verify you cannot construct weak keys (small-order points)
self.assertRaises(ValueError, ECC.construct, curve="Curve25519",
point_x=0)
self.assertRaises(ValueError, ECC.construct, curve="Curve25519",
point_x=1)
self.assertRaises(ValueError, ECC.construct, curve="Curve25519",
point_x=325606250916557431795983626356110631294008115727848805560023387167927233504)
self.assertRaises(ValueError, ECC.construct, curve="Curve25519",
point_x=39382357235489614581723060781553021112529911719440698176882885853963445705823)
p = 2**255 - 19
self.assertRaises(ValueError, ECC.construct, curve="Curve25519",
point_x=p-1)
self.assertRaises(ValueError, ECC.construct, curve="Curve25519",
point_x=p)
self.assertRaises(ValueError, ECC.construct, curve="Curve25519",
point_x=p+1)
self.assertRaises(ValueError, ECC.construct, curve="Curve25519",
point_x=p+325606250916557431795983626356110631294008115727848805560023387167927233504)
self.assertRaises(ValueError, ECC.construct, curve="Curve25519",
point_x=p+39382357235489614581723060781553021112529911719440698176882885853963445705823)
self.assertRaises(ValueError, ECC.construct, curve="Curve25519",
point_x=p*2-1)
self.assertRaises(ValueError, ECC.construct, curve="Curve25519",
point_x=p*2)
self.assertRaises(ValueError, ECC.construct, curve="Curve25519",
point_x=p*2+1)
def get_tests(config={}):
tests = []
tests += list_test_cases(TestEccPoint_Curve25519)
tests += list_test_cases(TestEccKey_Curve25519)
tests += list_test_cases(TestEccModule_Curve25519)
return tests
if __name__ == '__main__':
def suite():
return unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')

View File

@ -0,0 +1,246 @@
# This file is licensed under the BSD 2-Clause License.
# See https://opensource.org/licenses/BSD-2-Clause for details.
import unittest
from binascii import unhexlify
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.Math.Numbers import Integer
from Crypto.Hash import SHAKE128
from Crypto.PublicKey import ECC
from Crypto.PublicKey.ECC import EccKey, EccXPoint, _curves
CURVE448_P = 2**448 - 2**224 - 1
CURVE448_ORDER = 2**446 - 0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d
# Test vectors for scalar multiplication using point with X=5 as base
# Each tuple is (exponent, X-coordinate)
scalar_base5_test = [
(1, 5),
(2, 0x6391322257cae3d49aef4665d8bd5cccac9abefb511e83d75f3c766616266fc1bf3747f1da00ed7125e8f0255a1208087d32a4bc1c743cb6),
(3, 0x1fbe4b3584cab86170c14b9325840b8a2429b61fb93c42492c002a2807a4e7ea63138ea59bf95652ce9a7d13d0321c7511e3314d0553f34c),
(4, 0x93b44a7b78726ba8d0b048bd7144074f8bdad24ef9d0a6c8264f6c00b135ffcea11545e80d18364acc8ebfbcc45358e0da5fd5e5146e2b1),
(6, 0x693d165f453bd62871e5e53845f33e9e5b18b24d79c1f9102608aa7ba6f18ac24864012171d64c90b698f5ce5631cd02cee4e4336b1ad88c),
(9, 0xb970d576e7d9aa427dbf7cb9b7dd65170721d04ee060c9ea8d499dc361d4cfde1ceb19068eae853bac8f5d92827bdbf3d94c22de2fb42dae),
(129, 0x9fbdb50a1450438fe656aa32aa1bb2548d077d5c3a5d327689093a2996a4f94eacd1fb4f90315edb2afe41908a759f0d6db83fa791df80db),
(255, 0x31bc3e9385dfd12e1238927061eb0c911466da394e459bf058ba3b08260a258a3c392b0f85ddbd23828657137b88577a85b83774139fab9e),
(256, 0x735c7f30e6872e5e4215c0147c8a112d697f668c9bd0f92f5f1e4e6badc128a0b654e697cd4bae2144d54e726b54c1fa63a09b00dd3c17f),
(257, 0x95c1b0ce01286dc047aeb5922a5e62b3effb5b9296273a5004eb456f592728dd494a6fb5996a2ea7011ae6423874a48c2927bfa62d8ce8b0),
(0x10101, 0x113bb172c9dc52ab45bd665dd9751ed44e33b8596f943c6cb2f8dd329160ece802960b3eb0d2c21ef3a3ac12c20fccbc2a271fc2f061c1b2),
(0xAA55CC, 0xcf42585d2e0b1e45c0bfd601c91af4b137d7faf139fc761178c7ded432417c307ee1759af2deec6a14dbaf6b868eb13a6039fbdde4b61898),
(0x1B29A0E579E0A000567, 0x7bd9ec9775a664f4d860d82d6be60895113a7c36f92db25583dbba5dc17f09c136ec27e14857bfd6a705311327030aa657dd036325fad330),
(CURVE448_ORDER + 1, 5),
]
class TestEccPoint_Curve448(unittest.TestCase):
v1 = 0x09fa78b39b00a72930bcd8039be789a0997830bb99f79aeeb93493715390b4e8
v2 = 0x15210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493
def test_init(self):
EccXPoint(5, "curve448")
EccXPoint(CURVE448_P - 5, "curve448")
def test_curve_attribute(self):
point = EccXPoint(5, "curve448")
self.assertEqual(point.curve, "Curve448")
def test_init_fail(self):
self.assertRaises(ValueError, EccXPoint, 3*CURVE448_P, "curve448")
self.assertRaises(ValueError, EccXPoint, 3, "curve449")
def test_equal_set(self):
point1 = EccXPoint(self.v1, "curve448")
point2 = EccXPoint(self.v2, "curve448")
self.assertEqual(point1, point1)
self.assertNotEqual(point1, point2)
point2.set(point1)
self.assertEqual(point1.x, point2.x)
def test_copy(self):
point1 = EccXPoint(self.v1, "curve448")
point2 = point1.copy()
self.assertEqual(point1.x, point2.x)
def test_pai(self):
point1 = EccXPoint(self.v1, "curve448")
pai = point1.point_at_infinity()
self.assertTrue(pai.point_at_infinity())
point2 = EccXPoint(None, "curve448")
self.assertTrue(point2.point_at_infinity())
def test_scalar_multiply(self):
base = EccXPoint(5, "curve448")
pointH = 0 * base
self.assertTrue(pointH.point_at_infinity())
pointH = CURVE448_ORDER * base
self.assertTrue(pointH.point_at_infinity())
pointH = base * 1
self.assertEqual(pointH.x, 5)
for d, result in scalar_base5_test:
pointH = d * base
self.assertEqual(pointH.x, result)
def test_sizes(self):
point = EccXPoint(5, "curve448")
self.assertEqual(point.size_in_bits(), 448)
self.assertEqual(point.size_in_bytes(), 56)
class TestEccKey_Curve448(unittest.TestCase):
def test_private_key(self):
# RFC7748 Section 6.2 - Alice
alice_priv = unhexlify("9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b")
alice_pub = unhexlify("9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0")
alice_pub_x = Integer.from_bytes(alice_pub, byteorder='little')
key = EccKey(curve="Curve448", seed=alice_priv)
self.assertEqual(key.seed, alice_priv)
self.assertTrue(key.has_private())
self.assertEqual(key.pointQ.x, alice_pub_x)
# RFC7748 Section 6.2 - Bob
bob_priv = unhexlify("1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d")
bob_pub = unhexlify("3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609")
bob_pub_x = Integer.from_bytes(bob_pub, byteorder='little')
key = EccKey(curve="Curve448", seed=bob_priv)
self.assertEqual(key.seed, bob_priv)
self.assertTrue(key.has_private())
self.assertEqual(key.pointQ.x, bob_pub_x)
# Other names
key = EccKey(curve="curve448", seed=alice_priv)
# Must not accept d parameter
self.assertRaises(ValueError, EccKey, curve="curve448", d=1)
def test_public_key(self):
point = EccXPoint(_curves['curve448'].Gx,
curve='curve448')
key = EccKey(curve="curve448", point=point)
self.assertFalse(key.has_private())
self.assertEqual(key.pointQ, point)
def test_public_key_derived(self):
priv_key = EccKey(curve="curve448", seed=b'H'*56)
pub_key = priv_key.public_key()
self.assertFalse(pub_key.has_private())
self.assertEqual(priv_key.pointQ, pub_key.pointQ)
def test_invalid_seed(self):
self.assertRaises(ValueError, lambda: EccKey(curve="curve448",
seed=b'H' * 55))
def test_equality(self):
private_key = ECC.construct(seed=b'H'*56, curve="Curve448")
private_key2 = ECC.construct(seed=b'H'*56, curve="curve448")
private_key3 = ECC.construct(seed=b'C'*56, curve="Curve448")
public_key = private_key.public_key()
public_key2 = private_key2.public_key()
public_key3 = private_key3.public_key()
self.assertEqual(private_key, private_key2)
self.assertNotEqual(private_key, private_key3)
self.assertEqual(public_key, public_key2)
self.assertNotEqual(public_key, public_key3)
self.assertNotEqual(public_key, private_key)
def test_name_consistency(self):
key = ECC.generate(curve='curve448')
self.assertIn("curve='Curve448'", repr(key))
self.assertEqual(key.curve, 'Curve448')
self.assertEqual(key.public_key().curve, 'Curve448')
class TestEccModule_Curve448(unittest.TestCase):
def test_generate(self):
key = ECC.generate(curve="Curve448")
self.assertTrue(key.has_private())
point = EccXPoint(_curves['Curve448'].Gx, curve="Curve448") * key.d
self.assertEqual(key.pointQ, point)
# Always random
key2 = ECC.generate(curve="Curve448")
self.assertNotEqual(key, key2)
# Other names
ECC.generate(curve="curve448")
# Random source
key1 = ECC.generate(curve="Curve448", randfunc=SHAKE128.new().read)
key2 = ECC.generate(curve="Curve448", randfunc=SHAKE128.new().read)
self.assertEqual(key1, key2)
def test_construct(self):
seed = unhexlify("9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b")
point_hex = unhexlify("9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0")
Px = Integer.from_bytes(point_hex, byteorder='little')
point = EccXPoint(Px, curve="Curve448")
# Private key only
key = ECC.construct(curve="Curve448", seed=seed)
self.assertEqual(key.pointQ, point)
self.assertTrue(key.has_private())
# Public key only
key = ECC.construct(curve="Curve448", point_x=Px)
self.assertEqual(key.pointQ, point)
self.assertFalse(key.has_private())
# Private and public key
key = ECC.construct(curve="Curve448", seed=seed, point_x=Px)
self.assertEqual(key.pointQ, point)
self.assertTrue(key.has_private())
# Other names
key = ECC.construct(curve="curve448", seed=seed)
def test_negative_construct(self):
coordG = dict(point_x=_curves['curve448'].Gx)
self.assertRaises(ValueError, ECC.construct, curve="Curve448",
d=2, **coordG)
self.assertRaises(ValueError, ECC.construct, curve="Curve448",
seed=b'H'*55)
# Verify you cannot construct weak keys (small-order points)
self.assertRaises(ValueError, ECC.construct, curve="Curve448",
point_x=0)
self.assertRaises(ValueError, ECC.construct, curve="Curve448",
point_x=1)
p = 2**448 - 2**224 - 1
self.assertRaises(ValueError, ECC.construct, curve="Curve448",
point_x=p-1)
self.assertRaises(ValueError, ECC.construct, curve="Curve448",
point_x=p)
self.assertRaises(ValueError, ECC.construct, curve="Curve448",
point_x=p+1)
def get_tests(config={}):
tests = []
tests += list_test_cases(TestEccPoint_Curve448)
tests += list_test_cases(TestEccKey_Curve448)
tests += list_test_cases(TestEccModule_Curve448)
return tests
if __name__ == '__main__':
def suite():
return unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')

View File

@ -0,0 +1,341 @@
# ===================================================================
#
# Copyright (c) 2022, Legrandin <helderijs@gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
import unittest
from binascii import unhexlify
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.SelfTest.loader import load_test_vectors
from Crypto.PublicKey import ECC
from Crypto.PublicKey.ECC import EccPoint, _curves, EccKey
from Crypto.Math.Numbers import Integer
from Crypto.Hash import SHAKE128
class TestEccPoint_Ed25519(unittest.TestCase):
Gxy = {"x": 15112221349535400772501151409588531511454012693041857206046113283949847762202,
"y": 46316835694926478169428394003475163141307993866256225615783033603165251855960}
G2xy = {"x": 24727413235106541002554574571675588834622768167397638456726423682521233608206,
"y": 15549675580280190176352668710449542251549572066445060580507079593062643049417}
G3xy = {"x": 46896733464454938657123544595386787789046198280132665686241321779790909858396,
"y": 8324843778533443976490377120369201138301417226297555316741202210403726505172}
pointG = EccPoint(Gxy['x'], Gxy['y'], curve="ed25519")
pointG2 = EccPoint(G2xy['x'], G2xy['y'], curve="ed25519")
pointG3 = EccPoint(G3xy['x'], G3xy['y'], curve="ed25519")
def test_curve_attribute(self):
self.assertEqual(self.pointG.curve, "Ed25519")
def test_init_xy(self):
EccPoint(self.Gxy['x'], self.Gxy['y'], curve="Ed25519")
# Neutral point
pai = EccPoint(0, 1, curve="Ed25519")
self.assertEqual(pai.x, 0)
self.assertEqual(pai.y, 1)
self.assertEqual(pai.xy, (0, 1))
# G
bp = self.pointG.copy()
self.assertEqual(bp.x, 15112221349535400772501151409588531511454012693041857206046113283949847762202)
self.assertEqual(bp.y, 46316835694926478169428394003475163141307993866256225615783033603165251855960)
self.assertEqual(bp.xy, (bp.x, bp.y))
# 2G
bp2 = self.pointG2.copy()
self.assertEqual(bp2.x, 24727413235106541002554574571675588834622768167397638456726423682521233608206)
self.assertEqual(bp2.y, 15549675580280190176352668710449542251549572066445060580507079593062643049417)
self.assertEqual(bp2.xy, (bp2.x, bp2.y))
# 5G
EccPoint(x=33467004535436536005251147249499675200073690106659565782908757308821616914995,
y=43097193783671926753355113395909008640284023746042808659097434958891230611693,
curve="Ed25519")
# Catch if point is not on the curve
self.assertRaises(ValueError, EccPoint, 34, 35, curve="Ed25519")
def test_set(self):
pointW = EccPoint(0, 1, curve="Ed25519")
pointW.set(self.pointG)
self.assertEqual(pointW.x, self.pointG.x)
self.assertEqual(pointW.y, self.pointG.y)
def test_copy(self):
pointW = self.pointG.copy()
self.assertEqual(pointW.x, self.pointG.x)
self.assertEqual(pointW.y, self.pointG.y)
def test_equal(self):
pointH = self.pointG.copy()
pointI = self.pointG2.copy()
self.assertEqual(self.pointG, pointH)
self.assertNotEqual(self.pointG, pointI)
def test_pai(self):
pai = EccPoint(0, 1, curve="Ed25519")
self.assertTrue(pai.is_point_at_infinity())
self.assertEqual(pai, pai.point_at_infinity())
def test_negate(self):
negG = -self.pointG
G100 = self.pointG * 100
sum_zero = G100 + negG * 100
self.assertTrue(sum_zero.is_point_at_infinity())
sum_99 = G100 + negG
expected = self.pointG * 99
self.assertEqual(sum_99, expected)
def test_addition(self):
self.assertEqual(self.pointG + self.pointG2, self.pointG3)
self.assertEqual(self.pointG2 + self.pointG, self.pointG3)
self.assertEqual(self.pointG2 + self.pointG.point_at_infinity(), self.pointG2)
self.assertEqual(self.pointG.point_at_infinity() + self.pointG2, self.pointG2)
G5 = self.pointG2 + self.pointG3
self.assertEqual(G5.x, 33467004535436536005251147249499675200073690106659565782908757308821616914995)
self.assertEqual(G5.y, 43097193783671926753355113395909008640284023746042808659097434958891230611693)
def test_inplace_addition(self):
pointH = self.pointG.copy()
pointH += self.pointG
self.assertEqual(pointH, self.pointG2)
pointH += self.pointG
self.assertEqual(pointH, self.pointG3)
pointH += self.pointG.point_at_infinity()
self.assertEqual(pointH, self.pointG3)
def test_doubling(self):
pointH = self.pointG.copy()
pointH.double()
self.assertEqual(pointH.x, self.pointG2.x)
self.assertEqual(pointH.y, self.pointG2.y)
# 2*0
pai = self.pointG.point_at_infinity()
pointR = pai.copy()
pointR.double()
self.assertEqual(pointR, pai)
def test_scalar_multiply(self):
d = 0
pointH = d * self.pointG
self.assertEqual(pointH.x, 0)
self.assertEqual(pointH.y, 1)
d = 1
pointH = d * self.pointG
self.assertEqual(pointH.x, self.pointG.x)
self.assertEqual(pointH.y, self.pointG.y)
d = 2
pointH = d * self.pointG
self.assertEqual(pointH.x, self.pointG2.x)
self.assertEqual(pointH.y, self.pointG2.y)
d = 3
pointH = d * self.pointG
self.assertEqual(pointH.x, self.pointG3.x)
self.assertEqual(pointH.y, self.pointG3.y)
d = 4
pointH = d * self.pointG
self.assertEqual(pointH.x, 14582954232372986451776170844943001818709880559417862259286374126315108956272)
self.assertEqual(pointH.y, 32483318716863467900234833297694612235682047836132991208333042722294373421359)
d = 5
pointH = d * self.pointG
self.assertEqual(pointH.x, 33467004535436536005251147249499675200073690106659565782908757308821616914995)
self.assertEqual(pointH.y, 43097193783671926753355113395909008640284023746042808659097434958891230611693)
d = 10
pointH = d * self.pointG
self.assertEqual(pointH.x, 43500613248243327786121022071801015118933854441360174117148262713429272820047)
self.assertEqual(pointH.y, 45005105423099817237495816771148012388779685712352441364231470781391834741548)
d = 20
pointH = d * self.pointG
self.assertEqual(pointH.x, 46694936775300686710656303283485882876784402425210400817529601134760286812591)
self.assertEqual(pointH.y, 8786390172762935853260670851718824721296437982862763585171334833968259029560)
d = 255
pointH = d * self.pointG
self.assertEqual(pointH.x, 36843863416400016952258312492144504209624961884991522125275155377549541182230)
self.assertEqual(pointH.y, 22327030283879720808995671630924669697661065034121040761798775626517750047180)
d = 256
pointH = d * self.pointG
self.assertEqual(pointH.x, 42740085206947573681423002599456489563927820004573071834350074001818321593686)
self.assertEqual(pointH.y, 6935684722522267618220753829624209639984359598320562595061366101608187623111)
def test_sizes(self):
self.assertEqual(self.pointG.size_in_bits(), 255)
self.assertEqual(self.pointG.size_in_bytes(), 32)
class TestEccKey_Ed25519(unittest.TestCase):
def test_private_key(self):
seed = unhexlify("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")
Px = 38815646466658113194383306759739515082307681141926459231621296960732224964046
Py = 11903303657706407974989296177215005343713679411332034699907763981919547054807
key = EccKey(curve="Ed25519", seed=seed)
self.assertEqual(key.seed, seed)
self.assertEqual(key.d, 36144925721603087658594284515452164870581325872720374094707712194495455132720)
self.assertTrue(key.has_private())
self.assertEqual(key.pointQ.x, Px)
self.assertEqual(key.pointQ.y, Py)
point = EccPoint(Px, Py, "ed25519")
key = EccKey(curve="Ed25519", seed=seed, point=point)
self.assertEqual(key.d, 36144925721603087658594284515452164870581325872720374094707712194495455132720)
self.assertTrue(key.has_private())
self.assertEqual(key.pointQ, point)
# Other names
key = EccKey(curve="ed25519", seed=seed)
# Must not accept d parameter
self.assertRaises(ValueError, EccKey, curve="ed25519", d=1)
def test_public_key(self):
point = EccPoint(_curves['ed25519'].Gx, _curves['ed25519'].Gy, curve='ed25519')
key = EccKey(curve="ed25519", point=point)
self.assertFalse(key.has_private())
self.assertEqual(key.pointQ, point)
def test_public_key_derived(self):
priv_key = EccKey(curve="ed25519", seed=b'H'*32)
pub_key = priv_key.public_key()
self.assertFalse(pub_key.has_private())
self.assertEqual(priv_key.pointQ, pub_key.pointQ)
def test_invalid_seed(self):
self.assertRaises(ValueError, lambda: EccKey(curve="ed25519", seed=b'H' * 31))
def test_equality(self):
private_key = ECC.construct(seed=b'H'*32, curve="Ed25519")
private_key2 = ECC.construct(seed=b'H'*32, curve="ed25519")
private_key3 = ECC.construct(seed=b'C'*32, curve="Ed25519")
public_key = private_key.public_key()
public_key2 = private_key2.public_key()
public_key3 = private_key3.public_key()
self.assertEqual(private_key, private_key2)
self.assertNotEqual(private_key, private_key3)
self.assertEqual(public_key, public_key2)
self.assertNotEqual(public_key, public_key3)
self.assertNotEqual(public_key, private_key)
def test_name_consistency(self):
key = ECC.generate(curve='ed25519')
self.assertIn("curve='Ed25519'", repr(key))
self.assertEqual(key.curve, 'Ed25519')
self.assertEqual(key.public_key().curve, 'Ed25519')
class TestEccModule_Ed25519(unittest.TestCase):
def test_generate(self):
key = ECC.generate(curve="Ed25519")
self.assertTrue(key.has_private())
point = EccPoint(_curves['Ed25519'].Gx, _curves['Ed25519'].Gy, curve="Ed25519") * key.d
self.assertEqual(key.pointQ, point)
# Always random
key2 = ECC.generate(curve="Ed25519")
self.assertNotEqual(key, key2)
# Other names
ECC.generate(curve="Ed25519")
# Random source
key1 = ECC.generate(curve="Ed25519", randfunc=SHAKE128.new().read)
key2 = ECC.generate(curve="Ed25519", randfunc=SHAKE128.new().read)
self.assertEqual(key1, key2)
def test_construct(self):
seed = unhexlify("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")
Px = 38815646466658113194383306759739515082307681141926459231621296960732224964046
Py = 11903303657706407974989296177215005343713679411332034699907763981919547054807
d = 36144925721603087658594284515452164870581325872720374094707712194495455132720
point = EccPoint(Px, Py, curve="Ed25519")
# Private key only
key = ECC.construct(curve="Ed25519", seed=seed)
self.assertEqual(key.pointQ, point)
self.assertTrue(key.has_private())
# Public key only
key = ECC.construct(curve="Ed25519", point_x=Px, point_y=Py)
self.assertEqual(key.pointQ, point)
self.assertFalse(key.has_private())
# Private and public key
key = ECC.construct(curve="Ed25519", seed=seed, point_x=Px, point_y=Py)
self.assertEqual(key.pointQ, point)
self.assertTrue(key.has_private())
# Other names
key = ECC.construct(curve="ed25519", seed=seed)
def test_negative_construct(self):
coord = dict(point_x=10, point_y=4)
coordG = dict(point_x=_curves['ed25519'].Gx, point_y=_curves['ed25519'].Gy)
self.assertRaises(ValueError, ECC.construct, curve="Ed25519", **coord)
self.assertRaises(ValueError, ECC.construct, curve="Ed25519", d=2, **coordG)
self.assertRaises(ValueError, ECC.construct, curve="Ed25519", seed=b'H'*31)
def get_tests(config={}):
tests = []
tests += list_test_cases(TestEccPoint_Ed25519)
tests += list_test_cases(TestEccKey_Ed25519)
tests += list_test_cases(TestEccModule_Ed25519)
return tests
if __name__ == '__main__':
def suite():
return unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')

View File

@ -0,0 +1,336 @@
# ===================================================================
#
# Copyright (c) 2022, Legrandin <helderijs@gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
import unittest
from binascii import unhexlify
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.SelfTest.loader import load_test_vectors
from Crypto.PublicKey import ECC
from Crypto.PublicKey.ECC import EccPoint, _curves, EccKey
from Crypto.Math.Numbers import Integer
from Crypto.Hash import SHAKE128
class TestEccPoint_Ed448(unittest.TestCase):
Gxy = {"x": 0x4f1970c66bed0ded221d15a622bf36da9e146570470f1767ea6de324a3d3a46412ae1af72ab66511433b80e18b00938e2626a82bc70cc05e,
"y": 0x693f46716eb6bc248876203756c9c7624bea73736ca3984087789c1e05a0c2d73ad3ff1ce67c39c4fdbd132c4ed7c8ad9808795bf230fa14}
G2xy = {"x": 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa955555555555555555555555555555555555555555555555555555555,
"y": 0xae05e9634ad7048db359d6205086c2b0036ed7a035884dd7b7e36d728ad8c4b80d6565833a2a3098bbbcb2bed1cda06bdaeafbcdea9386ed}
G3xy = {"x": 0x865886b9108af6455bd64316cb6943332241b8b8cda82c7e2ba077a4a3fcfe8daa9cbf7f6271fd6e862b769465da8575728173286ff2f8f,
"y": 0xe005a8dbd5125cf706cbda7ad43aa6449a4a8d952356c3b9fce43c82ec4e1d58bb3a331bdb6767f0bffa9a68fed02dafb822ac13588ed6fc}
pointG = EccPoint(Gxy['x'], Gxy['y'], curve="ed448")
pointG2 = EccPoint(G2xy['x'], G2xy['y'], curve="ed448")
pointG3 = EccPoint(G3xy['x'], G3xy['y'], curve="ed448")
def test_curve_attribute(self):
self.assertEqual(self.pointG.curve, "Ed448")
def test_init_xy(self):
EccPoint(self.Gxy['x'], self.Gxy['y'], curve="Ed448")
# Neutral point
pai = EccPoint(0, 1, curve="Ed448")
self.assertEqual(pai.x, 0)
self.assertEqual(pai.y, 1)
self.assertEqual(pai.xy, (0, 1))
# G
bp = self.pointG.copy()
self.assertEqual(bp.x, 0x4f1970c66bed0ded221d15a622bf36da9e146570470f1767ea6de324a3d3a46412ae1af72ab66511433b80e18b00938e2626a82bc70cc05e)
self.assertEqual(bp.y, 0x693f46716eb6bc248876203756c9c7624bea73736ca3984087789c1e05a0c2d73ad3ff1ce67c39c4fdbd132c4ed7c8ad9808795bf230fa14)
self.assertEqual(bp.xy, (bp.x, bp.y))
# 2G
bp2 = self.pointG2.copy()
self.assertEqual(bp2.x, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa955555555555555555555555555555555555555555555555555555555)
self.assertEqual(bp2.y, 0xae05e9634ad7048db359d6205086c2b0036ed7a035884dd7b7e36d728ad8c4b80d6565833a2a3098bbbcb2bed1cda06bdaeafbcdea9386ed)
self.assertEqual(bp2.xy, (bp2.x, bp2.y))
# 5G
EccPoint(x=0x7a9f9335a48dcb0e2ba7601eedb50def80cbcf728562ada756d761e8958812808bc0d57a920c3c96f07b2d8cefc6f950d0a99d1092030034,
y=0xadfd751a2517edd3b9109ce4fd580ade260ca1823ab18fced86551f7b698017127d7a4ee59d2b33c58405512881f225443b4731472f435eb,
curve="Ed448")
# Catch if point is not on the curve
self.assertRaises(ValueError, EccPoint, 34, 35, curve="Ed448")
def test_set(self):
pointW = EccPoint(0, 1, curve="Ed448")
pointW.set(self.pointG)
self.assertEqual(pointW.x, self.pointG.x)
self.assertEqual(pointW.y, self.pointG.y)
def test_copy(self):
pointW = self.pointG.copy()
self.assertEqual(pointW.x, self.pointG.x)
self.assertEqual(pointW.y, self.pointG.y)
def test_equal(self):
pointH = self.pointG.copy()
pointI = self.pointG2.copy()
self.assertEqual(self.pointG, pointH)
self.assertNotEqual(self.pointG, pointI)
def test_pai(self):
pai = EccPoint(0, 1, curve="Ed448")
self.assertTrue(pai.is_point_at_infinity())
self.assertEqual(pai, pai.point_at_infinity())
def test_negate(self):
negG = -self.pointG
sum = self.pointG + negG
self.assertTrue(sum.is_point_at_infinity())
def test_addition(self):
self.assertEqual(self.pointG + self.pointG2, self.pointG3)
self.assertEqual(self.pointG2 + self.pointG, self.pointG3)
self.assertEqual(self.pointG2 + self.pointG.point_at_infinity(), self.pointG2)
self.assertEqual(self.pointG.point_at_infinity() + self.pointG2, self.pointG2)
G5 = self.pointG2 + self.pointG3
self.assertEqual(G5.x, 0x7a9f9335a48dcb0e2ba7601eedb50def80cbcf728562ada756d761e8958812808bc0d57a920c3c96f07b2d8cefc6f950d0a99d1092030034)
self.assertEqual(G5.y, 0xadfd751a2517edd3b9109ce4fd580ade260ca1823ab18fced86551f7b698017127d7a4ee59d2b33c58405512881f225443b4731472f435eb)
def test_inplace_addition(self):
pointH = self.pointG.copy()
pointH += self.pointG
self.assertEqual(pointH, self.pointG2)
pointH += self.pointG
self.assertEqual(pointH, self.pointG3)
pointH += self.pointG.point_at_infinity()
self.assertEqual(pointH, self.pointG3)
def test_doubling(self):
pointH = self.pointG.copy()
pointH.double()
self.assertEqual(pointH.x, self.pointG2.x)
self.assertEqual(pointH.y, self.pointG2.y)
# 2*0
pai = self.pointG.point_at_infinity()
pointR = pai.copy()
pointR.double()
self.assertEqual(pointR, pai)
def test_scalar_multiply(self):
d = 0
pointH = d * self.pointG
self.assertEqual(pointH.x, 0)
self.assertEqual(pointH.y, 1)
d = 1
pointH = d * self.pointG
self.assertEqual(pointH.x, self.pointG.x)
self.assertEqual(pointH.y, self.pointG.y)
d = 2
pointH = d * self.pointG
self.assertEqual(pointH.x, self.pointG2.x)
self.assertEqual(pointH.y, self.pointG2.y)
d = 3
pointH = d * self.pointG
self.assertEqual(pointH.x, self.pointG3.x)
self.assertEqual(pointH.y, self.pointG3.y)
d = 4
pointH = d * self.pointG
self.assertEqual(pointH.x, 0x49dcbc5c6c0cce2c1419a17226f929ea255a09cf4e0891c693fda4be70c74cc301b7bdf1515dd8ba21aee1798949e120e2ce42ac48ba7f30)
self.assertEqual(pointH.y, 0xd49077e4accde527164b33a5de021b979cb7c02f0457d845c90dc3227b8a5bc1c0d8f97ea1ca9472b5d444285d0d4f5b32e236f86de51839)
d = 5
pointH = d * self.pointG
self.assertEqual(pointH.x, 0x7a9f9335a48dcb0e2ba7601eedb50def80cbcf728562ada756d761e8958812808bc0d57a920c3c96f07b2d8cefc6f950d0a99d1092030034)
self.assertEqual(pointH.y, 0xadfd751a2517edd3b9109ce4fd580ade260ca1823ab18fced86551f7b698017127d7a4ee59d2b33c58405512881f225443b4731472f435eb)
d = 10
pointH = d * self.pointG
self.assertEqual(pointH.x, 0x77486f9d19f6411cdd35d30d1c3235f71936452c787e5c034134d3e8172278aca61622bc805761ce3dab65118a0122d73b403165d0ed303d)
self.assertEqual(pointH.y, 0x4d2fea0b026be11024f1f0fe7e94e618e8ac17381ada1d1bf7ee293a68ff5d0bf93c1997dc1aabdc0c7e6381428d85b6b1954a89e4cddf67)
d = 20
pointH = d * self.pointG
self.assertEqual(pointH.x, 0x3c236422354600fe6763defcc1503737e4ed89e262d0de3ec1e552020f2a56fe3b9e1e012d021072598c3c2821e18268bb8fb8339c0d1216)
self.assertEqual(pointH.y, 0xb555b9721f630ccb05fc466de4c74d3d2781e69eca88e1b040844f04cab39fd946f91c688fa42402bb38fb9c3e61231017020b219b4396e1)
d = 255
pointH = d * self.pointG
self.assertEqual(pointH.x, 0xbeb7f8388b05cd9c1aa2e3c0dcf31e2b563659361826225390e7748654f627d5c36cbe627e9019936b56d15d4dad7c337c09bac64ff4197f)
self.assertEqual(pointH.y, 0x1e37312b2dd4e9440c43c6e7725fc4fa3d11e582d4863f1d018e28f50c0efdb1f53f9b01ada7c87fa162b1f0d72401015d57613d25f1ad53)
d = 256
pointH = d * self.pointG
self.assertEqual(pointH.x, 0xf19c34feb56730e3e2be761ac0a2a2b24853b281dda019fc35a5ab58e3696beb39609ae756b0d20fb7ccf0d79aaf5f3bca2e4fdb25bfac1c)
self.assertEqual(pointH.y, 0x3beb69cc9111bffcaddc61d363ce6fe5dd44da4aadce78f52e92e985d5442344ced72c4611ed0daac9f4f5661eab73d7a12d25ce8a30241e)
def test_sizes(self):
self.assertEqual(self.pointG.size_in_bits(), 448)
self.assertEqual(self.pointG.size_in_bytes(), 56)
class TestEccKey_Ed448(unittest.TestCase):
def test_private_key(self):
seed = unhexlify("4adf5d37ac6785e83e99a924f92676d366a78690af59c92b6bdf14f9cdbcf26fdad478109607583d633b60078d61d51d81b7509c5433b0d4c9")
Px = 0x72a01eea003a35f9ac44231dc4aae2a382f351d80bf32508175b0855edcf389aa2bbf308dd961ce361a6e7c2091bc78957f6ebcf3002a617
Py = 0x9e0d08d84586e9aeefecacb41d049b831f1a3ee0c3eada63e34557b30702b50ab59fb372feff7c30b8cbb7dd51afbe88444ec56238722ec1
key = EccKey(curve="Ed448", seed=seed)
self.assertEqual(key.seed, seed)
self.assertEqual(key.d, 0xb07cf179604f83433186e5178760c759c15125ee54ff6f8dcde46e872b709ac82ed0bd0a4e036d774034dcb18a9fb11894657a1485895f80)
self.assertTrue(key.has_private())
self.assertEqual(key.pointQ.x, Px)
self.assertEqual(key.pointQ.y, Py)
point = EccPoint(Px, Py, "ed448")
key = EccKey(curve="Ed448", seed=seed, point=point)
self.assertEqual(key.d, 0xb07cf179604f83433186e5178760c759c15125ee54ff6f8dcde46e872b709ac82ed0bd0a4e036d774034dcb18a9fb11894657a1485895f80)
self.assertTrue(key.has_private())
self.assertEqual(key.pointQ, point)
# Other names
key = EccKey(curve="ed448", seed=seed)
# Must not accept d parameter
self.assertRaises(ValueError, EccKey, curve="ed448", d=1)
def test_public_key(self):
point = EccPoint(_curves['ed448'].Gx, _curves['ed448'].Gy, curve='ed448')
key = EccKey(curve="ed448", point=point)
self.assertFalse(key.has_private())
self.assertEqual(key.pointQ, point)
def test_public_key_derived(self):
priv_key = EccKey(curve="ed448", seed=b'H'*57)
pub_key = priv_key.public_key()
self.assertFalse(pub_key.has_private())
self.assertEqual(priv_key.pointQ, pub_key.pointQ)
def test_invalid_seed(self):
self.assertRaises(ValueError, lambda: EccKey(curve="ed448", seed=b'H' * 56))
def test_equality(self):
private_key = ECC.construct(seed=b'H'*57, curve="Ed448")
private_key2 = ECC.construct(seed=b'H'*57, curve="ed448")
private_key3 = ECC.construct(seed=b'C'*57, curve="Ed448")
public_key = private_key.public_key()
public_key2 = private_key2.public_key()
public_key3 = private_key3.public_key()
self.assertEqual(private_key, private_key2)
self.assertNotEqual(private_key, private_key3)
self.assertEqual(public_key, public_key2)
self.assertNotEqual(public_key, public_key3)
self.assertNotEqual(public_key, private_key)
def test_name_consistency(self):
key = ECC.generate(curve='ed448')
self.assertIn("curve='Ed448'", repr(key))
self.assertEqual(key.curve, 'Ed448')
self.assertEqual(key.public_key().curve, 'Ed448')
class TestEccModule_Ed448(unittest.TestCase):
def test_generate(self):
key = ECC.generate(curve="Ed448")
self.assertTrue(key.has_private())
point = EccPoint(_curves['Ed448'].Gx, _curves['Ed448'].Gy, curve="Ed448") * key.d
self.assertEqual(key.pointQ, point)
# Always random
key2 = ECC.generate(curve="Ed448")
self.assertNotEqual(key, key2)
# Other names
ECC.generate(curve="Ed448")
# Random source
key1 = ECC.generate(curve="Ed448", randfunc=SHAKE128.new().read)
key2 = ECC.generate(curve="Ed448", randfunc=SHAKE128.new().read)
self.assertEqual(key1, key2)
def test_construct(self):
seed = unhexlify("4adf5d37ac6785e83e99a924f92676d366a78690af59c92b6bdf14f9cdbcf26fdad478109607583d633b60078d61d51d81b7509c5433b0d4c9")
Px = 0x72a01eea003a35f9ac44231dc4aae2a382f351d80bf32508175b0855edcf389aa2bbf308dd961ce361a6e7c2091bc78957f6ebcf3002a617
Py = 0x9e0d08d84586e9aeefecacb41d049b831f1a3ee0c3eada63e34557b30702b50ab59fb372feff7c30b8cbb7dd51afbe88444ec56238722ec1
d = 0xb07cf179604f83433186e5178760c759c15125ee54ff6f8dcde46e872b709ac82ed0bd0a4e036d774034dcb18a9fb11894657a1485895f80
point = EccPoint(Px, Py, curve="Ed448")
# Private key only
key = ECC.construct(curve="Ed448", seed=seed)
self.assertEqual(key.pointQ, point)
self.assertTrue(key.has_private())
# Public key only
key = ECC.construct(curve="Ed448", point_x=Px, point_y=Py)
self.assertEqual(key.pointQ, point)
self.assertFalse(key.has_private())
# Private and public key
key = ECC.construct(curve="Ed448", seed=seed, point_x=Px, point_y=Py)
self.assertEqual(key.pointQ, point)
self.assertTrue(key.has_private())
# Other names
key = ECC.construct(curve="ed448", seed=seed)
def test_negative_construct(self):
coord = dict(point_x=10, point_y=4)
coordG = dict(point_x=_curves['ed448'].Gx, point_y=_curves['ed448'].Gy)
self.assertRaises(ValueError, ECC.construct, curve="Ed448", **coord)
self.assertRaises(ValueError, ECC.construct, curve="Ed448", d=2, **coordG)
self.assertRaises(ValueError, ECC.construct, curve="Ed448", seed=b'H'*58)
def get_tests(config={}):
tests = []
tests += list_test_cases(TestEccPoint_Ed448)
tests += list_test_cases(TestEccKey_Ed448)
tests += list_test_cases(TestEccModule_Ed448)
return tests
if __name__ == '__main__':
def suite():
return unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,217 @@
# -*- coding: utf-8 -*-
#
# SelfTest/PublicKey/test_ElGamal.py: Self-test for the ElGamal primitive
#
# ===================================================================
# The contents of this file are dedicated to the public domain. To
# the extent that dedication to the public domain is not available,
# everyone is granted a worldwide, perpetual, royalty-free,
# non-exclusive license to exercise all rights associated with the
# contents of this file for any purpose whatsoever.
# No rights are reserved.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# ===================================================================
"""Self-test suite for Crypto.PublicKey.ElGamal"""
__revision__ = "$Id$"
import unittest
from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex
from Crypto import Random
from Crypto.PublicKey import ElGamal
from Crypto.Util.number import bytes_to_long
from Crypto.Util.py3compat import *
class ElGamalTest(unittest.TestCase):
#
# Test vectors
#
# There seem to be no real ElGamal test vectors available in the
# public domain. The following test vectors have been generated
# with libgcrypt 1.5.0.
#
# Encryption
tve=[
{
# 256 bits
'p' :'BA4CAEAAED8CBE952AFD2126C63EB3B345D65C2A0A73D2A3AD4138B6D09BD933',
'g' :'05',
'y' :'60D063600ECED7C7C55146020E7A31C4476E9793BEAED420FEC9E77604CAE4EF',
'x' :'1D391BA2EE3C37FE1BA175A69B2C73A11238AD77675932',
'k' :'F5893C5BAB4131264066F57AB3D8AD89E391A0B68A68A1',
'pt' :'48656C6C6F207468657265',
'ct1':'32BFD5F487966CEA9E9356715788C491EC515E4ED48B58F0F00971E93AAA5EC7',
'ct2':'7BE8FBFF317C93E82FCEF9BD515284BA506603FEA25D01C0CB874A31F315EE68'
},
{
# 512 bits
'p' :'F1B18AE9F7B4E08FDA9A04832F4E919D89462FD31BF12F92791A93519F75076D6CE3942689CDFF2F344CAFF0F82D01864F69F3AECF566C774CBACF728B81A227',
'g' :'07',
'y' :'688628C676E4F05D630E1BE39D0066178CA7AA83836B645DE5ADD359B4825A12B02EF4252E4E6FA9BEC1DB0BE90F6D7C8629CABB6E531F472B2664868156E20C',
'x' :'14E60B1BDFD33436C0DA8A22FDC14A2CCDBBED0627CE68',
'k' :'38DBF14E1F319BDA9BAB33EEEADCAF6B2EA5250577ACE7',
'pt' :'48656C6C6F207468657265',
'ct1':'290F8530C2CC312EC46178724F196F308AD4C523CEABB001FACB0506BFED676083FE0F27AC688B5C749AB3CB8A80CD6F7094DBA421FB19442F5A413E06A9772B',
'ct2':'1D69AAAD1DC50493FB1B8E8721D621D683F3BF1321BE21BC4A43E11B40C9D4D9C80DE3AAC2AB60D31782B16B61112E68220889D53C4C3136EE6F6CE61F8A23A0'
}
]
# Signature
tvs=[
{
# 256 bits
'p' :'D2F3C41EA66530838A704A48FFAC9334F4701ECE3A97CEE4C69DD01AE7129DD7',
'g' :'05',
'y' :'C3F9417DC0DAFEA6A05C1D2333B7A95E63B3F4F28CC962254B3256984D1012E7',
'x' :'165E4A39BE44D5A2D8B1332D416BC559616F536BC735BB',
'k' :'C7F0C794A7EAD726E25A47FF8928013680E73C51DD3D7D99BFDA8F492585928F',
'h' :'48656C6C6F207468657265',
'sig1':'35CA98133779E2073EF31165AFCDEB764DD54E96ADE851715495F9C635E1E7C2',
'sig2':'0135B88B1151279FE5D8078D4FC685EE81177EE9802AB123A73925FC1CB059A7',
},
{
# 512 bits
'p' :'E24CF3A4B8A6AF749DCA6D714282FE4AABEEE44A53BB6ED15FBE32B5D3C3EF9CC4124A2ECA331F3C1C1B667ACA3766825217E7B5F9856648D95F05330C6A19CF',
'g' :'0B',
'y' :'2AD3A1049CA5D4ED207B2431C79A8719BB4073D4A94E450EA6CEE8A760EB07ADB67C0D52C275EE85D7B52789061EE45F2F37D9B2AE522A51C28329766BFE68AC',
'x' :'16CBB4F46D9ECCF24FF9F7E63CAA3BD8936341555062AB',
'k' :'8A3D89A4E429FD2476D7D717251FB79BF900FFE77444E6BB8299DC3F84D0DD57ABAB50732AE158EA52F5B9E7D8813E81FD9F79470AE22F8F1CF9AEC820A78C69',
'h' :'48656C6C6F207468657265',
'sig1':'BE001AABAFFF976EC9016198FBFEA14CBEF96B000CCC0063D3324016F9E91FE80D8F9325812ED24DDB2B4D4CF4430B169880B3CE88313B53255BD4EC0378586F',
'sig2':'5E266F3F837BA204E3BBB6DBECC0611429D96F8C7CE8F4EFDF9D4CB681C2A954468A357BF4242CEC7418B51DFC081BCD21299EF5B5A0DDEF3A139A1817503DDE',
}
]
def test_generate_180(self):
self._test_random_key(180)
def test_encryption(self):
for tv in self.tve:
d = self.convert_tv(tv, True)
key = ElGamal.construct(d['key'])
ct = key._encrypt(d['pt'], d['k'])
self.assertEqual(ct[0], d['ct1'])
self.assertEqual(ct[1], d['ct2'])
def test_decryption(self):
for tv in self.tve:
d = self.convert_tv(tv, True)
key = ElGamal.construct(d['key'])
pt = key._decrypt((d['ct1'], d['ct2']))
self.assertEqual(pt, d['pt'])
def test_signing(self):
for tv in self.tvs:
d = self.convert_tv(tv, True)
key = ElGamal.construct(d['key'])
sig1, sig2 = key._sign(d['h'], d['k'])
self.assertEqual(sig1, d['sig1'])
self.assertEqual(sig2, d['sig2'])
def test_verification(self):
for tv in self.tvs:
d = self.convert_tv(tv, True)
key = ElGamal.construct(d['key'])
# Positive test
res = key._verify( d['h'], (d['sig1'],d['sig2']) )
self.assertTrue(res)
# Negative test
res = key._verify( d['h'], (d['sig1']+1,d['sig2']) )
self.assertFalse(res)
def test_bad_key3(self):
tup = tup0 = list(self.convert_tv(self.tvs[0], 1)['key'])[:3]
tup[0] += 1 # p += 1 (not prime)
self.assertRaises(ValueError, ElGamal.construct, tup)
tup = tup0
tup[1] = 1 # g = 1
self.assertRaises(ValueError, ElGamal.construct, tup)
tup = tup0
tup[2] = tup[0]*2 # y = 2*p
self.assertRaises(ValueError, ElGamal.construct, tup)
def test_bad_key4(self):
tup = tup0 = list(self.convert_tv(self.tvs[0], 1)['key'])
tup[3] += 1 # x += 1
self.assertRaises(ValueError, ElGamal.construct, tup)
def convert_tv(self, tv, as_longs=0):
"""Convert a test vector from textual form (hexadecimal ascii
to either integers or byte strings."""
key_comps = 'p','g','y','x'
tv2 = {}
for c in tv.keys():
tv2[c] = a2b_hex(tv[c])
if as_longs or c in key_comps or c in ('sig1','sig2'):
tv2[c] = bytes_to_long(tv2[c])
tv2['key']=[]
for c in key_comps:
tv2['key'] += [tv2[c]]
del tv2[c]
return tv2
def _test_random_key(self, bits):
elgObj = ElGamal.generate(bits, Random.new().read)
self._check_private_key(elgObj)
self._exercise_primitive(elgObj)
pub = elgObj.publickey()
self._check_public_key(pub)
self._exercise_public_primitive(elgObj)
def _check_private_key(self, elgObj):
# Check capabilities
self.assertTrue(elgObj.has_private())
# Sanity check key data
self.assertTrue(1<elgObj.g<(elgObj.p-1))
self.assertEqual(pow(elgObj.g, elgObj.p-1, elgObj.p), 1)
self.assertTrue(1<elgObj.x<(elgObj.p-1))
self.assertEqual(pow(elgObj.g, elgObj.x, elgObj.p), elgObj.y)
def _check_public_key(self, elgObj):
# Check capabilities
self.assertFalse(elgObj.has_private())
# Sanity check key data
self.assertTrue(1<elgObj.g<(elgObj.p-1))
self.assertEqual(pow(elgObj.g, elgObj.p-1, elgObj.p), 1)
def _exercise_primitive(self, elgObj):
# Test encryption/decryption
plaintext = 127218
ciphertext = elgObj._encrypt(plaintext, 123456789)
plaintextP = elgObj._decrypt(ciphertext)
self.assertEqual(plaintext, plaintextP)
# Test signature/verification
signature = elgObj._sign(plaintext, 987654321)
elgObj._verify(plaintext, signature)
def _exercise_public_primitive(self, elgObj):
plaintext = 92987276
ciphertext = elgObj._encrypt(plaintext, 123456789)
def get_tests(config={}):
tests = []
tests += list_test_cases(ElGamalTest)
return tests
if __name__ == '__main__':
suite = lambda: unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')

View File

@ -0,0 +1,324 @@
# -*- coding: utf-8 -*-
#
# SelfTest/PublicKey/test_RSA.py: Self-test for the RSA primitive
#
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
#
# ===================================================================
# The contents of this file are dedicated to the public domain. To
# the extent that dedication to the public domain is not available,
# everyone is granted a worldwide, perpetual, royalty-free,
# non-exclusive license to exercise all rights associated with the
# contents of this file for any purpose whatsoever.
# No rights are reserved.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# ===================================================================
"""Self-test suite for Crypto.PublicKey.RSA"""
__revision__ = "$Id$"
import os
import pickle
from pickle import PicklingError
from Crypto.Util.py3compat import *
import unittest
from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex
class RSATest(unittest.TestCase):
# Test vectors from "RSA-OAEP and RSA-PSS test vectors (.zip file)"
# ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
# See RSADSI's PKCS#1 page at
# http://www.rsa.com/rsalabs/node.asp?id=2125
# from oaep-int.txt
# TODO: PyCrypto treats the message as starting *after* the leading "00"
# TODO: That behaviour should probably be changed in the future.
plaintext = """
eb 7a 19 ac e9 e3 00 63 50 e3 29 50 4b 45 e2
ca 82 31 0b 26 dc d8 7d 5c 68 f1 ee a8 f5 52 67
c3 1b 2e 8b b4 25 1f 84 d7 e0 b2 c0 46 26 f5 af
f9 3e dc fb 25 c9 c2 b3 ff 8a e1 0e 83 9a 2d db
4c dc fe 4f f4 77 28 b4 a1 b7 c1 36 2b aa d2 9a
b4 8d 28 69 d5 02 41 21 43 58 11 59 1b e3 92 f9
82 fb 3e 87 d0 95 ae b4 04 48 db 97 2f 3a c1 4f
7b c2 75 19 52 81 ce 32 d2 f1 b7 6d 4d 35 3e 2d
"""
ciphertext = """
12 53 e0 4d c0 a5 39 7b b4 4a 7a b8 7e 9b f2 a0
39 a3 3d 1e 99 6f c8 2a 94 cc d3 00 74 c9 5d f7
63 72 20 17 06 9e 52 68 da 5d 1c 0b 4f 87 2c f6
53 c1 1d f8 23 14 a6 79 68 df ea e2 8d ef 04 bb
6d 84 b1 c3 1d 65 4a 19 70 e5 78 3b d6 eb 96 a0
24 c2 ca 2f 4a 90 fe 9f 2e f5 c9 c1 40 e5 bb 48
da 95 36 ad 87 00 c8 4f c9 13 0a de a7 4e 55 8d
51 a7 4d df 85 d8 b5 0d e9 68 38 d6 06 3e 09 55
"""
modulus = """
bb f8 2f 09 06 82 ce 9c 23 38 ac 2b 9d a8 71 f7
36 8d 07 ee d4 10 43 a4 40 d6 b6 f0 74 54 f5 1f
b8 df ba af 03 5c 02 ab 61 ea 48 ce eb 6f cd 48
76 ed 52 0d 60 e1 ec 46 19 71 9d 8a 5b 8b 80 7f
af b8 e0 a3 df c7 37 72 3e e6 b4 b7 d9 3a 25 84
ee 6a 64 9d 06 09 53 74 88 34 b2 45 45 98 39 4e
e0 aa b1 2d 7b 61 a5 1f 52 7a 9a 41 f6 c1 68 7f
e2 53 72 98 ca 2a 8f 59 46 f8 e5 fd 09 1d bd cb
"""
e = 0x11 # public exponent
prime_factor = """
c9 7f b1 f0 27 f4 53 f6 34 12 33 ea aa d1 d9 35
3f 6c 42 d0 88 66 b1 d0 5a 0f 20 35 02 8b 9d 86
98 40 b4 16 66 b4 2e 92 ea 0d a3 b4 32 04 b5 cf
ce 33 52 52 4d 04 16 a5 a4 41 e7 00 af 46 15 03
"""
def setUp(self):
global RSA, Random, bytes_to_long
from Crypto.PublicKey import RSA
from Crypto import Random
from Crypto.Util.number import bytes_to_long, inverse
self.n = bytes_to_long(a2b_hex(self.modulus))
self.p = bytes_to_long(a2b_hex(self.prime_factor))
# Compute q, d, and u from n, e, and p
self.q = self.n // self.p
self.d = inverse(self.e, (self.p-1)*(self.q-1))
self.u = inverse(self.p, self.q) # u = e**-1 (mod q)
self.rsa = RSA
def test_generate_1arg(self):
"""RSA (default implementation) generated key (1 argument)"""
rsaObj = self.rsa.generate(1024)
self._check_private_key(rsaObj)
self._exercise_primitive(rsaObj)
pub = rsaObj.public_key()
self._check_public_key(pub)
self._exercise_public_primitive(rsaObj)
def test_generate_2arg(self):
"""RSA (default implementation) generated key (2 arguments)"""
rsaObj = self.rsa.generate(1024, Random.new().read)
self._check_private_key(rsaObj)
self._exercise_primitive(rsaObj)
pub = rsaObj.public_key()
self._check_public_key(pub)
self._exercise_public_primitive(rsaObj)
def test_generate_3args(self):
rsaObj = self.rsa.generate(1024, Random.new().read,e=65537)
self._check_private_key(rsaObj)
self._exercise_primitive(rsaObj)
pub = rsaObj.public_key()
self._check_public_key(pub)
self._exercise_public_primitive(rsaObj)
self.assertEqual(65537,rsaObj.e)
def test_construct_2tuple(self):
"""RSA (default implementation) constructed key (2-tuple)"""
pub = self.rsa.construct((self.n, self.e))
self._check_public_key(pub)
self._check_encryption(pub)
def test_construct_3tuple(self):
"""RSA (default implementation) constructed key (3-tuple)"""
rsaObj = self.rsa.construct((self.n, self.e, self.d))
self._check_encryption(rsaObj)
self._check_decryption(rsaObj)
def test_construct_4tuple(self):
"""RSA (default implementation) constructed key (4-tuple)"""
rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p))
self._check_encryption(rsaObj)
self._check_decryption(rsaObj)
def test_construct_5tuple(self):
"""RSA (default implementation) constructed key (5-tuple)"""
rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p, self.q))
self._check_private_key(rsaObj)
self._check_encryption(rsaObj)
self._check_decryption(rsaObj)
def test_construct_6tuple(self):
"""RSA (default implementation) constructed key (6-tuple)"""
rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p, self.q, self.u))
self._check_private_key(rsaObj)
self._check_encryption(rsaObj)
self._check_decryption(rsaObj)
def test_construct_bad_key2(self):
tup = (self.n, 1)
self.assertRaises(ValueError, self.rsa.construct, tup)
# An even modulus is wrong
tup = (self.n+1, self.e)
self.assertRaises(ValueError, self.rsa.construct, tup)
def test_construct_bad_key3(self):
tup = (self.n, self.e, self.d+1)
self.assertRaises(ValueError, self.rsa.construct, tup)
def test_construct_bad_key5(self):
tup = (self.n, self.e, self.d, self.p, self.p)
self.assertRaises(ValueError, self.rsa.construct, tup)
tup = (self.p*self.p, self.e, self.p, self.p)
self.assertRaises(ValueError, self.rsa.construct, tup)
tup = (self.p*self.p, 3, self.p, self.q)
self.assertRaises(ValueError, self.rsa.construct, tup)
def test_construct_bad_key6(self):
tup = (self.n, self.e, self.d, self.p, self.q, 10)
self.assertRaises(ValueError, self.rsa.construct, tup)
from Crypto.Util.number import inverse
tup = (self.n, self.e, self.d, self.p, self.q, inverse(self.q, self.p))
self.assertRaises(ValueError, self.rsa.construct, tup)
def test_factoring(self):
rsaObj = self.rsa.construct([self.n, self.e, self.d])
self.assertTrue(rsaObj.p==self.p or rsaObj.p==self.q)
self.assertTrue(rsaObj.q==self.p or rsaObj.q==self.q)
self.assertTrue(rsaObj.q*rsaObj.p == self.n)
self.assertRaises(ValueError, self.rsa.construct, [self.n, self.e, self.n-1])
def test_repr(self):
rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p, self.q))
repr(rsaObj)
def test_serialization(self):
"""RSA keys are unpickable"""
rsa_key = self.rsa.generate(1024)
self.assertRaises(PicklingError, pickle.dumps, rsa_key)
def test_raw_rsa_boundary(self):
# The argument of every RSA raw operation (encrypt/decrypt) must be
# non-negative and no larger than the modulus
rsa_obj = self.rsa.generate(1024)
self.assertRaises(ValueError, rsa_obj._decrypt, rsa_obj.n)
self.assertRaises(ValueError, rsa_obj._decrypt_to_bytes, rsa_obj.n)
self.assertRaises(ValueError, rsa_obj._encrypt, rsa_obj.n)
self.assertRaises(ValueError, rsa_obj._decrypt, -1)
self.assertRaises(ValueError, rsa_obj._decrypt_to_bytes, -1)
self.assertRaises(ValueError, rsa_obj._encrypt, -1)
def test_size(self):
pub = self.rsa.construct((self.n, self.e))
self.assertEqual(pub.size_in_bits(), 1024)
self.assertEqual(pub.size_in_bytes(), 128)
def _check_private_key(self, rsaObj):
from Crypto.Math.Numbers import Integer
# Check capabilities
self.assertEqual(1, rsaObj.has_private())
# Sanity check key data
self.assertEqual(rsaObj.n, rsaObj.p * rsaObj.q) # n = pq
lcm = int(Integer(rsaObj.p-1).lcm(rsaObj.q-1))
self.assertEqual(1, rsaObj.d * rsaObj.e % lcm) # ed = 1 (mod LCM(p-1, q-1))
self.assertEqual(1, rsaObj.p * rsaObj.u % rsaObj.q) # pu = 1 (mod q)
self.assertEqual(1, rsaObj.p > 1) # p > 1
self.assertEqual(1, rsaObj.q > 1) # q > 1
self.assertEqual(1, rsaObj.e > 1) # e > 1
self.assertEqual(1, rsaObj.d > 1) # d > 1
self.assertEqual(rsaObj.u, rsaObj.invp)
self.assertEqual(1, rsaObj.q * rsaObj.invq % rsaObj.p)
def _check_public_key(self, rsaObj):
ciphertext = a2b_hex(self.ciphertext)
# Check capabilities
self.assertEqual(0, rsaObj.has_private())
# Check rsaObj.[ne] -> rsaObj.[ne] mapping
self.assertEqual(rsaObj.n, rsaObj.n)
self.assertEqual(rsaObj.e, rsaObj.e)
# Check that private parameters are all missing
self.assertEqual(0, hasattr(rsaObj, 'd'))
self.assertEqual(0, hasattr(rsaObj, 'p'))
self.assertEqual(0, hasattr(rsaObj, 'q'))
self.assertEqual(0, hasattr(rsaObj, 'u'))
# Sanity check key data
self.assertEqual(1, rsaObj.e > 1) # e > 1
# Public keys should not be able to sign or decrypt
self.assertRaises(TypeError, rsaObj._decrypt,
bytes_to_long(ciphertext))
self.assertRaises(TypeError, rsaObj._decrypt_to_bytes,
bytes_to_long(ciphertext))
# Check __eq__ and __ne__
self.assertEqual(rsaObj.public_key() == rsaObj.public_key(),True) # assert_
self.assertEqual(rsaObj.public_key() != rsaObj.public_key(),False) # assertFalse
self.assertEqual(rsaObj.publickey(), rsaObj.public_key())
def _exercise_primitive(self, rsaObj):
# Since we're using a randomly-generated key, we can't check the test
# vector, but we can make sure encryption and decryption are inverse
# operations.
ciphertext = bytes_to_long(a2b_hex(self.ciphertext))
# Test decryption
plaintext = rsaObj._decrypt(ciphertext)
# Test encryption (2 arguments)
new_ciphertext2 = rsaObj._encrypt(plaintext)
self.assertEqual(ciphertext, new_ciphertext2)
def _exercise_public_primitive(self, rsaObj):
plaintext = a2b_hex(self.plaintext)
# Test encryption (2 arguments)
new_ciphertext2 = rsaObj._encrypt(bytes_to_long(plaintext))
def _check_encryption(self, rsaObj):
plaintext = a2b_hex(self.plaintext)
ciphertext = a2b_hex(self.ciphertext)
# Test encryption
new_ciphertext2 = rsaObj._encrypt(bytes_to_long(plaintext))
self.assertEqual(bytes_to_long(ciphertext), new_ciphertext2)
def _check_decryption(self, rsaObj):
plaintext = bytes_to_long(a2b_hex(self.plaintext))
ciphertext = bytes_to_long(a2b_hex(self.ciphertext))
# Test plain decryption
new_plaintext = rsaObj._decrypt(ciphertext)
self.assertEqual(plaintext, new_plaintext)
def get_tests(config={}):
tests = []
tests += list_test_cases(RSATest)
return tests
if __name__ == '__main__':
suite = lambda: unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')
# vim:set ts=4 sw=4 sts=4 expandtab:

View File

@ -0,0 +1,385 @@
# ===================================================================
#
# Copyright (c) 2024, Helder Eijs <helderijs@gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
import os
import errno
import warnings
import unittest
from binascii import unhexlify
from unittest import SkipTest
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.Util.py3compat import tostr, FileNotFoundError
from Crypto.Util.asn1 import DerSequence, DerBitString
from Crypto.Hash import SHAKE128
from Crypto.PublicKey import ECC
try:
import pycryptodome_test_vectors # type: ignore
test_vectors_available = True
except ImportError:
test_vectors_available = False
def load_file(file_name, mode="rb"):
results = None
try:
if not test_vectors_available:
raise FileNotFoundError(errno.ENOENT,
os.strerror(errno.ENOENT),
file_name)
dir_comps = ("PublicKey", "ECC")
init_dir = os.path.dirname(pycryptodome_test_vectors.__file__)
full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name)
with open(full_file_name, mode) as file_in:
results = file_in.read()
except FileNotFoundError:
warnings.warn("Warning: skipping extended tests for ECC",
UserWarning,
stacklevel=2)
if results is None:
raise SkipTest("Missing %s" % file_name)
return results
def compact(lines):
ext = b"".join(lines)
return unhexlify(tostr(ext).replace(" ", "").replace(":", ""))
def create_ref_keys_x25519():
key_lines = load_file("ecc_x25519.txt").splitlines()
seed = compact(key_lines[5:8])
key = ECC.construct(curve="Curve25519", seed=seed)
return (key, key.public_key())
def get_fixed_prng():
return SHAKE128.new().update(b"SEED").read
def extract_bitstring_from_spki(data):
seq = DerSequence()
seq.decode(data)
bs = DerBitString()
bs.decode(seq[1])
return bs.value
class TestImport(unittest.TestCase):
def test_empty(self):
self.assertRaises(ValueError, ECC.import_key, b"")
def test_mismatch(self):
# Private key with X448 Object ID but X25519 key
mismatch_hex = "302e020100300506032b656f042204207009906b64ec727d5cb5c23007bf0425b3fd79014c6cd62ca3dddfcf0f278f79"
mismatch = unhexlify(mismatch_hex)
self.assertRaises(ValueError, ECC.import_key, mismatch)
class TestImport_Curve25519(unittest.TestCase):
def __init__(self, *args, **kwargs):
super(TestImport_Curve25519, self).__init__(*args, **kwargs)
self.ref_private, self.ref_public = create_ref_keys_x25519()
def test_import_public_der(self):
key_file = load_file("ecc_x25519_public.der")
key = ECC._import_subjectPublicKeyInfo(key_file)
self.assertEqual(self.ref_public, key)
key = ECC._import_der(key_file, None)
self.assertEqual(self.ref_public, key)
key = ECC.import_key(key_file)
self.assertEqual(self.ref_public, key)
def test_import_pkcs8_der(self):
key_file = load_file("ecc_x25519_private.der")
key = ECC._import_der(key_file, None)
self.assertEqual(self.ref_private, key)
key = ECC.import_key(key_file)
self.assertEqual(self.ref_private, key)
def test_import_private_pkcs8_encrypted_1(self):
key_file = load_file("ecc_x25519_private_p8.der")
key = ECC._import_der(key_file, "secret")
self.assertEqual(self.ref_private, key)
key = ECC.import_key(key_file, "secret")
self.assertEqual(self.ref_private, key)
def test_import_private_pkcs8_encrypted_2(self):
key_file = load_file("ecc_x25519_private_p8.pem")
key = ECC.import_key(key_file, "secret")
self.assertEqual(self.ref_private, key)
def test_import_private_pkcs8_encrypted_3(self):
key_file = load_file("ecc_x25519_private_p8_2.der")
key = ECC._import_der(key_file, "secret")
self.assertEqual(self.ref_private, key)
key = ECC.import_key(key_file, "secret")
self.assertEqual(self.ref_private, key)
def test_import_x509_der(self):
key_file = load_file("ecc_x25519_x509.der")
key = ECC._import_der(key_file, None)
self.assertEqual(self.ref_public, key)
key = ECC.import_key(key_file)
self.assertEqual(self.ref_public, key)
def test_import_public_pem(self):
key_file = load_file("ecc_x25519_public.pem")
key = ECC.import_key(key_file)
self.assertEqual(self.ref_public, key)
def test_import_private_pem(self):
key_file = load_file("ecc_x25519_private.pem")
key = ECC.import_key(key_file)
self.assertEqual(self.ref_private, key)
def test_import_private_pem_encrypted(self):
for algo in "des3", "aes128", "aes192", "aes256":
key_file = load_file("ecc_x25519_private_enc_%s.pem" % algo)
key = ECC.import_key(key_file, "secret")
self.assertEqual(self.ref_private, key)
key = ECC.import_key(tostr(key_file), b"secret")
self.assertEqual(self.ref_private, key)
def test_import_x509_pem(self):
key_file = load_file("ecc_x25519_x509.pem")
key = ECC.import_key(key_file)
self.assertEqual(self.ref_public, key)
class TestExport_Curve25519(unittest.TestCase):
def __init__(self, *args, **kwargs):
super(TestExport_Curve25519, self).__init__(*args, **kwargs)
self.ref_private, self.ref_public = create_ref_keys_x25519()
def test_export_public_der(self):
key_file = load_file("ecc_x25519_public.der")
encoded = self.ref_public._export_subjectPublicKeyInfo(True)
self.assertEqual(key_file, encoded)
encoded = self.ref_public.export_key(format="DER")
self.assertEqual(key_file, encoded)
encoded = self.ref_public.export_key(format="DER", compress=False)
self.assertEqual(key_file, encoded)
def test_export_private_pkcs8_clear(self):
key_file = load_file("ecc_x25519_private.der")
encoded = self.ref_private._export_pkcs8()
self.assertEqual(key_file, encoded)
# ---
encoded = self.ref_private.export_key(format="DER")
self.assertEqual(key_file, encoded)
self.assertRaises(ValueError, self.ref_private.export_key,
format="DER", use_pkcs8=False)
def test_export_private_pkcs8_encrypted(self):
encoded = self.ref_private._export_pkcs8(passphrase="secret",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
# This should prove that the output is password-protected
self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None)
decoded = ECC._import_pkcs8(encoded, "secret")
self.assertEqual(self.ref_private, decoded)
# ---
encoded = self.ref_private.export_key(format="DER",
passphrase="secret",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
decoded = ECC.import_key(encoded, "secret")
self.assertEqual(self.ref_private, decoded)
# ---
encoded = self.ref_private.export_key(format="DER",
passphrase="secret",
protection="PBKDF2WithHMAC-SHA256AndAES128-CBC",
prot_params={'iteration_count': 123})
decoded = ECC.import_key(encoded, "secret")
self.assertEqual(self.ref_private, decoded)
def test_export_public_pem(self):
key_file_ref = load_file("ecc_x25519_public.pem", "rt").strip()
key_file = self.ref_public.export_key(format="PEM").strip()
self.assertEqual(key_file_ref, key_file)
def test_export_private_pem_clear(self):
key_file = load_file("ecc_x25519_private.pem", "rt").strip()
encoded = self.ref_private.export_key(format="PEM").strip()
self.assertEqual(key_file, encoded)
def test_export_private_pem_encrypted(self):
encoded = self.ref_private.export_key(format="PEM",
passphrase=b"secret",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
# This should prove that the output is password-protected
self.assertRaises(ValueError, ECC.import_key, encoded)
assert "ENCRYPTED PRIVATE KEY" in encoded
decoded = ECC.import_key(encoded, "secret")
self.assertEqual(self.ref_private, decoded)
def test_export_raw(self):
encoded = self.ref_public.export_key(format='raw')
self.assertEqual(len(encoded), 32)
self.assertEqual(encoded, unhexlify(b'ff7561ef60c9c8a757f6d6372ec14142c9be208d0e719136d8d3c715dfcf7e15'))
def test_prng(self):
# Test that password-protected containers use the provided PRNG
encoded1 = self.ref_private.export_key(format="PEM",
passphrase="secret",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC",
randfunc=get_fixed_prng())
encoded2 = self.ref_private.export_key(format="PEM",
passphrase="secret",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC",
randfunc=get_fixed_prng())
self.assertEqual(encoded1, encoded2)
def test_byte_or_string_passphrase(self):
encoded1 = self.ref_private.export_key(format="PEM",
passphrase="secret",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC",
randfunc=get_fixed_prng())
encoded2 = self.ref_private.export_key(format="PEM",
passphrase=b"secret",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC",
randfunc=get_fixed_prng())
self.assertEqual(encoded1, encoded2)
def test_error_params1(self):
# Unknown format
self.assertRaises(ValueError, self.ref_private.export_key, format="XXX")
# Missing 'protection' parameter when PKCS#8 is used
self.assertRaises(ValueError,
self.ref_private.export_key,
format="PEM",
passphrase="secret")
# Empty password
self.assertRaises(ValueError,
self.ref_private.export_key,
format="PEM",
passphrase="",
use_pkcs8=False)
self.assertRaises(ValueError,
self.ref_private.export_key,
format="PEM",
passphrase="",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
# No private keys with OpenSSH
self.assertRaises(ValueError,
self.ref_private.export_key,
format="OpenSSH",
passphrase="secret")
class TestImport_Curve25519_Weak(unittest.TestCase):
def test_weak_pem(self):
p = 2**255 - 19
weak_x = (0,
1,
325606250916557431795983626356110631294008115727848805560023387167927233504,
39382357235489614581723060781553021112529911719440698176882885853963445705823,
p - 1,
p,
p + 1,
p + 325606250916557431795983626356110631294008115727848805560023387167927233504,
p + 39382357235489614581723060781553021112529911719440698176882885853963445705823,
p * 2 - 1,
p * 2,
p * 2 + 1)
for x in weak_x:
low_order_point = ECC.EccXPoint(x, "curve25519")
weak_key = ECC.EccKey(point=low_order_point, curve="curve25519")
encoded = weak_key.export_key(format="PEM")
self.assertRaises(ValueError,
ECC.import_key,
encoded)
def get_tests(config={}):
tests = []
try:
tests += list_test_cases(TestImport)
tests += list_test_cases(TestImport_Curve25519)
tests += list_test_cases(TestExport_Curve25519)
tests += list_test_cases(TestImport_Curve25519_Weak)
except SkipTest:
pass
return tests
if __name__ == '__main__':
def suit():
return unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')

View File

@ -0,0 +1,351 @@
# This file is licensed under the BSD 2-Clause License.
# See https://opensource.org/licenses/BSD-2-Clause for details.
import os
import errno
import warnings
import unittest
from binascii import unhexlify
from unittest import SkipTest
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.Util.py3compat import tostr, FileNotFoundError
from Crypto.Util.asn1 import DerSequence, DerBitString
from Crypto.Hash import SHAKE128
from Crypto.PublicKey import ECC
try:
import pycryptodome_test_vectors # type: ignore
test_vectors_available = True
except ImportError:
test_vectors_available = False
def load_file(file_name, mode="rb"):
results = None
try:
if not test_vectors_available:
raise FileNotFoundError(errno.ENOENT,
os.strerror(errno.ENOENT),
file_name)
dir_comps = ("PublicKey", "ECC")
init_dir = os.path.dirname(pycryptodome_test_vectors.__file__)
full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name)
with open(full_file_name, mode) as file_in:
results = file_in.read()
except FileNotFoundError:
warnings.warn("Warning: skipping extended tests for ECC",
UserWarning,
stacklevel=2)
if results is None:
raise SkipTest("Missing %s" % file_name)
return results
def compact(lines):
ext = b"".join(lines)
return unhexlify(tostr(ext).replace(" ", "").replace(":", ""))
def create_ref_keys_x448():
key_lines = load_file("ecc_x448.txt").splitlines()
seed = compact(key_lines[6:10])
key = ECC.construct(curve="Curve448", seed=seed)
return (key, key.public_key())
def get_fixed_prng():
return SHAKE128.new().update(b"SEED").read
def extract_bitstring_from_spki(data):
seq = DerSequence()
seq.decode(data)
bs = DerBitString()
bs.decode(seq[1])
return bs.value
class TestImport(unittest.TestCase):
def test_empty(self):
self.assertRaises(ValueError, ECC.import_key, b"")
def test_mismatch(self):
# Private key with X448 Object ID but X448 key
mismatch_hex = "302e020100300506032b656f042204207009906b64ec727d5cb5c23007bf0425b3fd79014c6cd62ca3dddfcf0f278f79"
mismatch = unhexlify(mismatch_hex)
self.assertRaises(ValueError, ECC.import_key, mismatch)
class TestImport_Curve448(unittest.TestCase):
def __init__(self, *args, **kwargs):
super(TestImport_Curve448, self).__init__(*args, **kwargs)
self.ref_private, self.ref_public = create_ref_keys_x448()
def test_import_public_der(self):
key_file = load_file("ecc_x448_public.der")
key = ECC._import_subjectPublicKeyInfo(key_file)
self.assertEqual(self.ref_public, key)
key = ECC._import_der(key_file, None)
self.assertEqual(self.ref_public, key)
key = ECC.import_key(key_file)
self.assertEqual(self.ref_public, key)
def test_import_pkcs8_der(self):
key_file = load_file("ecc_x448_private.der")
key = ECC._import_der(key_file, None)
self.assertEqual(self.ref_private, key)
key = ECC.import_key(key_file)
self.assertEqual(self.ref_private, key)
def test_import_private_pkcs8_encrypted_1(self):
key_file = load_file("ecc_x448_private_p8.der")
key = ECC._import_der(key_file, "secret")
self.assertEqual(self.ref_private, key)
key = ECC.import_key(key_file, "secret")
self.assertEqual(self.ref_private, key)
def test_import_private_pkcs8_encrypted_2(self):
key_file = load_file("ecc_x448_private_p8.pem")
key = ECC.import_key(key_file, "secret")
self.assertEqual(self.ref_private, key)
def test_import_private_pkcs8_encrypted_3(self):
key_file = load_file("ecc_x448_private_p8_2.der")
key = ECC._import_der(key_file, "secret")
self.assertEqual(self.ref_private, key)
key = ECC.import_key(key_file, "secret")
self.assertEqual(self.ref_private, key)
def test_import_x509_der(self):
key_file = load_file("ecc_x448_x509.der")
key = ECC._import_der(key_file, None)
self.assertEqual(self.ref_public, key)
key = ECC.import_key(key_file)
self.assertEqual(self.ref_public, key)
def test_import_public_pem(self):
key_file = load_file("ecc_x448_public.pem")
key = ECC.import_key(key_file)
self.assertEqual(self.ref_public, key)
def test_import_private_pem(self):
key_file = load_file("ecc_x448_private.pem")
key = ECC.import_key(key_file)
self.assertEqual(self.ref_private, key)
def test_import_private_pem_encrypted(self):
for algo in "des3", "aes128", "aes192", "aes256":
key_file = load_file("ecc_x448_private_enc_%s.pem" % algo)
key = ECC.import_key(key_file, "secret")
self.assertEqual(self.ref_private, key)
key = ECC.import_key(tostr(key_file), b"secret")
self.assertEqual(self.ref_private, key)
def test_import_x509_pem(self):
key_file = load_file("ecc_x448_x509.pem")
key = ECC.import_key(key_file)
self.assertEqual(self.ref_public, key)
class TestExport_Curve448(unittest.TestCase):
def __init__(self, *args, **kwargs):
super(TestExport_Curve448, self).__init__(*args, **kwargs)
self.ref_private, self.ref_public = create_ref_keys_x448()
def test_export_public_der(self):
key_file = load_file("ecc_x448_public.der")
encoded = self.ref_public._export_subjectPublicKeyInfo(True)
self.assertEqual(key_file, encoded)
encoded = self.ref_public.export_key(format="DER")
self.assertEqual(key_file, encoded)
encoded = self.ref_public.export_key(format="DER", compress=False)
self.assertEqual(key_file, encoded)
def test_export_private_pkcs8_clear(self):
key_file = load_file("ecc_x448_private.der")
encoded = self.ref_private._export_pkcs8()
self.assertEqual(key_file, encoded)
# ---
encoded = self.ref_private.export_key(format="DER")
self.assertEqual(key_file, encoded)
self.assertRaises(ValueError, self.ref_private.export_key,
format="DER", use_pkcs8=False)
def test_export_private_pkcs8_encrypted(self):
encoded = self.ref_private._export_pkcs8(passphrase="secret",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
# This should prove that the output is password-protected
self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None)
decoded = ECC._import_pkcs8(encoded, "secret")
self.assertEqual(self.ref_private, decoded)
# ---
encoded = self.ref_private.export_key(format="DER",
passphrase="secret",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
decoded = ECC.import_key(encoded, "secret")
self.assertEqual(self.ref_private, decoded)
# ---
encoded = self.ref_private.export_key(format="DER",
passphrase="secret",
protection="PBKDF2WithHMAC-SHA256AndAES128-CBC",
prot_params={'iteration_count': 123})
decoded = ECC.import_key(encoded, "secret")
self.assertEqual(self.ref_private, decoded)
def test_export_public_pem(self):
key_file_ref = load_file("ecc_x448_public.pem", "rt").strip()
key_file = self.ref_public.export_key(format="PEM").strip()
self.assertEqual(key_file_ref, key_file)
def test_export_private_pem_clear(self):
key_file = load_file("ecc_x448_private.pem", "rt").strip()
encoded = self.ref_private.export_key(format="PEM").strip()
self.assertEqual(key_file, encoded)
def test_export_private_pem_encrypted(self):
encoded = self.ref_private.export_key(format="PEM",
passphrase=b"secret",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
# This should prove that the output is password-protected
self.assertRaises(ValueError, ECC.import_key, encoded)
assert "ENCRYPTED PRIVATE KEY" in encoded
decoded = ECC.import_key(encoded, "secret")
self.assertEqual(self.ref_private, decoded)
def test_export_raw(self):
encoded = self.ref_public.export_key(format='raw')
self.assertEqual(len(encoded), 56)
self.assertEqual(encoded, unhexlify(b'e2abae24ab8f65b01969e61f84fee615b525f413a90e3d727f71d0ffe60fb1d0a1a0285f2a7fd88789206e0aa4f3e9fcb9e4ba5d644e691e'))
def test_prng(self):
# Test that password-protected containers use the provided PRNG
encoded1 = self.ref_private.export_key(format="PEM",
passphrase="secret",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC",
randfunc=get_fixed_prng())
encoded2 = self.ref_private.export_key(format="PEM",
passphrase="secret",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC",
randfunc=get_fixed_prng())
self.assertEqual(encoded1, encoded2)
def test_byte_or_string_passphrase(self):
encoded1 = self.ref_private.export_key(format="PEM",
passphrase="secret",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC",
randfunc=get_fixed_prng())
encoded2 = self.ref_private.export_key(format="PEM",
passphrase=b"secret",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC",
randfunc=get_fixed_prng())
self.assertEqual(encoded1, encoded2)
def test_error_params1(self):
# Unknown format
self.assertRaises(ValueError, self.ref_private.export_key, format="XXX")
# Missing 'protection' parameter when PKCS#8 is used
self.assertRaises(ValueError,
self.ref_private.export_key,
format="PEM",
passphrase="secret")
# Empty password
self.assertRaises(ValueError,
self.ref_private.export_key,
format="PEM",
passphrase="",
use_pkcs8=False)
self.assertRaises(ValueError,
self.ref_private.export_key,
format="PEM",
passphrase="",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
# No private keys with OpenSSH
self.assertRaises(ValueError,
self.ref_private.export_key,
format="OpenSSH",
passphrase="secret")
class TestImport_Curve448_Weak(unittest.TestCase):
def test_weak_pem(self):
p = 2**448 - 2**224 - 1
weak_x = (0,
1,
p - 1,
p,
p + 1)
for x in weak_x:
low_order_point = ECC.EccXPoint(x, "curve448")
weak_key = ECC.EccKey(point=low_order_point, curve="curve448")
encoded = weak_key.export_key(format="PEM")
self.assertRaises(ValueError,
ECC.import_key,
encoded)
def get_tests(config={}):
tests = []
try:
tests += list_test_cases(TestImport)
tests += list_test_cases(TestImport_Curve448)
tests += list_test_cases(TestExport_Curve448)
tests += list_test_cases(TestImport_Curve448_Weak)
except SkipTest:
pass
return tests
if __name__ == '__main__':
def suit():
return unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')

View File

@ -0,0 +1,554 @@
# -*- coding: utf-8 -*-
#
# SelfTest/PublicKey/test_import_DSA.py: Self-test for importing DSA keys
#
# ===================================================================
# The contents of this file are dedicated to the public domain. To
# the extent that dedication to the public domain is not available,
# everyone is granted a worldwide, perpetual, royalty-free,
# non-exclusive license to exercise all rights associated with the
# contents of this file for any purpose whatsoever.
# No rights are reserved.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# ===================================================================
import unittest
import re
from Crypto.PublicKey import DSA
from Crypto.SelfTest.st_common import *
from Crypto.Util.py3compat import *
from binascii import unhexlify
class ImportKeyTests(unittest.TestCase):
y = 92137165128186062214622779787483327510946462589285775188003362705875131352591574106484271700740858696583623951844732128165434284507709057439633739849986759064015013893156866539696757799934634945787496920169462601722830899660681779448742875054459716726855443681559131362852474817534616736104831095601710736729
p = 162452170958135306109773853318304545923250830605675936228618290525164105310663722368377131295055868997377338797580997938253236213714988311430600065853662861806894003694743806769284131194035848116051021923956699231855223389086646903420682639786976554552864568460372266462812137447840653688476258666833303658691
q = 988791743931120302950649732173330531512663554851
g = 85583152299197514738065570254868711517748965097380456700369348466136657764813442044039878840094809620913085570225318356734366886985903212775602770761953571967834823306046501307810937486758039063386311593890777319935391363872375452381836756832784184928202587843258855704771836753434368484556809100537243908232
x = 540873410045082450874416847965843801027716145253
def setUp(self):
# It is easier to write test vectors in text form,
# and convert them to byte strigs dynamically here
for mname, mvalue in ImportKeyTests.__dict__.items():
if mname[:4] in ('der_', 'pem_', 'ssh_'):
if mname[:4] == 'der_':
mvalue = unhexlify(tobytes(mvalue))
mvalue = tobytes(mvalue)
setattr(self, mname, mvalue)
# 1. SubjectPublicKeyInfo
der_public=\
'308201b73082012b06072a8648ce3804013082011e02818100e756ee1717f4b6'+\
'794c7c214724a19763742c45572b4b3f8ff3b44f3be9f44ce039a2757695ec91'+\
'5697da74ef914fcd1b05660e2419c761d639f45d2d79b802dbd23e7ab8b81b47'+\
'9a380e1f30932584ba2a0b955032342ebc83cb5ca906e7b0d7cd6fe656cecb4c'+\
'8b5a77123a8c6750a481e3b06057aff6aa6eba620b832d60c3021500ad32f48c'+\
'd3ae0c45a198a61fa4b5e20320763b2302818079dfdc3d614fe635fceb7eaeae'+\
'3718dc2efefb45282993ac6749dc83c223d8c1887296316b3b0b54466cf444f3'+\
'4b82e3554d0b90a778faaf1306f025dae6a3e36c7f93dd5bac4052b92370040a'+\
'ca70b8d5820599711900efbc961812c355dd9beffe0981da85c5548074b41c56'+\
'ae43fd300d89262e4efd89943f99a651b03888038185000281810083352a69a1'+\
'32f34843d2a0eb995bff4e2f083a73f0049d2c91ea2f0ce43d144abda48199e4'+\
'b003c570a8af83303d45105f606c5c48d925a40ed9c2630c2fa4cdbf838539de'+\
'b9a29f919085f2046369f627ca84b2cb1e2c7940564b670f963ab1164d4e2ca2'+\
'bf6ffd39f12f548928bf4d2d1b5e6980b4f1be4c92a91986fba559'
def testImportKey1(self):
key_obj = DSA.importKey(self.der_public)
self.assertFalse(key_obj.has_private())
self.assertEqual(self.y, key_obj.y)
self.assertEqual(self.p, key_obj.p)
self.assertEqual(self.q, key_obj.q)
self.assertEqual(self.g, key_obj.g)
def testExportKey1(self):
tup = (self.y, self.g, self.p, self.q)
key = DSA.construct(tup)
encoded = key.export_key('DER')
self.assertEqual(self.der_public, encoded)
# 2.
pem_public="""\
-----BEGIN PUBLIC KEY-----
MIIBtzCCASsGByqGSM44BAEwggEeAoGBAOdW7hcX9LZ5THwhRyShl2N0LEVXK0s/
j/O0Tzvp9EzgOaJ1dpXskVaX2nTvkU/NGwVmDiQZx2HWOfRdLXm4AtvSPnq4uBtH
mjgOHzCTJYS6KguVUDI0LryDy1ypBuew181v5lbOy0yLWncSOoxnUKSB47BgV6/2
qm66YguDLWDDAhUArTL0jNOuDEWhmKYfpLXiAyB2OyMCgYB539w9YU/mNfzrfq6u
NxjcLv77RSgpk6xnSdyDwiPYwYhyljFrOwtURmz0RPNLguNVTQuQp3j6rxMG8CXa
5qPjbH+T3VusQFK5I3AECspwuNWCBZlxGQDvvJYYEsNV3Zvv/gmB2oXFVIB0tBxW
rkP9MA2JJi5O/YmUP5mmUbA4iAOBhQACgYEAgzUqaaEy80hD0qDrmVv/Ti8IOnPw
BJ0skeovDOQ9FEq9pIGZ5LADxXCor4MwPUUQX2BsXEjZJaQO2cJjDC+kzb+DhTne
uaKfkZCF8gRjafYnyoSyyx4seUBWS2cPljqxFk1OLKK/b/058S9UiSi/TS0bXmmA
tPG+TJKpGYb7pVk=
-----END PUBLIC KEY-----"""
def testImportKey2(self):
for pem in (self.pem_public, tostr(self.pem_public)):
key_obj = DSA.importKey(pem)
self.assertFalse(key_obj.has_private())
self.assertEqual(self.y, key_obj.y)
self.assertEqual(self.p, key_obj.p)
self.assertEqual(self.q, key_obj.q)
self.assertEqual(self.g, key_obj.g)
def testExportKey2(self):
tup = (self.y, self.g, self.p, self.q)
key = DSA.construct(tup)
encoded = key.export_key('PEM')
self.assertEqual(self.pem_public, encoded)
# 3. OpenSSL/OpenSSH format
der_private=\
'308201bb02010002818100e756ee1717f4b6794c7c214724a19763742c45572b'+\
'4b3f8ff3b44f3be9f44ce039a2757695ec915697da74ef914fcd1b05660e2419'+\
'c761d639f45d2d79b802dbd23e7ab8b81b479a380e1f30932584ba2a0b955032'+\
'342ebc83cb5ca906e7b0d7cd6fe656cecb4c8b5a77123a8c6750a481e3b06057'+\
'aff6aa6eba620b832d60c3021500ad32f48cd3ae0c45a198a61fa4b5e2032076'+\
'3b2302818079dfdc3d614fe635fceb7eaeae3718dc2efefb45282993ac6749dc'+\
'83c223d8c1887296316b3b0b54466cf444f34b82e3554d0b90a778faaf1306f0'+\
'25dae6a3e36c7f93dd5bac4052b92370040aca70b8d5820599711900efbc9618'+\
'12c355dd9beffe0981da85c5548074b41c56ae43fd300d89262e4efd89943f99'+\
'a651b038880281810083352a69a132f34843d2a0eb995bff4e2f083a73f0049d'+\
'2c91ea2f0ce43d144abda48199e4b003c570a8af83303d45105f606c5c48d925'+\
'a40ed9c2630c2fa4cdbf838539deb9a29f919085f2046369f627ca84b2cb1e2c'+\
'7940564b670f963ab1164d4e2ca2bf6ffd39f12f548928bf4d2d1b5e6980b4f1'+\
'be4c92a91986fba55902145ebd9a3f0b82069d98420986b314215025756065'
def testImportKey3(self):
key_obj = DSA.importKey(self.der_private)
self.assertTrue(key_obj.has_private())
self.assertEqual(self.y, key_obj.y)
self.assertEqual(self.p, key_obj.p)
self.assertEqual(self.q, key_obj.q)
self.assertEqual(self.g, key_obj.g)
self.assertEqual(self.x, key_obj.x)
def testExportKey3(self):
tup = (self.y, self.g, self.p, self.q, self.x)
key = DSA.construct(tup)
encoded = key.export_key('DER', pkcs8=False)
self.assertEqual(self.der_private, encoded)
# 4.
pem_private="""\
-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQDnVu4XF/S2eUx8IUckoZdjdCxFVytLP4/ztE876fRM4DmidXaV
7JFWl9p075FPzRsFZg4kGcdh1jn0XS15uALb0j56uLgbR5o4Dh8wkyWEuioLlVAy
NC68g8tcqQbnsNfNb+ZWzstMi1p3EjqMZ1CkgeOwYFev9qpuumILgy1gwwIVAK0y
9IzTrgxFoZimH6S14gMgdjsjAoGAed/cPWFP5jX8636urjcY3C7++0UoKZOsZ0nc
g8Ij2MGIcpYxazsLVEZs9ETzS4LjVU0LkKd4+q8TBvAl2uaj42x/k91brEBSuSNw
BArKcLjVggWZcRkA77yWGBLDVd2b7/4JgdqFxVSAdLQcVq5D/TANiSYuTv2JlD+Z
plGwOIgCgYEAgzUqaaEy80hD0qDrmVv/Ti8IOnPwBJ0skeovDOQ9FEq9pIGZ5LAD
xXCor4MwPUUQX2BsXEjZJaQO2cJjDC+kzb+DhTneuaKfkZCF8gRjafYnyoSyyx4s
eUBWS2cPljqxFk1OLKK/b/058S9UiSi/TS0bXmmAtPG+TJKpGYb7pVkCFF69mj8L
ggadmEIJhrMUIVAldWBl
-----END DSA PRIVATE KEY-----"""
def testImportKey4(self):
for pem in (self.pem_private, tostr(self.pem_private)):
key_obj = DSA.importKey(pem)
self.assertTrue(key_obj.has_private())
self.assertEqual(self.y, key_obj.y)
self.assertEqual(self.p, key_obj.p)
self.assertEqual(self.q, key_obj.q)
self.assertEqual(self.g, key_obj.g)
self.assertEqual(self.x, key_obj.x)
def testExportKey4(self):
tup = (self.y, self.g, self.p, self.q, self.x)
key = DSA.construct(tup)
encoded = key.export_key('PEM', pkcs8=False)
self.assertEqual(self.pem_private, encoded)
# 5. PKCS8 (unencrypted)
der_pkcs8=\
'3082014a0201003082012b06072a8648ce3804013082011e02818100e756ee17'+\
'17f4b6794c7c214724a19763742c45572b4b3f8ff3b44f3be9f44ce039a27576'+\
'95ec915697da74ef914fcd1b05660e2419c761d639f45d2d79b802dbd23e7ab8'+\
'b81b479a380e1f30932584ba2a0b955032342ebc83cb5ca906e7b0d7cd6fe656'+\
'cecb4c8b5a77123a8c6750a481e3b06057aff6aa6eba620b832d60c3021500ad'+\
'32f48cd3ae0c45a198a61fa4b5e20320763b2302818079dfdc3d614fe635fceb'+\
'7eaeae3718dc2efefb45282993ac6749dc83c223d8c1887296316b3b0b54466c'+\
'f444f34b82e3554d0b90a778faaf1306f025dae6a3e36c7f93dd5bac4052b923'+\
'70040aca70b8d5820599711900efbc961812c355dd9beffe0981da85c5548074'+\
'b41c56ae43fd300d89262e4efd89943f99a651b03888041602145ebd9a3f0b82'+\
'069d98420986b314215025756065'
def testImportKey5(self):
key_obj = DSA.importKey(self.der_pkcs8)
self.assertTrue(key_obj.has_private())
self.assertEqual(self.y, key_obj.y)
self.assertEqual(self.p, key_obj.p)
self.assertEqual(self.q, key_obj.q)
self.assertEqual(self.g, key_obj.g)
self.assertEqual(self.x, key_obj.x)
def testExportKey5(self):
tup = (self.y, self.g, self.p, self.q, self.x)
key = DSA.construct(tup)
encoded = key.export_key('DER')
self.assertEqual(self.der_pkcs8, encoded)
encoded = key.export_key('DER', pkcs8=True)
self.assertEqual(self.der_pkcs8, encoded)
# 6.
pem_pkcs8="""\
-----BEGIN PRIVATE KEY-----
MIIBSgIBADCCASsGByqGSM44BAEwggEeAoGBAOdW7hcX9LZ5THwhRyShl2N0LEVX
K0s/j/O0Tzvp9EzgOaJ1dpXskVaX2nTvkU/NGwVmDiQZx2HWOfRdLXm4AtvSPnq4
uBtHmjgOHzCTJYS6KguVUDI0LryDy1ypBuew181v5lbOy0yLWncSOoxnUKSB47Bg
V6/2qm66YguDLWDDAhUArTL0jNOuDEWhmKYfpLXiAyB2OyMCgYB539w9YU/mNfzr
fq6uNxjcLv77RSgpk6xnSdyDwiPYwYhyljFrOwtURmz0RPNLguNVTQuQp3j6rxMG
8CXa5qPjbH+T3VusQFK5I3AECspwuNWCBZlxGQDvvJYYEsNV3Zvv/gmB2oXFVIB0
tBxWrkP9MA2JJi5O/YmUP5mmUbA4iAQWAhRevZo/C4IGnZhCCYazFCFQJXVgZQ==
-----END PRIVATE KEY-----"""
def testImportKey6(self):
for pem in (self.pem_pkcs8, tostr(self.pem_pkcs8)):
key_obj = DSA.importKey(pem)
self.assertTrue(key_obj.has_private())
self.assertEqual(self.y, key_obj.y)
self.assertEqual(self.p, key_obj.p)
self.assertEqual(self.q, key_obj.q)
self.assertEqual(self.g, key_obj.g)
self.assertEqual(self.x, key_obj.x)
def testExportKey6(self):
tup = (self.y, self.g, self.p, self.q, self.x)
key = DSA.construct(tup)
encoded = key.export_key('PEM')
self.assertEqual(self.pem_pkcs8, encoded)
encoded = key.export_key('PEM', pkcs8=True)
self.assertEqual(self.pem_pkcs8, encoded)
# 7. OpenSSH/RFC4253
ssh_pub="""ssh-dss AAAAB3NzaC1kc3MAAACBAOdW7hcX9LZ5THwhRyShl2N0LEVXK0s/j/O0Tzvp9EzgOaJ1dpXskVaX2nTvkU/NGwVmDiQZx2HWOfRdLXm4AtvSPnq4uBtHmjgOHzCTJYS6KguVUDI0LryDy1ypBuew181v5lbOy0yLWncSOoxnUKSB47BgV6/2qm66YguDLWDDAAAAFQCtMvSM064MRaGYph+kteIDIHY7IwAAAIB539w9YU/mNfzrfq6uNxjcLv77RSgpk6xnSdyDwiPYwYhyljFrOwtURmz0RPNLguNVTQuQp3j6rxMG8CXa5qPjbH+T3VusQFK5I3AECspwuNWCBZlxGQDvvJYYEsNV3Zvv/gmB2oXFVIB0tBxWrkP9MA2JJi5O/YmUP5mmUbA4iAAAAIEAgzUqaaEy80hD0qDrmVv/Ti8IOnPwBJ0skeovDOQ9FEq9pIGZ5LADxXCor4MwPUUQX2BsXEjZJaQO2cJjDC+kzb+DhTneuaKfkZCF8gRjafYnyoSyyx4seUBWS2cPljqxFk1OLKK/b/058S9UiSi/TS0bXmmAtPG+TJKpGYb7pVk="""
def testImportKey7(self):
for ssh in (self.ssh_pub, tostr(self.ssh_pub)):
key_obj = DSA.importKey(ssh)
self.assertFalse(key_obj.has_private())
self.assertEqual(self.y, key_obj.y)
self.assertEqual(self.p, key_obj.p)
self.assertEqual(self.q, key_obj.q)
self.assertEqual(self.g, key_obj.g)
def testExportKey7(self):
tup = (self.y, self.g, self.p, self.q)
key = DSA.construct(tup)
encoded = key.export_key('OpenSSH')
self.assertEqual(self.ssh_pub, encoded)
# 8. Encrypted OpenSSL/OpenSSH
pem_private_encrypted="""\
-----BEGIN DSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,70B6908939D65E9F2EB999E8729788CE
4V6GHRDpCrdZ8MBjbyp5AlGUrjvr2Pn2e2zVxy5RBt4FBj9/pa0ae0nnyUPMLSUU
kKyOR0topRYTVRLElm4qVrb5uNZ3hRwfbklr+pSrB7O9eHz9V5sfOQxyODS07JxK
k1OdOs70/ouMXLF9EWfAZOmWUccZKHNblUwg1p1UrZIz5jXw4dUE/zqhvXh6d+iC
ADsICaBCjCrRQJKDp50h3+ndQjkYBKVH+pj8TiQ79U7lAvdp3+iMghQN6YXs9mdI
gFpWw/f97oWM4GHZFqHJ+VSMNFjBiFhAvYV587d7Lk4dhD8sCfbxj42PnfRgUItc
nnPqHxmhMQozBWzYM4mQuo3XbF2WlsNFbOzFVyGhw1Bx1s91qvXBVWJh2ozrW0s6
HYDV7ZkcTml/4kjA/d+mve6LZ8kuuR1qCiZx6rkffhh1gDN/1Xz3HVvIy/dQ+h9s
5zp7PwUoWbhqp3WCOr156P6gR8qo7OlT6wMh33FSXK/mxikHK136fV2shwTKQVII
rJBvXpj8nACUmi7scKuTWGeUoXa+dwTZVVe+b+L2U1ZM7+h/neTJiXn7u99PFUwu
xVJtxaV37m3aXxtCsPnbBg==
-----END DSA PRIVATE KEY-----"""
def testImportKey8(self):
for pem in (self.pem_private_encrypted, tostr(self.pem_private_encrypted)):
key_obj = DSA.importKey(pem, "PWDTEST")
self.assertTrue(key_obj.has_private())
self.assertEqual(self.y, key_obj.y)
self.assertEqual(self.p, key_obj.p)
self.assertEqual(self.q, key_obj.q)
self.assertEqual(self.g, key_obj.g)
self.assertEqual(self.x, key_obj.x)
def testExportKey8(self):
tup = (self.y, self.g, self.p, self.q, self.x)
key = DSA.construct(tup)
encoded = key.export_key('PEM', pkcs8=False, passphrase="PWDTEST")
key = DSA.importKey(encoded, "PWDTEST")
self.assertEqual(self.y, key.y)
self.assertEqual(self.p, key.p)
self.assertEqual(self.q, key.q)
self.assertEqual(self.g, key.g)
self.assertEqual(self.x, key.x)
# 9. Encrypted PKCS8
# pbeWithMD5AndDES-CBC
pem_pkcs8_encrypted="""\
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIBcTAbBgkqhkiG9w0BBQMwDgQI0GC3BJ/jSw8CAggABIIBUHc1cXZpExIE9tC7
7ryiW+5ihtF2Ekurq3e408GYSAu5smJjN2bvQXmzRFBz8W38K8eMf1sbWroZ4+zn
kZSbb9nSm5kAa8lR2+oF2k+WRswMR/PTC3f/D9STO2X0QxdrzKgIHEcSGSHp5jTx
aVvbkCDHo9vhBTl6S3ogZ48As/MEro76+9igUwJ1jNhIQZPJ7e20QH5qDpQFFJN4
CKl2ENSEuwGiqBszItFy4dqH0g63ZGZV/xt9wSO9Rd7SK/EbA/dklOxBa5Y/VItM
gnIhs9XDMoGYyn6F023EicNJm6g/bVQk81BTTma4tm+12TKGdYm+QkeZvCOMZylr
Wv67cKwO3cAXt5C3QXMDgYR64XvuaT5h7C0igMp2afSXJlnbHEbFxQVJlv83T4FM
eZ4k+NQDbEL8GiHmFxzDWQAuPPZKJWEEEV2p/To+WOh+kSDHQw==
-----END ENCRYPTED PRIVATE KEY-----"""
def testImportKey9(self):
for pem in (self.pem_pkcs8_encrypted, tostr(self.pem_pkcs8_encrypted)):
key_obj = DSA.importKey(pem, "PWDTEST")
self.assertTrue(key_obj.has_private())
self.assertEqual(self.y, key_obj.y)
self.assertEqual(self.p, key_obj.p)
self.assertEqual(self.q, key_obj.q)
self.assertEqual(self.g, key_obj.g)
self.assertEqual(self.x, key_obj.x)
# 10. Encrypted PKCS8
# pkcs5PBES2 /
# pkcs5PBKDF2 (rounds=1000, salt=D725BF1B6B8239F4) /
# des-EDE3-CBC (iv=27A1C66C42AFEECE)
#
der_pkcs8_encrypted=\
'30820196304006092a864886f70d01050d3033301b06092a864886f70d01050c'+\
'300e0408d725bf1b6b8239f4020203e8301406082a864886f70d0307040827a1'+\
'c66c42afeece048201505cacfde7bf8edabb3e0d387950dc872662ea7e9b1ed4'+\
'400d2e7e6186284b64668d8d0328c33a9d9397e6f03df7cb68268b0a06b4e22f'+\
'7d132821449ecf998a8b696dbc6dd2b19e66d7eb2edfeb4153c1771d49702395'+\
'4f36072868b5fcccf93413a5ac4b2eb47d4b3f681c6bd67ae363ed776f45ae47'+\
'174a00098a7c930a50f820b227ddf50f9742d8e950d02586ff2dac0e3c372248'+\
'e5f9b6a7a02f4004f20c87913e0f7b52bccc209b95d478256a890b31d4c9adec'+\
'21a4d157a179a93a3dad06f94f3ce486b46dfa7fc15fd852dd7680bbb2f17478'+\
'7e71bd8dbaf81eca7518d76c1d26256e95424864ba45ca5d47d7c5a421be02fa'+\
'b94ab01e18593f66cf9094eb5c94b9ecf3aa08b854a195cf87612fbe5e96c426'+\
'2b0d573e52dc71ba3f5e468c601e816c49b7d32c698b22175e89aaef0c443770'+\
'5ef2f88a116d99d8e2869a4fd09a771b84b49e4ccb79aadcb1c9'
def testImportKey10(self):
key_obj = DSA.importKey(self.der_pkcs8_encrypted, "PWDTEST")
self.assertTrue(key_obj.has_private())
self.assertEqual(self.y, key_obj.y)
self.assertEqual(self.p, key_obj.p)
self.assertEqual(self.q, key_obj.q)
self.assertEqual(self.g, key_obj.g)
self.assertEqual(self.x, key_obj.x)
def testExportKey10(self):
tup = (self.y, self.g, self.p, self.q, self.x)
key = DSA.construct(tup)
randfunc = BytesIO(unhexlify(b("27A1C66C42AFEECE") + b("D725BF1B6B8239F4"))).read
encoded = key.export_key('DER', pkcs8=True, passphrase="PWDTEST", randfunc=randfunc)
self.assertEqual(self.der_pkcs8_encrypted, encoded)
# ----
def testImportError1(self):
self.assertRaises(ValueError, DSA.importKey, self.der_pkcs8_encrypted, "wrongpwd")
def testExportError2(self):
tup = (self.y, self.g, self.p, self.q, self.x)
key = DSA.construct(tup)
self.assertRaises(ValueError, key.export_key, 'DER', pkcs8=False, passphrase="PWDTEST")
def test_import_key(self):
"""Verify importKey is an alias to import_key"""
key_obj = DSA.import_key(self.der_public)
self.assertFalse(key_obj.has_private())
self.assertEqual(self.y, key_obj.y)
self.assertEqual(self.p, key_obj.p)
self.assertEqual(self.q, key_obj.q)
self.assertEqual(self.g, key_obj.g)
def test_exportKey(self):
tup = (self.y, self.g, self.p, self.q, self.x)
key = DSA.construct(tup)
self.assertEqual(key.exportKey(), key.export_key())
def test_import_empty(self):
self.assertRaises(ValueError, DSA.import_key, b'')
class ImportKeyFromX509Cert(unittest.TestCase):
def test_x509v1(self):
# Sample V1 certificate with a 1024 bit DSA key
x509_v1_cert = """
-----BEGIN CERTIFICATE-----
MIIDUjCCArsCAQIwDQYJKoZIhvcNAQEFBQAwfjENMAsGA1UEChMEQWNtZTELMAkG
A1UECxMCUkQxHDAaBgkqhkiG9w0BCQEWDXNwYW1AYWNtZS5vcmcxEzARBgNVBAcT
Ck1ldHJvcG9saXMxETAPBgNVBAgTCE5ldyBZb3JrMQswCQYDVQQGEwJVUzENMAsG
A1UEAxMEdGVzdDAeFw0xNDA3MTEyMDM4NDNaFw0xNzA0MDYyMDM4NDNaME0xCzAJ
BgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazENMAsGA1UEChMEQWNtZTELMAkG
A1UECxMCUkQxDzANBgNVBAMTBnBvbGFuZDCCAbYwggErBgcqhkjOOAQBMIIBHgKB
gQDOrN4Ox4+t3T6wKeHfhzArhcrNEFMQ4Ss+4PIKyimDy9Bn64WPkL1B/9dvYIga
23GLu6tVJmXo6EdJnVOHEMhr99EeOwuDWWeP7Awq7RSlKEejokr4BEzMTW/tExSD
cO6/GI7xzh0eTH+VTTPDfyrJMYCkh0rJAfCP+5xrmPNetwIVALtXYOV1yoRrzJ2Q
M5uEjidH6GiZAoGAfUqA1SAm5g5U68SILMVX9l5rq0OpB0waBMpJQ31/R/yXNDqo
c3gGWZTOJFU4IzwNpGhrGNADUByz/lc1SAOAdEJIr0JVrhbGewQjB4pWqoLGbBKz
RoavTNDc/zD7SYa12evWDHADwvlXoeQg+lWop1zS8OqaDC7aLGKpWN3/m8kDgYQA
AoGAKoirPAfcp1rbbl4y2FFAIktfW8f4+T7d2iKSg73aiVfujhNOt1Zz1lfC0NI2
eonLWO3tAM4XGKf1TLjb5UXngGn40okPsaA81YE6ZIKm20ywjlOY3QkAEdMaLVY3
9PJvM8RGB9m7pLKxyHfGMfF40MVN4222zKeGp7xhM0CNiCUwDQYJKoZIhvcNAQEF
BQADgYEAfbNZfpYa2KlALEM1FZnwvQDvJHntHz8LdeJ4WM7CXDlKi67wY2HKM30w
s2xej75imkVOFd1kF2d0A8sjfriXLVIt1Hwq9ANZomhu4Edx0xpH8tqdh/bDtnM2
TmduZNY9OWkb07h0CtWD6Zt8fhRllVsSSrlWd/2or7FXNC5weFQ=
-----END CERTIFICATE-----
""".strip()
# DSA public key as dumped by openssl
y_str = """
2a:88:ab:3c:07:dc:a7:5a:db:6e:5e:32:d8:51:40:
22:4b:5f:5b:c7:f8:f9:3e:dd:da:22:92:83:bd:da:
89:57:ee:8e:13:4e:b7:56:73:d6:57:c2:d0:d2:36:
7a:89:cb:58:ed:ed:00:ce:17:18:a7:f5:4c:b8:db:
e5:45:e7:80:69:f8:d2:89:0f:b1:a0:3c:d5:81:3a:
64:82:a6:db:4c:b0:8e:53:98:dd:09:00:11:d3:1a:
2d:56:37:f4:f2:6f:33:c4:46:07:d9:bb:a4:b2:b1:
c8:77:c6:31:f1:78:d0:c5:4d:e3:6d:b6:cc:a7:86:
a7:bc:61:33:40:8d:88:25
"""
p_str = """
00:ce:ac:de:0e:c7:8f:ad:dd:3e:b0:29:e1:df:87:
30:2b:85:ca:cd:10:53:10:e1:2b:3e:e0:f2:0a:ca:
29:83:cb:d0:67:eb:85:8f:90:bd:41:ff:d7:6f:60:
88:1a:db:71:8b:bb:ab:55:26:65:e8:e8:47:49:9d:
53:87:10:c8:6b:f7:d1:1e:3b:0b:83:59:67:8f:ec:
0c:2a:ed:14:a5:28:47:a3:a2:4a:f8:04:4c:cc:4d:
6f:ed:13:14:83:70:ee:bf:18:8e:f1:ce:1d:1e:4c:
7f:95:4d:33:c3:7f:2a:c9:31:80:a4:87:4a:c9:01:
f0:8f:fb:9c:6b:98:f3:5e:b7
"""
q_str = """
00:bb:57:60:e5:75:ca:84:6b:cc:9d:90:33:9b:84:
8e:27:47:e8:68:99
"""
g_str = """
7d:4a:80:d5:20:26:e6:0e:54:eb:c4:88:2c:c5:57:
f6:5e:6b:ab:43:a9:07:4c:1a:04:ca:49:43:7d:7f:
47:fc:97:34:3a:a8:73:78:06:59:94:ce:24:55:38:
23:3c:0d:a4:68:6b:18:d0:03:50:1c:b3:fe:57:35:
48:03:80:74:42:48:af:42:55:ae:16:c6:7b:04:23:
07:8a:56:aa:82:c6:6c:12:b3:46:86:af:4c:d0:dc:
ff:30:fb:49:86:b5:d9:eb:d6:0c:70:03:c2:f9:57:
a1:e4:20:fa:55:a8:a7:5c:d2:f0:ea:9a:0c:2e:da:
2c:62:a9:58:dd:ff:9b:c9
"""
key = DSA.importKey(x509_v1_cert)
for comp_name in ('y', 'p', 'q', 'g'):
comp_str = locals()[comp_name + "_str"]
comp = int(re.sub("[^0-9a-f]", "", comp_str), 16)
self.assertEqual(getattr(key, comp_name), comp)
self.assertFalse(key.has_private())
def test_x509v3(self):
# Sample V3 certificate with a 1024 bit DSA key
x509_v3_cert = """
-----BEGIN CERTIFICATE-----
MIIFhjCCA26gAwIBAgIBAzANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEL
MAkGA1UECAwCTUQxEjAQBgNVBAcMCUJhbHRpbW9yZTEQMA4GA1UEAwwHVGVzdCBD
QTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxlLmNvbTAeFw0xNDA3MTMyMDUz
MjBaFw0xNzA0MDgyMDUzMjBaMEAxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNRDES
MBAGA1UEBwwJQmFsdGltb3JlMRAwDgYDVQQDDAdhdXN0cmlhMIIBtjCCASsGByqG
SM44BAEwggEeAoGBALfd8gyEpVPA0ZI69Kp3nyJcu5N0ZZ3K1K9hleQLNqKEcZOh
7a/C2J1TPdmHTLJ0rAwBZ1nWxnARSgRphziGDFspKCYQwYcSMz8KoFgvXbXpuchy
oFACiQ2LqZnc5MakuLQtLcQciSYGYj3zmZdYMoa904F1aDWr+DxQI6DVC3/bAhUA
hqXMCJ6fQK3G2O9S3/CC/yVZXCsCgYBRXROl3R2khX7l10LQjDEgo3B1IzjXU/jP
McMBl6XO+nBJXxr/scbq8Ajiv7LTnGpSjgryHtvfj887kfvo8QbSS3kp3vq5uSqI
ui7E7r3jguWaLj616AG1HWOctXJUjqsiabZwsp2h09gHTzmHEXBOmiARu8xFxKAH
xsuo7onAbwOBhAACgYBylWjWSnKHE8mHx1A5m/0GQx6xnhWIe3+MJAnEhRGxA2J4
SCsfWU0OwglIQToh1z5uUU9oDi9cYgNPBevOFRnDhc2yaJY6VAYnI+D+6J5IU6Yd
0iaG/iSc4sV4bFr0axcPpse3SN0XaQxiKeSFBfFnoMqL+dd9Gb3QPZSllBcVD6OB
1TCB0jAdBgNVHQ4EFgQUx5wN0Puotv388M9Tp/fsPbZpzAUwHwYDVR0jBBgwFoAU
a0hkif3RMaraiWtsOOZZlLu9wJwwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwSgYD
VR0RBEMwQYILZXhhbXBsZS5jb22CD3d3dy5leGFtcGxlLmNvbYIQbWFpbC5leGFt
cGxlLmNvbYIPZnRwLmV4YW1wbGUuY29tMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NM
IEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAgEAyWf1TiJI
aNEIA9o/PG8/JiGASTS2/HBVTJbkq03k6NkJVk/GxC1DPziTUJ+CdWlHWcAi1EOW
Ach3QxNDRrVfCOfCMDgElIO1094/reJgdFYG00LRi8QkRJuxANV7YS4tLudhyHJC
kR2lhdMNmEuzWK+s2y+5cLrdm7qdvdENQCcV67uvGPx4sc+EaE7x13SczKjWBtbo
QCs6JTOW+EkPRl4Zo27K4OIZ43/J+GxvwU9QUVH3wPVdbbLNw+QeTFBYMTEcxyc4
kv50HPBFaithziXBFyvdIs19FjkFzu0Uz/e0zb1+vMzQlJMD94HVOrMnIj5Sb2cL
KKdYXS4uhxFJmdV091Xur5JkYYwEzuaGav7J3zOzYutrIGTgDluLCvA+VQkRcTsy
jZ065SkY/v+38QHp+cmm8WRluupJTs8wYzVp6Fu0iFaaK7ztFmaZmHpiPIfDFjva
aCIgzzT5NweJd/b71A2SyzHXJ14zBXsr1PMylMp2TpHIidhuuNuQL6I0HaollB4M
Z3FsVBMhVDw4Z76qnFPr8mZE2tar33hSlJI/3pS/bBiukuBk8U7VB0X8OqaUnP3C
7b2Z4G8GtqDVcKGMzkvMjT4n9rKd/Le+qHSsQOGO9W/0LB7UDAZSwUsfAPnoBgdS
5t9tIomLCOstByXi+gGZue1TcdCa3Ph4kO0=
-----END CERTIFICATE-----
""".strip()
# DSA public key as dumped by openssl
y_str = """
72:95:68:d6:4a:72:87:13:c9:87:c7:50:39:9b:fd:
06:43:1e:b1:9e:15:88:7b:7f:8c:24:09:c4:85:11:
b1:03:62:78:48:2b:1f:59:4d:0e:c2:09:48:41:3a:
21:d7:3e:6e:51:4f:68:0e:2f:5c:62:03:4f:05:eb:
ce:15:19:c3:85:cd:b2:68:96:3a:54:06:27:23:e0:
fe:e8:9e:48:53:a6:1d:d2:26:86:fe:24:9c:e2:c5:
78:6c:5a:f4:6b:17:0f:a6:c7:b7:48:dd:17:69:0c:
62:29:e4:85:05:f1:67:a0:ca:8b:f9:d7:7d:19:bd:
d0:3d:94:a5:94:17:15:0f
"""
p_str = """
00:b7:dd:f2:0c:84:a5:53:c0:d1:92:3a:f4:aa:77:
9f:22:5c:bb:93:74:65:9d:ca:d4:af:61:95:e4:0b:
36:a2:84:71:93:a1:ed:af:c2:d8:9d:53:3d:d9:87:
4c:b2:74:ac:0c:01:67:59:d6:c6:70:11:4a:04:69:
87:38:86:0c:5b:29:28:26:10:c1:87:12:33:3f:0a:
a0:58:2f:5d:b5:e9:b9:c8:72:a0:50:02:89:0d:8b:
a9:99:dc:e4:c6:a4:b8:b4:2d:2d:c4:1c:89:26:06:
62:3d:f3:99:97:58:32:86:bd:d3:81:75:68:35:ab:
f8:3c:50:23:a0:d5:0b:7f:db
"""
q_str = """
00:86:a5:cc:08:9e:9f:40:ad:c6:d8:ef:52:df:f0:
82:ff:25:59:5c:2b
"""
g_str = """
51:5d:13:a5:dd:1d:a4:85:7e:e5:d7:42:d0:8c:31:
20:a3:70:75:23:38:d7:53:f8:cf:31:c3:01:97:a5:
ce:fa:70:49:5f:1a:ff:b1:c6:ea:f0:08:e2:bf:b2:
d3:9c:6a:52:8e:0a:f2:1e:db:df:8f:cf:3b:91:fb:
e8:f1:06:d2:4b:79:29:de:fa:b9:b9:2a:88:ba:2e:
c4:ee:bd:e3:82:e5:9a:2e:3e:b5:e8:01:b5:1d:63:
9c:b5:72:54:8e:ab:22:69:b6:70:b2:9d:a1:d3:d8:
07:4f:39:87:11:70:4e:9a:20:11:bb:cc:45:c4:a0:
07:c6:cb:a8:ee:89:c0:6f
"""
key = DSA.importKey(x509_v3_cert)
for comp_name in ('y', 'p', 'q', 'g'):
comp_str = locals()[comp_name + "_str"]
comp = int(re.sub("[^0-9a-f]", "", comp_str), 16)
self.assertEqual(getattr(key, comp_name), comp)
self.assertFalse(key.has_private())
if __name__ == '__main__':
unittest.main()
def get_tests(config={}):
tests = []
tests += list_test_cases(ImportKeyTests)
tests += list_test_cases(ImportKeyFromX509Cert)
return tests
if __name__ == '__main__':
suite = lambda: unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,636 @@
# -*- coding: utf-8 -*-
#
# SelfTest/PublicKey/test_importKey.py: Self-test for importing RSA keys
#
# ===================================================================
# The contents of this file are dedicated to the public domain. To
# the extent that dedication to the public domain is not available,
# everyone is granted a worldwide, perpetual, royalty-free,
# non-exclusive license to exercise all rights associated with the
# contents of this file for any purpose whatsoever.
# No rights are reserved.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# ===================================================================
import os
import re
import errno
import warnings
import unittest
from unittest import SkipTest
from Crypto.PublicKey import RSA
from Crypto.SelfTest.st_common import a2b_hex, list_test_cases
from Crypto.IO import PEM
from Crypto.Util.py3compat import b, tostr, FileNotFoundError
from Crypto.Util.number import inverse
from Crypto.Util import asn1
try:
import pycryptodome_test_vectors # type: ignore
test_vectors_available = True
except ImportError:
test_vectors_available = False
def load_file(file_name, mode="rb"):
results = None
try:
if not test_vectors_available:
raise FileNotFoundError(errno.ENOENT,
os.strerror(errno.ENOENT),
file_name)
dir_comps = ("PublicKey", "RSA")
init_dir = os.path.dirname(pycryptodome_test_vectors.__file__)
full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name)
with open(full_file_name, mode) as file_in:
results = file_in.read()
except FileNotFoundError:
warnings.warn("Skipping tests for RSA based on %s" % file_name,
UserWarning,
stacklevel=2)
if results is None:
raise SkipTest("Missing %s" % file_name)
return results
def der2pem(der, text='PUBLIC'):
import binascii
chunks = [binascii.b2a_base64(der[i:i+48]) for i in range(0, len(der), 48)]
pem = b('-----BEGIN %s KEY-----\n' % text)
pem += b('').join(chunks)
pem += b('-----END %s KEY-----' % text)
return pem
class ImportKeyTests(unittest.TestCase):
# 512-bit RSA key generated with openssl
rsaKeyPEM = u'''-----BEGIN RSA PRIVATE KEY-----
MIIBOwIBAAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+TLr7UkvEtFrRhDDKMtuII
q19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQJACUSDEp8RTe32ftq8IwG8
Wojl5mAd1wFiIOrZ/Uv8b963WJOJiuQcVN29vxU5+My9GPZ7RA3hrDBEAoHUDPrI
OQIhAPIPLz4dphiD9imAkivY31Rc5AfHJiQRA7XixTcjEkojAiEAyh/pJHks/Mlr
+rdPNEpotBjfV4M4BkgGAA/ipcmaAjcCIQCHvhwwKVBLzzTscT2HeUdEeBMoiXXK
JACAr3sJQJGxIQIgarRp+m1WSKV1MciwMaTOnbU7wxFs9DP1pva76lYBzgUCIQC9
n0CnZCJ6IZYqSt0H5N7+Q+2Ro64nuwV/OSQfM6sBwQ==
-----END RSA PRIVATE KEY-----'''
# As above, but this is actually an unencrypted PKCS#8 key
rsaKeyPEM8 = u'''-----BEGIN PRIVATE KEY-----
MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvx4nkAqgiyNRGlwS
ga5tkzEsPv6RP5MuvtSS8S0WtGEMMoy24girX0WsvilQgzKY8xIsGfeEkt7fQPDj
wZAzhQIDAQABAkAJRIMSnxFN7fZ+2rwjAbxaiOXmYB3XAWIg6tn9S/xv3rdYk4mK
5BxU3b2/FTn4zL0Y9ntEDeGsMEQCgdQM+sg5AiEA8g8vPh2mGIP2KYCSK9jfVFzk
B8cmJBEDteLFNyMSSiMCIQDKH+kkeSz8yWv6t080Smi0GN9XgzgGSAYAD+KlyZoC
NwIhAIe+HDApUEvPNOxxPYd5R0R4EyiJdcokAICvewlAkbEhAiBqtGn6bVZIpXUx
yLAxpM6dtTvDEWz0M/Wm9rvqVgHOBQIhAL2fQKdkInohlipK3Qfk3v5D7ZGjrie7
BX85JB8zqwHB
-----END PRIVATE KEY-----'''
# The same RSA private key as in rsaKeyPEM, but now encrypted
rsaKeyEncryptedPEM = (
# PEM encryption
# With DES and passphrase 'test'
('test', u'''-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-CBC,AF8F9A40BD2FA2FC
Ckl9ex1kaVEWhYC2QBmfaF+YPiR4NFkRXA7nj3dcnuFEzBnY5XULupqQpQI3qbfA
u8GYS7+b3toWWiHZivHbAAUBPDIZG9hKDyB9Sq2VMARGsX1yW1zhNvZLIiVJzUHs
C6NxQ1IJWOXzTew/xM2I26kPwHIvadq+/VaT8gLQdjdH0jOiVNaevjWnLgrn1mLP
BCNRMdcexozWtAFNNqSzfW58MJL2OdMi21ED184EFytIc1BlB+FZiGZduwKGuaKy
9bMbdb/1PSvsSzPsqW7KSSrTw6MgJAFJg6lzIYvR5F4poTVBxwBX3+EyEmShiaNY
IRX3TgQI0IjrVuLmvlZKbGWP18FXj7I7k9tSsNOOzllTTdq3ny5vgM3A+ynfAaxp
dysKznQ6P+IoqML1WxAID4aGRMWka+uArOJ148Rbj9s=
-----END RSA PRIVATE KEY-----'''),
# PKCS8 encryption
('winter', u'''-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIBpjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIeZIsbW3O+JcCAggA
MBQGCCqGSIb3DQMHBAgSM2p0D8FilgSCAWBhFyP2tiGKVpGj3mO8qIBzinU60ApR
3unvP+N6j7LVgnV2lFGaXbJ6a1PbQXe+2D6DUyBLo8EMXrKKVLqOMGkFMHc0UaV6
R6MmrsRDrbOqdpTuVRW+NVd5J9kQQh4xnfU/QrcPPt7vpJvSf4GzG0n666Ki50OV
M/feuVlIiyGXY6UWdVDpcOV72cq02eNUs/1JWdh2uEBvA9fCL0c07RnMrdT+CbJQ
NjJ7f8ULtp7xvR9O3Al/yJ4Wv3i4VxF1f3MCXzhlUD4I0ONlr0kJWgeQ80q/cWhw
ntvgJwnCn2XR1h6LA8Wp+0ghDTsL2NhJpWd78zClGhyU4r3hqu1XDjoXa7YCXCix
jCV15+ViDJzlNCwg+W6lRg18sSLkCT7alviIE0U5tHc6UPbbHwT5QqAxAABaP+nZ
CGqJGyiwBzrKebjgSm/KRd4C91XqcsysyH2kKPfT51MLAoD4xelOURBP
-----END ENCRYPTED PRIVATE KEY-----'''
),
)
rsaPublicKeyPEM = u'''-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+T
Lr7UkvEtFrRhDDKMtuIIq19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQ==
-----END PUBLIC KEY-----'''
# Obtained using 'ssh-keygen -i -m PKCS8 -f rsaPublicKeyPEM'
rsaPublicKeyOpenSSH = b('''ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQC/HieQCqCLI1EaXBKBrm2TMSw+/pE/ky6+1JLxLRa0YQwyjLbiCKtfRay+KVCDMpjzEiwZ94SS3t9A8OPBkDOF comment\n''')
# The private key, in PKCS#1 format encoded with DER
rsaKeyDER = a2b_hex(
'''3082013b020100024100bf1e27900aa08b23511a5c1281ae6d93312c3efe
913f932ebed492f12d16b4610c328cb6e208ab5f45acbe2950833298f312
2c19f78492dedf40f0e3c190338502030100010240094483129f114dedf6
7edabc2301bc5a88e5e6601dd7016220ead9fd4bfc6fdeb75893898ae41c
54ddbdbf1539f8ccbd18f67b440de1ac30440281d40cfac839022100f20f
2f3e1da61883f62980922bd8df545ce407c726241103b5e2c53723124a23
022100ca1fe924792cfcc96bfab74f344a68b418df578338064806000fe2
a5c99a023702210087be1c3029504bcf34ec713d877947447813288975ca
240080af7b094091b12102206ab469fa6d5648a57531c8b031a4ce9db53b
c3116cf433f5a6f6bbea5601ce05022100bd9f40a764227a21962a4add07
e4defe43ed91a3ae27bb057f39241f33ab01c1
'''.replace(" ",""))
# The private key, in unencrypted PKCS#8 format encoded with DER
rsaKeyDER8 = a2b_hex(
'''30820155020100300d06092a864886f70d01010105000482013f3082013
b020100024100bf1e27900aa08b23511a5c1281ae6d93312c3efe913f932
ebed492f12d16b4610c328cb6e208ab5f45acbe2950833298f3122c19f78
492dedf40f0e3c190338502030100010240094483129f114dedf67edabc2
301bc5a88e5e6601dd7016220ead9fd4bfc6fdeb75893898ae41c54ddbdb
f1539f8ccbd18f67b440de1ac30440281d40cfac839022100f20f2f3e1da
61883f62980922bd8df545ce407c726241103b5e2c53723124a23022100c
a1fe924792cfcc96bfab74f344a68b418df578338064806000fe2a5c99a0
23702210087be1c3029504bcf34ec713d877947447813288975ca240080a
f7b094091b12102206ab469fa6d5648a57531c8b031a4ce9db53bc3116cf
433f5a6f6bbea5601ce05022100bd9f40a764227a21962a4add07e4defe4
3ed91a3ae27bb057f39241f33ab01c1
'''.replace(" ",""))
rsaPublicKeyDER = a2b_hex(
'''305c300d06092a864886f70d0101010500034b003048024100bf1e27900a
a08b23511a5c1281ae6d93312c3efe913f932ebed492f12d16b4610c328c
b6e208ab5f45acbe2950833298f3122c19f78492dedf40f0e3c190338502
03010001
'''.replace(" ",""))
n = int('BF 1E 27 90 0A A0 8B 23 51 1A 5C 12 81 AE 6D 93 31 2C 3E FE 91 3F 93 2E BE D4 92 F1 2D 16 B4 61 0C 32 8C B6 E2 08 AB 5F 45 AC BE 29 50 83 32 98 F3 12 2C 19 F7 84 92 DE DF 40 F0 E3 C1 90 33 85'.replace(" ",""),16)
e = 65537
d = int('09 44 83 12 9F 11 4D ED F6 7E DA BC 23 01 BC 5A 88 E5 E6 60 1D D7 01 62 20 EA D9 FD 4B FC 6F DE B7 58 93 89 8A E4 1C 54 DD BD BF 15 39 F8 CC BD 18 F6 7B 44 0D E1 AC 30 44 02 81 D4 0C FA C8 39'.replace(" ",""),16)
p = int('00 F2 0F 2F 3E 1D A6 18 83 F6 29 80 92 2B D8 DF 54 5C E4 07 C7 26 24 11 03 B5 E2 C5 37 23 12 4A 23'.replace(" ",""),16)
q = int('00 CA 1F E9 24 79 2C FC C9 6B FA B7 4F 34 4A 68 B4 18 DF 57 83 38 06 48 06 00 0F E2 A5 C9 9A 02 37'.replace(" ",""),16)
# This is q^{-1} mod p). fastmath and slowmath use pInv (p^{-1}
# mod q) instead!
qInv = int('00 BD 9F 40 A7 64 22 7A 21 96 2A 4A DD 07 E4 DE FE 43 ED 91 A3 AE 27 BB 05 7F 39 24 1F 33 AB 01 C1'.replace(" ",""),16)
pInv = inverse(p,q)
def testImportKey1(self):
"""Verify import of RSAPrivateKey DER SEQUENCE"""
key = RSA.importKey(self.rsaKeyDER)
self.assertTrue(key.has_private())
self.assertEqual(key.n, self.n)
self.assertEqual(key.e, self.e)
self.assertEqual(key.d, self.d)
self.assertEqual(key.p, self.p)
self.assertEqual(key.q, self.q)
def testImportKey2(self):
"""Verify import of SubjectPublicKeyInfo DER SEQUENCE"""
key = RSA.importKey(self.rsaPublicKeyDER)
self.assertFalse(key.has_private())
self.assertEqual(key.n, self.n)
self.assertEqual(key.e, self.e)
def testImportKey3unicode(self):
"""Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode"""
key = RSA.importKey(self.rsaKeyPEM)
self.assertEqual(key.has_private(),True) # assert_
self.assertEqual(key.n, self.n)
self.assertEqual(key.e, self.e)
self.assertEqual(key.d, self.d)
self.assertEqual(key.p, self.p)
self.assertEqual(key.q, self.q)
def testImportKey3bytes(self):
"""Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as byte string"""
key = RSA.importKey(b(self.rsaKeyPEM))
self.assertEqual(key.has_private(),True) # assert_
self.assertEqual(key.n, self.n)
self.assertEqual(key.e, self.e)
self.assertEqual(key.d, self.d)
self.assertEqual(key.p, self.p)
self.assertEqual(key.q, self.q)
def testImportKey4unicode(self):
"""Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode"""
key = RSA.importKey(self.rsaPublicKeyPEM)
self.assertEqual(key.has_private(),False) # assertFalse
self.assertEqual(key.n, self.n)
self.assertEqual(key.e, self.e)
def testImportKey4bytes(self):
"""Verify import of SubjectPublicKeyInfo DER SEQUENCE, encoded with PEM as byte string"""
key = RSA.importKey(b(self.rsaPublicKeyPEM))
self.assertEqual(key.has_private(),False) # assertFalse
self.assertEqual(key.n, self.n)
self.assertEqual(key.e, self.e)
def testImportKey5(self):
"""Verifies that the imported key is still a valid RSA pair"""
key = RSA.importKey(self.rsaKeyPEM)
idem = key._encrypt(key._decrypt(89))
self.assertEqual(idem, 89)
def testImportKey6(self):
"""Verifies that the imported key is still a valid RSA pair"""
key = RSA.importKey(self.rsaKeyDER)
idem = key._encrypt(key._decrypt(65))
self.assertEqual(idem, 65)
def testImportKey7(self):
"""Verify import of OpenSSH public key"""
key = RSA.importKey(self.rsaPublicKeyOpenSSH)
self.assertEqual(key.n, self.n)
self.assertEqual(key.e, self.e)
def testImportKey8(self):
"""Verify import of encrypted PrivateKeyInfo DER SEQUENCE"""
for t in self.rsaKeyEncryptedPEM:
key = RSA.importKey(t[1], t[0])
self.assertTrue(key.has_private())
self.assertEqual(key.n, self.n)
self.assertEqual(key.e, self.e)
self.assertEqual(key.d, self.d)
self.assertEqual(key.p, self.p)
self.assertEqual(key.q, self.q)
def testImportKey9(self):
"""Verify import of unencrypted PrivateKeyInfo DER SEQUENCE"""
key = RSA.importKey(self.rsaKeyDER8)
self.assertTrue(key.has_private())
self.assertEqual(key.n, self.n)
self.assertEqual(key.e, self.e)
self.assertEqual(key.d, self.d)
self.assertEqual(key.p, self.p)
self.assertEqual(key.q, self.q)
def testImportKey10(self):
"""Verify import of unencrypted PrivateKeyInfo DER SEQUENCE, encoded with PEM"""
key = RSA.importKey(self.rsaKeyPEM8)
self.assertTrue(key.has_private())
self.assertEqual(key.n, self.n)
self.assertEqual(key.e, self.e)
self.assertEqual(key.d, self.d)
self.assertEqual(key.p, self.p)
self.assertEqual(key.q, self.q)
def testImportKey11(self):
"""Verify import of RSAPublicKey DER SEQUENCE"""
der = asn1.DerSequence([17, 3]).encode()
key = RSA.importKey(der)
self.assertEqual(key.n, 17)
self.assertEqual(key.e, 3)
def testImportKey12(self):
"""Verify import of RSAPublicKey DER SEQUENCE, encoded with PEM"""
der = asn1.DerSequence([17, 3]).encode()
pem = der2pem(der)
key = RSA.importKey(pem)
self.assertEqual(key.n, 17)
self.assertEqual(key.e, 3)
def test_import_key_windows_cr_lf(self):
pem_cr_lf = "\r\n".join(self.rsaKeyPEM.splitlines())
key = RSA.importKey(pem_cr_lf)
self.assertEqual(key.n, self.n)
self.assertEqual(key.e, self.e)
self.assertEqual(key.d, self.d)
self.assertEqual(key.p, self.p)
self.assertEqual(key.q, self.q)
def test_import_empty(self):
self.assertRaises(ValueError, RSA.import_key, b"")
###
def testExportKey1(self):
key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
derKey = key.export_key("DER")
self.assertEqual(derKey, self.rsaKeyDER)
def testExportKey2(self):
key = RSA.construct([self.n, self.e])
derKey = key.export_key("DER")
self.assertEqual(derKey, self.rsaPublicKeyDER)
def testExportKey3(self):
key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
pemKey = key.export_key("PEM")
self.assertEqual(pemKey, b(self.rsaKeyPEM))
def testExportKey4(self):
key = RSA.construct([self.n, self.e])
pemKey = key.export_key("PEM")
self.assertEqual(pemKey, b(self.rsaPublicKeyPEM))
def testExportKey5(self):
key = RSA.construct([self.n, self.e])
openssh_1 = key.export_key("OpenSSH").split()
openssh_2 = self.rsaPublicKeyOpenSSH.split()
self.assertEqual(openssh_1[0], openssh_2[0])
self.assertEqual(openssh_1[1], openssh_2[1])
def testExportKey7(self):
key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
derKey = key.export_key("DER", pkcs=8)
self.assertEqual(derKey, self.rsaKeyDER8)
def testExportKey8(self):
key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
pemKey = key.export_key("PEM", pkcs=8)
self.assertEqual(pemKey, b(self.rsaKeyPEM8))
def testExportKey9(self):
key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
self.assertRaises(ValueError, key.export_key, "invalid-format")
def testExportKey10(self):
# Export and re-import the encrypted key. It must match.
# PEM envelope, PKCS#1, old PEM encryption
key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
outkey = key.export_key('PEM', 'test')
self.assertTrue(tostr(outkey).find('4,ENCRYPTED')!=-1)
self.assertTrue(tostr(outkey).find('BEGIN RSA PRIVATE KEY')!=-1)
inkey = RSA.importKey(outkey, 'test')
self.assertEqual(key.n, inkey.n)
self.assertEqual(key.e, inkey.e)
self.assertEqual(key.d, inkey.d)
def testExportKey11(self):
# Export and re-import the encrypted key. It must match.
# PEM envelope, PKCS#1, old PEM encryption
key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
outkey = key.export_key('PEM', 'test', pkcs=1)
self.assertTrue(tostr(outkey).find('4,ENCRYPTED')!=-1)
self.assertTrue(tostr(outkey).find('BEGIN RSA PRIVATE KEY')!=-1)
inkey = RSA.importKey(outkey, 'test')
self.assertEqual(key.n, inkey.n)
self.assertEqual(key.e, inkey.e)
self.assertEqual(key.d, inkey.d)
def testExportKey12(self):
# Export and re-import the encrypted key. It must match.
# PEM envelope, PKCS#8, old PEM encryption
key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
outkey = key.export_key('PEM', 'test', pkcs=8)
self.assertTrue(tostr(outkey).find('4,ENCRYPTED')!=-1)
self.assertTrue(tostr(outkey).find('BEGIN PRIVATE KEY')!=-1)
inkey = RSA.importKey(outkey, 'test')
self.assertEqual(key.n, inkey.n)
self.assertEqual(key.e, inkey.e)
self.assertEqual(key.d, inkey.d)
def testExportKey13(self):
# Export and re-import the encrypted key. It must match.
# PEM envelope, PKCS#8, PKCS#8 encryption
key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
outkey = key.export_key('PEM', 'test', pkcs=8,
protection='PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC')
self.assertTrue(tostr(outkey).find('4,ENCRYPTED')==-1)
self.assertTrue(tostr(outkey).find('BEGIN ENCRYPTED PRIVATE KEY')!=-1)
inkey = RSA.importKey(outkey, 'test')
self.assertEqual(key.n, inkey.n)
self.assertEqual(key.e, inkey.e)
self.assertEqual(key.d, inkey.d)
def testExportKey14(self):
# Export and re-import the encrypted key. It must match.
# DER envelope, PKCS#8, PKCS#8 encryption
key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
outkey = key.export_key('DER', 'test', pkcs=8)
inkey = RSA.importKey(outkey, 'test')
self.assertEqual(key.n, inkey.n)
self.assertEqual(key.e, inkey.e)
self.assertEqual(key.d, inkey.d)
def testExportKey15(self):
# Verify that that error an condition is detected when trying to
# use a password with DER encoding and PKCS#1.
key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
self.assertRaises(ValueError, key.export_key, 'DER', 'test', 1)
def testExportKey16(self):
# Export and re-import the encrypted key. It must match.
# PEM envelope, PKCS#8, PKCS#8 encryption with parameters
key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
outkey = key.export_key('PEM', 'test', pkcs=8,
protection='PBKDF2WithHMAC-SHA512AndAES256-CBC',
prot_params={'iteration_count':123}
)
self.assertTrue(tostr(outkey).find('4,ENCRYPTED')==-1)
self.assertTrue(tostr(outkey).find('BEGIN ENCRYPTED PRIVATE KEY')!=-1)
# Verify the iteration count
der = PEM.decode(tostr(outkey))[0]
seq1 = asn1.DerSequence().decode(der)
seq2 = asn1.DerSequence().decode(seq1[0])
seq3 = asn1.DerSequence().decode(seq2[1])
seq4 = asn1.DerSequence().decode(seq3[0])
seq5 = asn1.DerSequence().decode(seq4[1])
self.assertEqual(seq5[1], 123)
inkey = RSA.importKey(outkey, 'test')
self.assertEqual(key.n, inkey.n)
self.assertEqual(key.e, inkey.e)
self.assertEqual(key.d, inkey.d)
def test_import_key(self):
"""Verify that import_key is an alias to importKey"""
key = RSA.import_key(self.rsaPublicKeyDER)
self.assertFalse(key.has_private())
self.assertEqual(key.n, self.n)
self.assertEqual(key.e, self.e)
def test_import_key_ba_mv(self):
"""Verify that import_key can be used on bytearrays and memoryviews"""
key = RSA.import_key(bytearray(self.rsaPublicKeyDER))
key = RSA.import_key(memoryview(self.rsaPublicKeyDER))
def test_exportKey(self):
key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
self.assertEqual(key.export_key(), key.exportKey())
class ImportKeyFromX509Cert(unittest.TestCase):
def test_x509v1(self):
# Sample V1 certificate with a 1024 bit RSA key
x509_v1_cert = """
-----BEGIN CERTIFICATE-----
MIICOjCCAaMCAQEwDQYJKoZIhvcNAQEEBQAwfjENMAsGA1UEChMEQWNtZTELMAkG
A1UECxMCUkQxHDAaBgkqhkiG9w0BCQEWDXNwYW1AYWNtZS5vcmcxEzARBgNVBAcT
Ck1ldHJvcG9saXMxETAPBgNVBAgTCE5ldyBZb3JrMQswCQYDVQQGEwJVUzENMAsG
A1UEAxMEdGVzdDAeFw0xNDA3MTExOTU3MjRaFw0xNzA0MDYxOTU3MjRaME0xCzAJ
BgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazENMAsGA1UEChMEQWNtZTELMAkG
A1UECxMCUkQxDzANBgNVBAMTBmxhdHZpYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
gYkCgYEAyG+kytdRj3TFbRmHDYp3TXugVQ81chew0qeOxZWOz80IjtWpgdOaCvKW
NCuc8wUR9BWrEQW+39SaRMLiQfQtyFSQZijc3nsEBu/Lo4uWZ0W/FHDRVSvkJA/V
Ex5NL5ikI+wbUeCV5KajGNDalZ8F1pk32+CBs8h1xNx5DyxuEHUCAwEAATANBgkq
hkiG9w0BAQQFAAOBgQCVQF9Y//Q4Psy+umEM38pIlbZ2hxC5xNz/MbVPwuCkNcGn
KYNpQJP+JyVTsPpO8RLZsAQDzRueMI3S7fbbwTzAflN0z19wvblvu93xkaBytVok
9VBAH28olVhy9b1MMeg2WOt5sUEQaFNPnwwsyiY9+HsRpvpRnPSQF+kyYVsshQ==
-----END CERTIFICATE-----
""".strip()
# RSA public key as dumped by openssl
exponent = 65537
modulus_str = """
00:c8:6f:a4:ca:d7:51:8f:74:c5:6d:19:87:0d:8a:
77:4d:7b:a0:55:0f:35:72:17:b0:d2:a7:8e:c5:95:
8e:cf:cd:08:8e:d5:a9:81:d3:9a:0a:f2:96:34:2b:
9c:f3:05:11:f4:15:ab:11:05:be:df:d4:9a:44:c2:
e2:41:f4:2d:c8:54:90:66:28:dc:de:7b:04:06:ef:
cb:a3:8b:96:67:45:bf:14:70:d1:55:2b:e4:24:0f:
d5:13:1e:4d:2f:98:a4:23:ec:1b:51:e0:95:e4:a6:
a3:18:d0:da:95:9f:05:d6:99:37:db:e0:81:b3:c8:
75:c4:dc:79:0f:2c:6e:10:75
"""
modulus = int(re.sub("[^0-9a-f]","", modulus_str), 16)
key = RSA.importKey(x509_v1_cert)
self.assertEqual(key.e, exponent)
self.assertEqual(key.n, modulus)
self.assertFalse(key.has_private())
def test_x509v3(self):
# Sample V3 certificate with a 1024 bit RSA key
x509_v3_cert = """
-----BEGIN CERTIFICATE-----
MIIEcjCCAlqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEL
MAkGA1UECAwCTUQxEjAQBgNVBAcMCUJhbHRpbW9yZTEQMA4GA1UEAwwHVGVzdCBD
QTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxlLmNvbTAeFw0xNDA3MTIwOTM1
MTJaFw0xNzA0MDcwOTM1MTJaMEQxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNRDES
MBAGA1UEBwwJQmFsdGltb3JlMRQwEgYDVQQDDAtUZXN0IFNlcnZlcjCBnzANBgkq
hkiG9w0BAQEFAAOBjQAwgYkCgYEA/S7GJV2OcFdyNMQ4K75KrYFtMEn3VnEFdPHa
jyS37XlMxSh0oS4GeTGVUCJInl5Cpsv8WQdh03FfeOdvzp5IZ46OcjeOPiWnmjgl
2G5j7e2bDH7RSchGV+OD6Fb1Agvuu2/9iy8fdf3rPQ/7eAddzKUrzwacVbnW+tg2
QtSXKRcCAwEAAaOB1TCB0jAdBgNVHQ4EFgQU/WwCX7FfWMIPDFfJ+I8a2COG+l8w
HwYDVR0jBBgwFoAUa0hkif3RMaraiWtsOOZZlLu9wJwwCQYDVR0TBAIwADALBgNV
HQ8EBAMCBeAwSgYDVR0RBEMwQYILZXhhbXBsZS5jb22CD3d3dy5leGFtcGxlLmNv
bYIQbWFpbC5leGFtcGxlLmNvbYIPZnRwLmV4YW1wbGUuY29tMCwGCWCGSAGG+EIB
DQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsF
AAOCAgEAvO6xfdsGbnoK4My3eJthodTAjMjPwFVY133LH04QLcCv54TxKhtUg1fi
PgdjVe1HpTytPBfXy2bSZbXAN0abZCtw1rYrnn7o1g2pN8iypVq3zVn0iMTzQzxs
zEPO3bpR/UhNSf90PmCsS5rqZpAAnXSaAy1ClwHWk/0eG2pYkhE1m1ABVMN2lsAW
e9WxGk6IFqaI9O37NYQwmEypMs4DC+ECJEvbPFiqi3n0gbXCZJJ6omDA5xJldaYK
Oa7KR3s/qjBsu9UAiWpLBuFoSTHIF2aeRKRFmUdmzwo43eVPep65pY6eQ4AdL2RF
rqEuINbGlzI5oQyYhu71IwB+iPZXaZZPlwjLgOsuad/p2hOgDb5WxUi8FnDPursQ
ujfpIpmrOP/zpvvQWnwePI3lI+5n41kTBSbefXEdv6rXpHk3QRzB90uPxnXPdxSC
16ASA8bQT5an/1AgoE3k9CrcD2K0EmgaX0YI0HUhkyzbkg34EhpWJ6vvRUbRiNRo
9cIbt/ya9Y9u0Ja8GLXv6dwX0l0IdJMkL8KifXUFAVCujp1FBrr/gdmwQn8itANy
+qbnWSxmOvtaY0zcaFAcONuHva0h51/WqXOMO1eb8PhR4HIIYU8p1oBwQp7dSni8
THDi1F+GG5PsymMDj5cWK42f+QzjVw5PrVmFqqrrEoMlx8DWh5Y=
-----END CERTIFICATE-----
""".strip()
# RSA public key as dumped by openssl
exponent = 65537
modulus_str = """
00:fd:2e:c6:25:5d:8e:70:57:72:34:c4:38:2b:be:
4a:ad:81:6d:30:49:f7:56:71:05:74:f1:da:8f:24:
b7:ed:79:4c:c5:28:74:a1:2e:06:79:31:95:50:22:
48:9e:5e:42:a6:cb:fc:59:07:61:d3:71:5f:78:e7:
6f:ce:9e:48:67:8e:8e:72:37:8e:3e:25:a7:9a:38:
25:d8:6e:63:ed:ed:9b:0c:7e:d1:49:c8:46:57:e3:
83:e8:56:f5:02:0b:ee:bb:6f:fd:8b:2f:1f:75:fd:
eb:3d:0f:fb:78:07:5d:cc:a5:2b:cf:06:9c:55:b9:
d6:fa:d8:36:42:d4:97:29:17
"""
modulus = int(re.sub("[^0-9a-f]","", modulus_str), 16)
key = RSA.importKey(x509_v3_cert)
self.assertEqual(key.e, exponent)
self.assertEqual(key.n, modulus)
self.assertFalse(key.has_private())
class TestImport_2048(unittest.TestCase):
def test_import_pss(self):
pub_key_file = load_file("rsa2048_pss_public.pem")
pub_key = RSA.import_key(pub_key_file)
priv_key_file = load_file("rsa2048_pss_private.pem")
priv_key = RSA.import_key(priv_key_file)
self.assertEqual(pub_key.n, priv_key.n)
def test_import_openssh_public(self):
key_file_ref = load_file("rsa2048_private.pem")
key_file = load_file("rsa2048_public_openssh.txt")
# Skip test if test vectors are not installed
if None in (key_file_ref, key_file):
return
key_ref = RSA.import_key(key_file_ref).public_key()
key = RSA.import_key(key_file)
self.assertEqual(key_ref, key)
def test_import_openssh_private_clear(self):
key_file = load_file("rsa2048_private_openssh.pem")
key_file_old = load_file("rsa2048_private_openssh_old.pem")
# Skip test if test vectors are not installed
if None in (key_file_old, key_file):
return
key = RSA.import_key(key_file)
key_old = RSA.import_key(key_file_old)
self.assertEqual(key, key_old)
def test_import_openssh_private_password(self):
key_file = load_file("rsa2048_private_openssh_pwd.pem")
key_file_old = load_file("rsa2048_private_openssh_pwd_old.pem")
# Skip test if test vectors are not installed
if None in (key_file_old, key_file):
return
key = RSA.import_key(key_file, b"password")
key_old = RSA.import_key(key_file_old)
self.assertEqual(key, key_old)
def test_import_pkcs8_private(self):
key_file_ref = load_file("rsa2048_private.pem")
key_file = load_file("rsa2048_private_p8.der")
# Skip test if test vectors are not installed
if None in (key_file_ref, key_file):
return
key_ref = RSA.import_key(key_file_ref)
key = RSA.import_key(key_file, b'secret')
self.assertEqual(key_ref, key)
def get_tests(config={}):
tests = []
tests += list_test_cases(ImportKeyTests)
tests += list_test_cases(ImportKeyFromX509Cert)
tests += list_test_cases(TestImport_2048)
return tests
if __name__ == '__main__':
def suite():
return unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')