summaryrefslogtreecommitdiffstats
path: root/lib/Crypto/SelfTest/PublicKey
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Crypto/SelfTest/PublicKey')
-rw-r--r--lib/Crypto/SelfTest/PublicKey/__init__.py53
-rw-r--r--lib/Crypto/SelfTest/PublicKey/test_DSA.py247
-rw-r--r--lib/Crypto/SelfTest/PublicKey/test_ECC_25519.py327
-rw-r--r--lib/Crypto/SelfTest/PublicKey/test_ECC_448.py327
-rw-r--r--lib/Crypto/SelfTest/PublicKey/test_ECC_NIST.py1389
-rw-r--r--lib/Crypto/SelfTest/PublicKey/test_ElGamal.py217
-rw-r--r--lib/Crypto/SelfTest/PublicKey/test_RSA.py317
-rw-r--r--lib/Crypto/SelfTest/PublicKey/test_import_DSA.py554
-rw-r--r--lib/Crypto/SelfTest/PublicKey/test_import_ECC.py2643
-rw-r--r--lib/Crypto/SelfTest/PublicKey/test_import_RSA.py590
10 files changed, 6664 insertions, 0 deletions
diff --git a/lib/Crypto/SelfTest/PublicKey/__init__.py b/lib/Crypto/SelfTest/PublicKey/__init__.py
new file mode 100644
index 0000000..437d3e4
--- /dev/null
+++ b/lib/Crypto/SelfTest/PublicKey/__init__.py
@@ -0,0 +1,53 @@
+# -*- 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_25519, test_ECC_448,
+ test_import_DSA, test_import_RSA,
+ test_import_ECC, test_ElGamal)
+
+
+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_25519.get_tests(config=config)
+ tests += test_ECC_448.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_ElGamal.get_tests(config=config)
+ return tests
+
+
+if __name__ == '__main__':
+ def suite():
+ return unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
diff --git a/lib/Crypto/SelfTest/PublicKey/test_DSA.py b/lib/Crypto/SelfTest/PublicKey/test_DSA.py
new file mode 100644
index 0000000..125cf6c
--- /dev/null
+++ b/lib/Crypto/SelfTest/PublicKey/test_DSA.py
@@ -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:
diff --git a/lib/Crypto/SelfTest/PublicKey/test_ECC_25519.py b/lib/Crypto/SelfTest/PublicKey/test_ECC_25519.py
new file mode 100644
index 0000000..305c077
--- /dev/null
+++ b/lib/Crypto/SelfTest/PublicKey/test_ECC_25519.py
@@ -0,0 +1,327 @@
+# ===================================================================
+#
+# 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_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.failUnless(pai.is_point_at_infinity())
+ self.assertEqual(pai, pai.point_at_infinity())
+
+ def test_negate(self):
+ negG = -self.pointG
+ sum = self.pointG + negG
+ self.failUnless(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, 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)
+
+
+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')
diff --git a/lib/Crypto/SelfTest/PublicKey/test_ECC_448.py b/lib/Crypto/SelfTest/PublicKey/test_ECC_448.py
new file mode 100644
index 0000000..68bcaa3
--- /dev/null
+++ b/lib/Crypto/SelfTest/PublicKey/test_ECC_448.py
@@ -0,0 +1,327 @@
+# ===================================================================
+#
+# 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_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.failUnless(pai.is_point_at_infinity())
+ self.assertEqual(pai, pai.point_at_infinity())
+
+ def test_negate(self):
+ negG = -self.pointG
+ sum = self.pointG + negG
+ self.failUnless(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)
+
+
+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')
diff --git a/lib/Crypto/SelfTest/PublicKey/test_ECC_NIST.py b/lib/Crypto/SelfTest/PublicKey/test_ECC_NIST.py
new file mode 100644
index 0000000..fc13f2d
--- /dev/null
+++ b/lib/Crypto/SelfTest/PublicKey/test_ECC_NIST.py
@@ -0,0 +1,1389 @@
+# ===================================================================
+#
+# Copyright (c) 2015, 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
+
+
+class TestEccPoint(unittest.TestCase):
+
+ def test_mix(self):
+
+ p1 = ECC.generate(curve='P-256').pointQ
+ p2 = ECC.generate(curve='P-384').pointQ
+
+ try:
+ p1 + p2
+ assert(False)
+ except ValueError as e:
+ assert "not on the same curve" in str(e)
+
+ try:
+ p1 += p2
+ assert(False)
+ except ValueError as e:
+ assert "not on the same curve" in str(e)
+
+ def test_repr(self):
+ p1 = ECC.construct(curve='P-256',
+ d=75467964919405407085864614198393977741148485328036093939970922195112333446269,
+ point_x=20573031766139722500939782666697015100983491952082159880539639074939225934381,
+ point_y=108863130203210779921520632367477406025152638284581252625277850513266505911389)
+ self.assertEqual(repr(p1), "EccKey(curve='NIST P-256', point_x=20573031766139722500939782666697015100983491952082159880539639074939225934381, point_y=108863130203210779921520632367477406025152638284581252625277850513266505911389, d=75467964919405407085864614198393977741148485328036093939970922195112333446269)")
+
+
+class TestEccPoint_NIST_P192(unittest.TestCase):
+ """Tests defined in section 4.1 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf"""
+
+ pointS = EccPoint(
+ 0xd458e7d127ae671b0c330266d246769353a012073e97acf8,
+ 0x325930500d851f336bddc050cf7fb11b5673a1645086df3b,
+ curve='p192')
+
+ pointT = EccPoint(
+ 0xf22c4395213e9ebe67ddecdd87fdbd01be16fb059b9753a4,
+ 0x264424096af2b3597796db48f8dfb41fa9cecc97691a9c79,
+ curve='p192')
+
+ def test_set(self):
+ pointW = EccPoint(0, 0)
+ pointW.set(self.pointS)
+ self.assertEqual(pointW, self.pointS)
+
+ def test_copy(self):
+ pointW = self.pointS.copy()
+ self.assertEqual(pointW, self.pointS)
+ pointW.set(self.pointT)
+ self.assertEqual(pointW, self.pointT)
+ self.assertNotEqual(self.pointS, self.pointT)
+
+ def test_negate(self):
+ negS = -self.pointS
+ sum = self.pointS + negS
+ self.assertEqual(sum, self.pointS.point_at_infinity())
+
+ def test_addition(self):
+ pointRx = 0x48e1e4096b9b8e5ca9d0f1f077b8abf58e843894de4d0290
+ pointRy = 0x408fa77c797cd7dbfb16aa48a3648d3d63c94117d7b6aa4b
+
+ pointR = self.pointS + self.pointT
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ pai = pointR.point_at_infinity()
+
+ # S + 0
+ pointR = self.pointS + pai
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + S
+ pointR = pai + self.pointS
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + 0
+ pointR = pai + pai
+ self.assertEqual(pointR, pai)
+
+ def test_inplace_addition(self):
+ pointRx = 0x48e1e4096b9b8e5ca9d0f1f077b8abf58e843894de4d0290
+ pointRy = 0x408fa77c797cd7dbfb16aa48a3648d3d63c94117d7b6aa4b
+
+ pointR = self.pointS.copy()
+ pointR += self.pointT
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ pai = pointR.point_at_infinity()
+
+ # S + 0
+ pointR = self.pointS.copy()
+ pointR += pai
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + S
+ pointR = pai.copy()
+ pointR += self.pointS
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + 0
+ pointR = pai.copy()
+ pointR += pai
+ self.assertEqual(pointR, pai)
+
+ def test_doubling(self):
+ pointRx = 0x30c5bc6b8c7da25354b373dc14dd8a0eba42d25a3f6e6962
+ pointRy = 0x0dde14bc4249a721c407aedbf011e2ddbbcb2968c9d889cf
+
+ pointR = self.pointS.copy()
+ pointR.double()
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ # 2*0
+ pai = self.pointS.point_at_infinity()
+ pointR = pai.copy()
+ pointR.double()
+ self.assertEqual(pointR, pai)
+
+ # S + S
+ pointR = self.pointS.copy()
+ pointR += pointR
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ def test_scalar_multiply(self):
+ d = 0xa78a236d60baec0c5dd41b33a542463a8255391af64c74ee
+ pointRx = 0x1faee4205a4f669d2d0a8f25e3bcec9a62a6952965bf6d31
+ pointRy = 0x5ff2cdfa508a2581892367087c696f179e7a4d7e8260fb06
+
+ pointR = self.pointS * d
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ # 0*S
+ pai = self.pointS.point_at_infinity()
+ pointR = self.pointS * 0
+ self.assertEqual(pointR, pai)
+
+ # -1*S
+ self.assertRaises(ValueError, lambda: self.pointS * -1)
+
+ # Reverse order
+ pointR = d * self.pointS
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ pointR = Integer(d) * self.pointS
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ def test_joint_scalar_multiply(self):
+ d = 0xa78a236d60baec0c5dd41b33a542463a8255391af64c74ee
+ e = 0xc4be3d53ec3089e71e4de8ceab7cce889bc393cd85b972bc
+ pointRx = 0x019f64eed8fa9b72b7dfea82c17c9bfa60ecb9e1778b5bde
+ pointRy = 0x16590c5fcd8655fa4ced33fb800e2a7e3c61f35d83503644
+
+ pointR = self.pointS * d + self.pointT * e
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ def test_sizes(self):
+ self.assertEqual(self.pointS.size_in_bits(), 192)
+ self.assertEqual(self.pointS.size_in_bytes(), 24)
+
+
+class TestEccPoint_NIST_P224(unittest.TestCase):
+ """Tests defined in section 4.2 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf"""
+
+ pointS = EccPoint(
+ 0x6eca814ba59a930843dc814edd6c97da95518df3c6fdf16e9a10bb5b,
+ 0xef4b497f0963bc8b6aec0ca0f259b89cd80994147e05dc6b64d7bf22,
+ curve='p224')
+
+ pointT = EccPoint(
+ 0xb72b25aea5cb03fb88d7e842002969648e6ef23c5d39ac903826bd6d,
+ 0xc42a8a4d34984f0b71b5b4091af7dceb33ea729c1a2dc8b434f10c34,
+ curve='p224')
+
+ def test_set(self):
+ pointW = EccPoint(0, 0)
+ pointW.set(self.pointS)
+ self.assertEqual(pointW, self.pointS)
+
+ def test_copy(self):
+ pointW = self.pointS.copy()
+ self.assertEqual(pointW, self.pointS)
+ pointW.set(self.pointT)
+ self.assertEqual(pointW, self.pointT)
+ self.assertNotEqual(self.pointS, self.pointT)
+
+ def test_negate(self):
+ negS = -self.pointS
+ sum = self.pointS + negS
+ self.assertEqual(sum, self.pointS.point_at_infinity())
+
+ def test_addition(self):
+ pointRx = 0x236f26d9e84c2f7d776b107bd478ee0a6d2bcfcaa2162afae8d2fd15
+ pointRy = 0xe53cc0a7904ce6c3746f6a97471297a0b7d5cdf8d536ae25bb0fda70
+
+ pointR = self.pointS + self.pointT
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ pai = pointR.point_at_infinity()
+
+ # S + 0
+ pointR = self.pointS + pai
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + S
+ pointR = pai + self.pointS
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + 0
+ pointR = pai + pai
+ self.assertEqual(pointR, pai)
+
+ def test_inplace_addition(self):
+ pointRx = 0x236f26d9e84c2f7d776b107bd478ee0a6d2bcfcaa2162afae8d2fd15
+ pointRy = 0xe53cc0a7904ce6c3746f6a97471297a0b7d5cdf8d536ae25bb0fda70
+
+ pointR = self.pointS.copy()
+ pointR += self.pointT
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ pai = pointR.point_at_infinity()
+
+ # S + 0
+ pointR = self.pointS.copy()
+ pointR += pai
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + S
+ pointR = pai.copy()
+ pointR += self.pointS
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + 0
+ pointR = pai.copy()
+ pointR += pai
+ self.assertEqual(pointR, pai)
+
+ def test_doubling(self):
+ pointRx = 0xa9c96f2117dee0f27ca56850ebb46efad8ee26852f165e29cb5cdfc7
+ pointRy = 0xadf18c84cf77ced4d76d4930417d9579207840bf49bfbf5837dfdd7d
+
+ pointR = self.pointS.copy()
+ pointR.double()
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ # 2*0
+ pai = self.pointS.point_at_infinity()
+ pointR = pai.copy()
+ pointR.double()
+ self.assertEqual(pointR, pai)
+
+ # S + S
+ pointR = self.pointS.copy()
+ pointR += pointR
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ def test_scalar_multiply(self):
+ d = 0xa78ccc30eaca0fcc8e36b2dd6fbb03df06d37f52711e6363aaf1d73b
+ pointRx = 0x96a7625e92a8d72bff1113abdb95777e736a14c6fdaacc392702bca4
+ pointRy = 0x0f8e5702942a3c5e13cd2fd5801915258b43dfadc70d15dbada3ed10
+
+ pointR = self.pointS * d
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ # 0*S
+ pai = self.pointS.point_at_infinity()
+ pointR = self.pointS * 0
+ self.assertEqual(pointR, pai)
+
+ # -1*S
+ self.assertRaises(ValueError, lambda: self.pointS * -1)
+
+ # Reverse order
+ pointR = d * self.pointS
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ pointR = Integer(d) * self.pointS
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ def test_joing_scalar_multiply(self):
+ d = 0xa78ccc30eaca0fcc8e36b2dd6fbb03df06d37f52711e6363aaf1d73b
+ e = 0x54d549ffc08c96592519d73e71e8e0703fc8177fa88aa77a6ed35736
+ pointRx = 0xdbfe2958c7b2cda1302a67ea3ffd94c918c5b350ab838d52e288c83e
+ pointRy = 0x2f521b83ac3b0549ff4895abcc7f0c5a861aacb87acbc5b8147bb18b
+
+ pointR = self.pointS * d + self.pointT * e
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ def test_sizes(self):
+ self.assertEqual(self.pointS.size_in_bits(), 224)
+ self.assertEqual(self.pointS.size_in_bytes(), 28)
+
+
+class TestEccPoint_NIST_P256(unittest.TestCase):
+ """Tests defined in section 4.3 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf"""
+
+ pointS = EccPoint(
+ 0xde2444bebc8d36e682edd27e0f271508617519b3221a8fa0b77cab3989da97c9,
+ 0xc093ae7ff36e5380fc01a5aad1e66659702de80f53cec576b6350b243042a256)
+
+ pointT = EccPoint(
+ 0x55a8b00f8da1d44e62f6b3b25316212e39540dc861c89575bb8cf92e35e0986b,
+ 0x5421c3209c2d6c704835d82ac4c3dd90f61a8a52598b9e7ab656e9d8c8b24316)
+
+ def test_set(self):
+ pointW = EccPoint(0, 0)
+ pointW.set(self.pointS)
+ self.assertEqual(pointW, self.pointS)
+
+ def test_copy(self):
+ pointW = self.pointS.copy()
+ self.assertEqual(pointW, self.pointS)
+ pointW.set(self.pointT)
+ self.assertEqual(pointW, self.pointT)
+ self.assertNotEqual(self.pointS, self.pointT)
+
+ def test_negate(self):
+ negS = -self.pointS
+ sum = self.pointS + negS
+ self.assertEqual(sum, self.pointS.point_at_infinity())
+
+ def test_addition(self):
+ pointRx = 0x72b13dd4354b6b81745195e98cc5ba6970349191ac476bd4553cf35a545a067e
+ pointRy = 0x8d585cbb2e1327d75241a8a122d7620dc33b13315aa5c9d46d013011744ac264
+
+ pointR = self.pointS + self.pointT
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ pai = pointR.point_at_infinity()
+
+ # S + 0
+ pointR = self.pointS + pai
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + S
+ pointR = pai + self.pointS
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + 0
+ pointR = pai + pai
+ self.assertEqual(pointR, pai)
+
+ def test_inplace_addition(self):
+ pointRx = 0x72b13dd4354b6b81745195e98cc5ba6970349191ac476bd4553cf35a545a067e
+ pointRy = 0x8d585cbb2e1327d75241a8a122d7620dc33b13315aa5c9d46d013011744ac264
+
+ pointR = self.pointS.copy()
+ pointR += self.pointT
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ pai = pointR.point_at_infinity()
+
+ # S + 0
+ pointR = self.pointS.copy()
+ pointR += pai
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + S
+ pointR = pai.copy()
+ pointR += self.pointS
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + 0
+ pointR = pai.copy()
+ pointR += pai
+ self.assertEqual(pointR, pai)
+
+ def test_doubling(self):
+ pointRx = 0x7669e6901606ee3ba1a8eef1e0024c33df6c22f3b17481b82a860ffcdb6127b0
+ pointRy = 0xfa878162187a54f6c39f6ee0072f33de389ef3eecd03023de10ca2c1db61d0c7
+
+ pointR = self.pointS.copy()
+ pointR.double()
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ # 2*0
+ pai = self.pointS.point_at_infinity()
+ pointR = pai.copy()
+ pointR.double()
+ self.assertEqual(pointR, pai)
+
+ # S + S
+ pointR = self.pointS.copy()
+ pointR += pointR
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ def test_scalar_multiply(self):
+ d = 0xc51e4753afdec1e6b6c6a5b992f43f8dd0c7a8933072708b6522468b2ffb06fd
+ pointRx = 0x51d08d5f2d4278882946d88d83c97d11e62becc3cfc18bedacc89ba34eeca03f
+ pointRy = 0x75ee68eb8bf626aa5b673ab51f6e744e06f8fcf8a6c0cf3035beca956a7b41d5
+
+ pointR = self.pointS * d
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ # 0*S
+ pai = self.pointS.point_at_infinity()
+ pointR = self.pointS * 0
+ self.assertEqual(pointR, pai)
+
+ # -1*S
+ self.assertRaises(ValueError, lambda: self.pointS * -1)
+
+ # Reverse order
+ pointR = d * self.pointS
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ pointR = Integer(d) * self.pointS
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ def test_joing_scalar_multiply(self):
+ d = 0xc51e4753afdec1e6b6c6a5b992f43f8dd0c7a8933072708b6522468b2ffb06fd
+ e = 0xd37f628ece72a462f0145cbefe3f0b355ee8332d37acdd83a358016aea029db7
+ pointRx = 0xd867b4679221009234939221b8046245efcf58413daacbeff857b8588341f6b8
+ pointRy = 0xf2504055c03cede12d22720dad69c745106b6607ec7e50dd35d54bd80f615275
+
+ pointR = self.pointS * d + self.pointT * e
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ def test_sizes(self):
+ self.assertEqual(self.pointS.size_in_bits(), 256)
+ self.assertEqual(self.pointS.size_in_bytes(), 32)
+
+
+class TestEccPoint_NIST_P384(unittest.TestCase):
+ """Tests defined in section 4.4 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf"""
+
+ pointS = EccPoint(
+ 0xfba203b81bbd23f2b3be971cc23997e1ae4d89e69cb6f92385dda82768ada415ebab4167459da98e62b1332d1e73cb0e,
+ 0x5ffedbaefdeba603e7923e06cdb5d0c65b22301429293376d5c6944e3fa6259f162b4788de6987fd59aed5e4b5285e45,
+ "p384")
+
+ pointT = EccPoint(
+ 0xaacc05202e7fda6fc73d82f0a66220527da8117ee8f8330ead7d20ee6f255f582d8bd38c5a7f2b40bcdb68ba13d81051,
+ 0x84009a263fefba7c2c57cffa5db3634d286131afc0fca8d25afa22a7b5dce0d9470da89233cee178592f49b6fecb5092,
+ "p384")
+
+ def test_set(self):
+ pointW = EccPoint(0, 0, "p384")
+ pointW.set(self.pointS)
+ self.assertEqual(pointW, self.pointS)
+
+ def test_copy(self):
+ pointW = self.pointS.copy()
+ self.assertEqual(pointW, self.pointS)
+ pointW.set(self.pointT)
+ self.assertEqual(pointW, self.pointT)
+ self.assertNotEqual(self.pointS, self.pointT)
+
+ def test_negate(self):
+ negS = -self.pointS
+ sum = self.pointS + negS
+ self.assertEqual(sum, self.pointS.point_at_infinity())
+
+ def test_addition(self):
+ pointRx = 0x12dc5ce7acdfc5844d939f40b4df012e68f865b89c3213ba97090a247a2fc009075cf471cd2e85c489979b65ee0b5eed
+ pointRy = 0x167312e58fe0c0afa248f2854e3cddcb557f983b3189b67f21eee01341e7e9fe67f6ee81b36988efa406945c8804a4b0
+
+ pointR = self.pointS + self.pointT
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ pai = pointR.point_at_infinity()
+
+ # S + 0
+ pointR = self.pointS + pai
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + S
+ pointR = pai + self.pointS
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + 0
+ pointR = pai + pai
+ self.assertEqual(pointR, pai)
+
+ def _test_inplace_addition(self):
+ pointRx = 0x72b13dd4354b6b81745195e98cc5ba6970349191ac476bd4553cf35a545a067e
+ pointRy = 0x8d585cbb2e1327d75241a8a122d7620dc33b13315aa5c9d46d013011744ac264
+
+ pointR = self.pointS.copy()
+ pointR += self.pointT
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ pai = pointR.point_at_infinity()
+
+ # S + 0
+ pointR = self.pointS.copy()
+ pointR += pai
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + S
+ pointR = pai.copy()
+ pointR += self.pointS
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + 0
+ pointR = pai.copy()
+ pointR += pai
+ self.assertEqual(pointR, pai)
+
+ def test_doubling(self):
+ pointRx = 0x2a2111b1e0aa8b2fc5a1975516bc4d58017ff96b25e1bdff3c229d5fac3bacc319dcbec29f9478f42dee597b4641504c
+ pointRy = 0xfa2e3d9dc84db8954ce8085ef28d7184fddfd1344b4d4797343af9b5f9d837520b450f726443e4114bd4e5bdb2f65ddd
+
+ pointR = self.pointS.copy()
+ pointR.double()
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ # 2*0
+ pai = self.pointS.point_at_infinity()
+ pointR = pai.copy()
+ pointR.double()
+ self.assertEqual(pointR, pai)
+
+ # S + S
+ pointR = self.pointS.copy()
+ pointR += pointR
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ def test_scalar_multiply(self):
+ d = 0xa4ebcae5a665983493ab3e626085a24c104311a761b5a8fdac052ed1f111a5c44f76f45659d2d111a61b5fdd97583480
+ pointRx = 0xe4f77e7ffeb7f0958910e3a680d677a477191df166160ff7ef6bb5261f791aa7b45e3e653d151b95dad3d93ca0290ef2
+ pointRy = 0xac7dee41d8c5f4a7d5836960a773cfc1376289d3373f8cf7417b0c6207ac32e913856612fc9ff2e357eb2ee05cf9667f
+
+ pointR = self.pointS * d
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ # 0*S
+ pai = self.pointS.point_at_infinity()
+ pointR = self.pointS * 0
+ self.assertEqual(pointR, pai)
+
+ # -1*S
+ self.assertRaises(ValueError, lambda: self.pointS * -1)
+
+ def test_joing_scalar_multiply(self):
+ d = 0xa4ebcae5a665983493ab3e626085a24c104311a761b5a8fdac052ed1f111a5c44f76f45659d2d111a61b5fdd97583480
+ e = 0xafcf88119a3a76c87acbd6008e1349b29f4ba9aa0e12ce89bcfcae2180b38d81ab8cf15095301a182afbc6893e75385d
+ pointRx = 0x917ea28bcd641741ae5d18c2f1bd917ba68d34f0f0577387dc81260462aea60e2417b8bdc5d954fc729d211db23a02dc
+ pointRy = 0x1a29f7ce6d074654d77b40888c73e92546c8f16a5ff6bcbd307f758d4aee684beff26f6742f597e2585c86da908f7186
+
+ pointR = self.pointS * d + self.pointT * e
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ def test_sizes(self):
+ self.assertEqual(self.pointS.size_in_bits(), 384)
+ self.assertEqual(self.pointS.size_in_bytes(), 48)
+
+
+class TestEccPoint_NIST_P521(unittest.TestCase):
+ """Tests defined in section 4.5 of https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.204.9073&rep=rep1&type=pdf"""
+
+ pointS = EccPoint(
+ 0x000001d5c693f66c08ed03ad0f031f937443458f601fd098d3d0227b4bf62873af50740b0bb84aa157fc847bcf8dc16a8b2b8bfd8e2d0a7d39af04b089930ef6dad5c1b4,
+ 0x00000144b7770963c63a39248865ff36b074151eac33549b224af5c8664c54012b818ed037b2b7c1a63ac89ebaa11e07db89fcee5b556e49764ee3fa66ea7ae61ac01823,
+ "p521")
+
+ pointT = EccPoint(
+ 0x000000f411f2ac2eb971a267b80297ba67c322dba4bb21cec8b70073bf88fc1ca5fde3ba09e5df6d39acb2c0762c03d7bc224a3e197feaf760d6324006fe3be9a548c7d5,
+ 0x000001fdf842769c707c93c630df6d02eff399a06f1b36fb9684f0b373ed064889629abb92b1ae328fdb45534268384943f0e9222afe03259b32274d35d1b9584c65e305,
+ "p521")
+
+ def test_set(self):
+ pointW = EccPoint(0, 0)
+ pointW.set(self.pointS)
+ self.assertEqual(pointW, self.pointS)
+
+ def test_copy(self):
+ pointW = self.pointS.copy()
+ self.assertEqual(pointW, self.pointS)
+ pointW.set(self.pointT)
+ self.assertEqual(pointW, self.pointT)
+ self.assertNotEqual(self.pointS, self.pointT)
+
+ def test_negate(self):
+ negS = -self.pointS
+ sum = self.pointS + negS
+ self.assertEqual(sum, self.pointS.point_at_infinity())
+
+ def test_addition(self):
+ pointRx = 0x000001264ae115ba9cbc2ee56e6f0059e24b52c8046321602c59a339cfb757c89a59c358a9a8e1f86d384b3f3b255ea3f73670c6dc9f45d46b6a196dc37bbe0f6b2dd9e9
+ pointRy = 0x00000062a9c72b8f9f88a271690bfa017a6466c31b9cadc2fc544744aeb817072349cfddc5ad0e81b03f1897bd9c8c6efbdf68237dc3bb00445979fb373b20c9a967ac55
+
+ pointR = self.pointS + self.pointT
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ pai = pointR.point_at_infinity()
+
+ # S + 0
+ pointR = self.pointS + pai
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + S
+ pointR = pai + self.pointS
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + 0
+ pointR = pai + pai
+ self.assertEqual(pointR, pai)
+
+ def test_inplace_addition(self):
+ pointRx = 0x000001264ae115ba9cbc2ee56e6f0059e24b52c8046321602c59a339cfb757c89a59c358a9a8e1f86d384b3f3b255ea3f73670c6dc9f45d46b6a196dc37bbe0f6b2dd9e9
+ pointRy = 0x00000062a9c72b8f9f88a271690bfa017a6466c31b9cadc2fc544744aeb817072349cfddc5ad0e81b03f1897bd9c8c6efbdf68237dc3bb00445979fb373b20c9a967ac55
+
+ pointR = self.pointS.copy()
+ pointR += self.pointT
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ pai = pointR.point_at_infinity()
+
+ # S + 0
+ pointR = self.pointS.copy()
+ pointR += pai
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + S
+ pointR = pai.copy()
+ pointR += self.pointS
+ self.assertEqual(pointR, self.pointS)
+
+ # 0 + 0
+ pointR = pai.copy()
+ pointR += pai
+ self.assertEqual(pointR, pai)
+
+ def test_doubling(self):
+ pointRx = 0x0000012879442f2450c119e7119a5f738be1f1eba9e9d7c6cf41b325d9ce6d643106e9d61124a91a96bcf201305a9dee55fa79136dc700831e54c3ca4ff2646bd3c36bc6
+ pointRy = 0x0000019864a8b8855c2479cbefe375ae553e2393271ed36fadfc4494fc0583f6bd03598896f39854abeae5f9a6515a021e2c0eef139e71de610143f53382f4104dccb543
+
+ pointR = self.pointS.copy()
+ pointR.double()
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ # 2*0
+ pai = self.pointS.point_at_infinity()
+ pointR = pai.copy()
+ pointR.double()
+ self.assertEqual(pointR, pai)
+
+ # S + S
+ pointR = self.pointS.copy()
+ pointR += pointR
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ def test_scalar_multiply(self):
+ d = 0x000001eb7f81785c9629f136a7e8f8c674957109735554111a2a866fa5a166699419bfa9936c78b62653964df0d6da940a695c7294d41b2d6600de6dfcf0edcfc89fdcb1
+ pointRx = 0x00000091b15d09d0ca0353f8f96b93cdb13497b0a4bb582ae9ebefa35eee61bf7b7d041b8ec34c6c00c0c0671c4ae063318fb75be87af4fe859608c95f0ab4774f8c95bb
+ pointRy = 0x00000130f8f8b5e1abb4dd94f6baaf654a2d5810411e77b7423965e0c7fd79ec1ae563c207bd255ee9828eb7a03fed565240d2cc80ddd2cecbb2eb50f0951f75ad87977f
+
+ pointR = self.pointS * d
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ # 0*S
+ pai = self.pointS.point_at_infinity()
+ pointR = self.pointS * 0
+ self.assertEqual(pointR, pai)
+
+ # -1*S
+ self.assertRaises(ValueError, lambda: self.pointS * -1)
+
+ def test_joing_scalar_multiply(self):
+ d = 0x000001eb7f81785c9629f136a7e8f8c674957109735554111a2a866fa5a166699419bfa9936c78b62653964df0d6da940a695c7294d41b2d6600de6dfcf0edcfc89fdcb1
+ e = 0x00000137e6b73d38f153c3a7575615812608f2bab3229c92e21c0d1c83cfad9261dbb17bb77a63682000031b9122c2f0cdab2af72314be95254de4291a8f85f7c70412e3
+ pointRx = 0x0000009d3802642b3bea152beb9e05fba247790f7fc168072d363340133402f2585588dc1385d40ebcb8552f8db02b23d687cae46185b27528adb1bf9729716e4eba653d
+ pointRy = 0x0000000fe44344e79da6f49d87c1063744e5957d9ac0a505bafa8281c9ce9ff25ad53f8da084a2deb0923e46501de5797850c61b229023dd9cf7fc7f04cd35ebb026d89d
+
+ pointR = self.pointS * d
+ pointR += self.pointT * e
+ self.assertEqual(pointR.x, pointRx)
+ self.assertEqual(pointR.y, pointRy)
+
+ def test_sizes(self):
+ self.assertEqual(self.pointS.size_in_bits(), 521)
+ self.assertEqual(self.pointS.size_in_bytes(), 66)
+
+
+class TestEccPoint_PAI_P192(unittest.TestCase):
+ """Test vectors from http://point-at-infinity.org/ecc/nisttv"""
+
+ curve = _curves['p192']
+ pointG = EccPoint(curve.Gx, curve.Gy, "p192")
+
+
+tv_pai = load_test_vectors(("PublicKey", "ECC"),
+ "point-at-infinity.org-P192.txt",
+ "P-192 tests from point-at-infinity.org",
+ {"k": lambda k: int(k),
+ "x": lambda x: int(x, 16),
+ "y": lambda y: int(y, 16)}) or []
+for tv in tv_pai:
+ def new_test(self, scalar=tv.k, x=tv.x, y=tv.y):
+ result = self.pointG * scalar
+ self.assertEqual(result.x, x)
+ self.assertEqual(result.y, y)
+ setattr(TestEccPoint_PAI_P192, "test_%d" % tv.count, new_test)
+
+
+class TestEccPoint_PAI_P224(unittest.TestCase):
+ """Test vectors from http://point-at-infinity.org/ecc/nisttv"""
+
+ curve = _curves['p224']
+ pointG = EccPoint(curve.Gx, curve.Gy, "p224")
+
+
+tv_pai = load_test_vectors(("PublicKey", "ECC"),
+ "point-at-infinity.org-P224.txt",
+ "P-224 tests from point-at-infinity.org",
+ {"k": lambda k: int(k),
+ "x": lambda x: int(x, 16),
+ "y": lambda y: int(y, 16)}) or []
+for tv in tv_pai:
+ def new_test(self, scalar=tv.k, x=tv.x, y=tv.y):
+ result = self.pointG * scalar
+ self.assertEqual(result.x, x)
+ self.assertEqual(result.y, y)
+ setattr(TestEccPoint_PAI_P224, "test_%d" % tv.count, new_test)
+
+
+class TestEccPoint_PAI_P256(unittest.TestCase):
+ """Test vectors from http://point-at-infinity.org/ecc/nisttv"""
+
+ curve = _curves['p256']
+ pointG = EccPoint(curve.Gx, curve.Gy, "p256")
+
+
+tv_pai = load_test_vectors(("PublicKey", "ECC"),
+ "point-at-infinity.org-P256.txt",
+ "P-256 tests from point-at-infinity.org",
+ {"k": lambda k: int(k),
+ "x": lambda x: int(x, 16),
+ "y": lambda y: int(y, 16)}) or []
+for tv in tv_pai:
+ def new_test(self, scalar=tv.k, x=tv.x, y=tv.y):
+ result = self.pointG * scalar
+ self.assertEqual(result.x, x)
+ self.assertEqual(result.y, y)
+ setattr(TestEccPoint_PAI_P256, "test_%d" % tv.count, new_test)
+
+
+class TestEccPoint_PAI_P384(unittest.TestCase):
+ """Test vectors from http://point-at-infinity.org/ecc/nisttv"""
+
+ curve = _curves['p384']
+ pointG = EccPoint(curve.Gx, curve.Gy, "p384")
+
+
+tv_pai = load_test_vectors(("PublicKey", "ECC"),
+ "point-at-infinity.org-P384.txt",
+ "P-384 tests from point-at-infinity.org",
+ {"k": lambda k: int(k),
+ "x": lambda x: int(x, 16),
+ "y": lambda y: int(y, 16)}) or []
+for tv in tv_pai:
+ def new_test(self, scalar=tv.k, x=tv.x, y=tv.y):
+ result = self.pointG * scalar
+ self.assertEqual(result.x, x)
+ self.assertEqual(result.y, y)
+ setattr(TestEccPoint_PAI_P384, "test_%d" % tv.count, new_test)
+
+
+class TestEccPoint_PAI_P521(unittest.TestCase):
+ """Test vectors from http://point-at-infinity.org/ecc/nisttv"""
+
+ curve = _curves['p521']
+ pointG = EccPoint(curve.Gx, curve.Gy, "p521")
+
+
+tv_pai = load_test_vectors(("PublicKey", "ECC"),
+ "point-at-infinity.org-P521.txt",
+ "P-521 tests from point-at-infinity.org",
+ {"k": lambda k: int(k),
+ "x": lambda x: int(x, 16),
+ "y": lambda y: int(y, 16)}) or []
+for tv in tv_pai:
+ def new_test(self, scalar=tv.k, x=tv.x, y=tv.y):
+ result = self.pointG * scalar
+ self.assertEqual(result.x, x)
+ self.assertEqual(result.y, y)
+ setattr(TestEccPoint_PAI_P521, "test_%d" % tv.count, new_test)
+
+
+class TestEccKey_P192(unittest.TestCase):
+
+ def test_private_key(self):
+
+ key = EccKey(curve="P-192", d=1)
+ self.assertEqual(key.d, 1)
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ.x, _curves['p192'].Gx)
+ self.assertEqual(key.pointQ.y, _curves['p192'].Gy)
+
+ point = EccPoint(_curves['p192'].Gx, _curves['p192'].Gy, curve='P-192')
+ key = EccKey(curve="P-192", d=1, point=point)
+ self.assertEqual(key.d, 1)
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ, point)
+
+ # Other names
+ key = EccKey(curve="secp192r1", d=1)
+ key = EccKey(curve="prime192v1", d=1)
+
+ def test_public_key(self):
+
+ point = EccPoint(_curves['p192'].Gx, _curves['p192'].Gy, curve='P-192')
+ key = EccKey(curve="P-192", point=point)
+ self.assertFalse(key.has_private())
+ self.assertEqual(key.pointQ, point)
+
+ def test_public_key_derived(self):
+
+ priv_key = EccKey(curve="P-192", d=3)
+ pub_key = priv_key.public_key()
+ self.assertFalse(pub_key.has_private())
+ self.assertEqual(priv_key.pointQ, pub_key.pointQ)
+
+ def test_invalid_curve(self):
+ self.assertRaises(ValueError, lambda: EccKey(curve="P-193", d=1))
+
+ def test_invalid_d(self):
+ self.assertRaises(ValueError, lambda: EccKey(curve="P-192", d=0))
+ self.assertRaises(ValueError, lambda: EccKey(curve="P-192",
+ d=_curves['p192'].order))
+
+ def test_equality(self):
+
+ private_key = ECC.construct(d=3, curve="P-192")
+ private_key2 = ECC.construct(d=3, curve="P-192")
+ private_key3 = ECC.construct(d=4, curve="P-192")
+
+ 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)
+
+
+class TestEccKey_P224(unittest.TestCase):
+
+ def test_private_key(self):
+
+ key = EccKey(curve="P-224", d=1)
+ self.assertEqual(key.d, 1)
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ.x, _curves['p224'].Gx)
+ self.assertEqual(key.pointQ.y, _curves['p224'].Gy)
+
+ point = EccPoint(_curves['p224'].Gx, _curves['p224'].Gy, curve='P-224')
+ key = EccKey(curve="P-224", d=1, point=point)
+ self.assertEqual(key.d, 1)
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ, point)
+
+ # Other names
+ key = EccKey(curve="secp224r1", d=1)
+ key = EccKey(curve="prime224v1", d=1)
+
+ def test_public_key(self):
+
+ point = EccPoint(_curves['p224'].Gx, _curves['p224'].Gy, curve='P-224')
+ key = EccKey(curve="P-224", point=point)
+ self.assertFalse(key.has_private())
+ self.assertEqual(key.pointQ, point)
+
+ def test_public_key_derived(self):
+
+ priv_key = EccKey(curve="P-224", d=3)
+ pub_key = priv_key.public_key()
+ self.assertFalse(pub_key.has_private())
+ self.assertEqual(priv_key.pointQ, pub_key.pointQ)
+
+ def test_invalid_curve(self):
+ self.assertRaises(ValueError, lambda: EccKey(curve="P-225", d=1))
+
+ def test_invalid_d(self):
+ self.assertRaises(ValueError, lambda: EccKey(curve="P-224", d=0))
+ self.assertRaises(ValueError, lambda: EccKey(curve="P-224",
+ d=_curves['p224'].order))
+
+ def test_equality(self):
+
+ private_key = ECC.construct(d=3, curve="P-224")
+ private_key2 = ECC.construct(d=3, curve="P-224")
+ private_key3 = ECC.construct(d=4, curve="P-224")
+
+ 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)
+
+
+class TestEccKey_P256(unittest.TestCase):
+
+ def test_private_key(self):
+
+ key = EccKey(curve="P-256", d=1)
+ self.assertEqual(key.d, 1)
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ.x, _curves['p256'].Gx)
+ self.assertEqual(key.pointQ.y, _curves['p256'].Gy)
+
+ point = EccPoint(_curves['p256'].Gx, _curves['p256'].Gy)
+ key = EccKey(curve="P-256", d=1, point=point)
+ self.assertEqual(key.d, 1)
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ, point)
+
+ # Other names
+ key = EccKey(curve="secp256r1", d=1)
+ key = EccKey(curve="prime256v1", d=1)
+
+ # Must not accept d parameter
+ self.assertRaises(ValueError, EccKey, curve="p256", seed=b'H'*32)
+
+ def test_public_key(self):
+
+ point = EccPoint(_curves['p256'].Gx, _curves['p256'].Gy)
+ key = EccKey(curve="P-256", point=point)
+ self.assertFalse(key.has_private())
+ self.assertEqual(key.pointQ, point)
+
+ def test_public_key_derived(self):
+
+ priv_key = EccKey(curve="P-256", d=3)
+ pub_key = priv_key.public_key()
+ self.assertFalse(pub_key.has_private())
+ self.assertEqual(priv_key.pointQ, pub_key.pointQ)
+
+ def test_invalid_curve(self):
+ self.assertRaises(ValueError, lambda: EccKey(curve="P-257", d=1))
+
+ def test_invalid_d(self):
+ self.assertRaises(ValueError, lambda: EccKey(curve="P-256", d=0))
+ self.assertRaises(ValueError, lambda: EccKey(curve="P-256", d=_curves['p256'].order))
+
+ def test_equality(self):
+
+ private_key = ECC.construct(d=3, curve="P-256")
+ private_key2 = ECC.construct(d=3, curve="P-256")
+ private_key3 = ECC.construct(d=4, curve="P-256")
+
+ 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)
+
+
+class TestEccKey_P384(unittest.TestCase):
+
+ def test_private_key(self):
+
+ p384 = _curves['p384']
+
+ key = EccKey(curve="P-384", d=1)
+ self.assertEqual(key.d, 1)
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ.x, p384.Gx)
+ self.assertEqual(key.pointQ.y, p384.Gy)
+
+ point = EccPoint(p384.Gx, p384.Gy, "p384")
+ key = EccKey(curve="P-384", d=1, point=point)
+ self.assertEqual(key.d, 1)
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ, point)
+
+ # Other names
+ key = EccKey(curve="p384", d=1)
+ key = EccKey(curve="secp384r1", d=1)
+ key = EccKey(curve="prime384v1", d=1)
+
+ def test_public_key(self):
+
+ p384 = _curves['p384']
+ point = EccPoint(p384.Gx, p384.Gy, 'p384')
+ key = EccKey(curve="P-384", point=point)
+ self.assertFalse(key.has_private())
+ self.assertEqual(key.pointQ, point)
+
+ def test_public_key_derived(self):
+
+ priv_key = EccKey(curve="P-384", d=3)
+ pub_key = priv_key.public_key()
+ self.assertFalse(pub_key.has_private())
+ self.assertEqual(priv_key.pointQ, pub_key.pointQ)
+
+ def test_invalid_curve(self):
+ self.assertRaises(ValueError, lambda: EccKey(curve="P-385", d=1))
+
+ def test_invalid_d(self):
+ self.assertRaises(ValueError, lambda: EccKey(curve="P-384", d=0))
+ self.assertRaises(ValueError, lambda: EccKey(curve="P-384",
+ d=_curves['p384'].order))
+
+ def test_equality(self):
+
+ private_key = ECC.construct(d=3, curve="P-384")
+ private_key2 = ECC.construct(d=3, curve="P-384")
+ private_key3 = ECC.construct(d=4, curve="P-384")
+
+ 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)
+
+
+class TestEccKey_P521(unittest.TestCase):
+
+ def test_private_key(self):
+
+ p521 = _curves['p521']
+
+ key = EccKey(curve="P-521", d=1)
+ self.assertEqual(key.d, 1)
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ.x, p521.Gx)
+ self.assertEqual(key.pointQ.y, p521.Gy)
+
+ point = EccPoint(p521.Gx, p521.Gy, "p521")
+ key = EccKey(curve="P-521", d=1, point=point)
+ self.assertEqual(key.d, 1)
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ, point)
+
+ # Other names
+ key = EccKey(curve="p521", d=1)
+ key = EccKey(curve="secp521r1", d=1)
+ key = EccKey(curve="prime521v1", d=1)
+
+ def test_public_key(self):
+
+ p521 = _curves['p521']
+ point = EccPoint(p521.Gx, p521.Gy, 'p521')
+ key = EccKey(curve="P-384", point=point)
+ self.assertFalse(key.has_private())
+ self.assertEqual(key.pointQ, point)
+
+ def test_public_key_derived(self):
+
+ priv_key = EccKey(curve="P-521", d=3)
+ pub_key = priv_key.public_key()
+ self.assertFalse(pub_key.has_private())
+ self.assertEqual(priv_key.pointQ, pub_key.pointQ)
+
+ def test_invalid_curve(self):
+ self.assertRaises(ValueError, lambda: EccKey(curve="P-522", d=1))
+
+ def test_invalid_d(self):
+ self.assertRaises(ValueError, lambda: EccKey(curve="P-521", d=0))
+ self.assertRaises(ValueError, lambda: EccKey(curve="P-521",
+ d=_curves['p521'].order))
+
+ def test_equality(self):
+
+ private_key = ECC.construct(d=3, curve="P-521")
+ private_key2 = ECC.construct(d=3, curve="P-521")
+ private_key3 = ECC.construct(d=4, curve="P-521")
+
+ 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)
+
+
+class TestEccModule_P192(unittest.TestCase):
+
+ def test_generate(self):
+
+ key = ECC.generate(curve="P-192")
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ, EccPoint(_curves['p192'].Gx,
+ _curves['p192'].Gy,
+ "P-192") * key.d,
+ "p192")
+
+ # Other names
+ ECC.generate(curve="secp192r1")
+ ECC.generate(curve="prime192v1")
+
+ def test_construct(self):
+
+ key = ECC.construct(curve="P-192", d=1)
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ, _curves['p192'].G)
+
+ key = ECC.construct(curve="P-192", point_x=_curves['p192'].Gx,
+ point_y=_curves['p192'].Gy)
+ self.assertFalse(key.has_private())
+ self.assertEqual(key.pointQ, _curves['p192'].G)
+
+ # Other names
+ ECC.construct(curve="p192", d=1)
+ ECC.construct(curve="secp192r1", d=1)
+ ECC.construct(curve="prime192v1", d=1)
+
+ def test_negative_construct(self):
+ coord = dict(point_x=10, point_y=4)
+ coordG = dict(point_x=_curves['p192'].Gx, point_y=_curves['p192'].Gy)
+
+ self.assertRaises(ValueError, ECC.construct, curve="P-192", **coord)
+ self.assertRaises(ValueError, ECC.construct, curve="P-192", d=2, **coordG)
+
+
+class TestEccModule_P224(unittest.TestCase):
+
+ def test_generate(self):
+
+ key = ECC.generate(curve="P-224")
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ, EccPoint(_curves['p224'].Gx,
+ _curves['p224'].Gy,
+ "P-224") * key.d,
+ "p224")
+
+ # Other names
+ ECC.generate(curve="secp224r1")
+ ECC.generate(curve="prime224v1")
+
+ def test_construct(self):
+
+ key = ECC.construct(curve="P-224", d=1)
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ, _curves['p224'].G)
+
+ key = ECC.construct(curve="P-224", point_x=_curves['p224'].Gx,
+ point_y=_curves['p224'].Gy)
+ self.assertFalse(key.has_private())
+ self.assertEqual(key.pointQ, _curves['p224'].G)
+
+ # Other names
+ ECC.construct(curve="p224", d=1)
+ ECC.construct(curve="secp224r1", d=1)
+ ECC.construct(curve="prime224v1", d=1)
+
+ def test_negative_construct(self):
+ coord = dict(point_x=10, point_y=4)
+ coordG = dict(point_x=_curves['p224'].Gx, point_y=_curves['p224'].Gy)
+
+ self.assertRaises(ValueError, ECC.construct, curve="P-224", **coord)
+ self.assertRaises(ValueError, ECC.construct, curve="P-224", d=2, **coordG)
+
+
+class TestEccModule_P256(unittest.TestCase):
+
+ def test_generate(self):
+
+ key = ECC.generate(curve="P-256")
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ, EccPoint(_curves['p256'].Gx,
+ _curves['p256'].Gy) * key.d,
+ "p256")
+
+ # Other names
+ ECC.generate(curve="secp256r1")
+ ECC.generate(curve="prime256v1")
+
+ def test_construct(self):
+
+ key = ECC.construct(curve="P-256", d=1)
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ, _curves['p256'].G)
+
+ key = ECC.construct(curve="P-256", point_x=_curves['p256'].Gx,
+ point_y=_curves['p256'].Gy)
+ self.assertFalse(key.has_private())
+ self.assertEqual(key.pointQ, _curves['p256'].G)
+
+ # Other names
+ ECC.construct(curve="p256", d=1)
+ ECC.construct(curve="secp256r1", d=1)
+ ECC.construct(curve="prime256v1", d=1)
+
+ def test_negative_construct(self):
+ coord = dict(point_x=10, point_y=4)
+ coordG = dict(point_x=_curves['p256'].Gx, point_y=_curves['p256'].Gy)
+
+ self.assertRaises(ValueError, ECC.construct, curve="P-256", **coord)
+ self.assertRaises(ValueError, ECC.construct, curve="P-256", d=2, **coordG)
+
+
+class TestEccModule_P384(unittest.TestCase):
+
+ def test_generate(self):
+
+ curve = _curves['p384']
+ key = ECC.generate(curve="P-384")
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ, EccPoint(curve.Gx, curve.Gy, "p384") * key.d)
+
+ # Other names
+ ECC.generate(curve="secp384r1")
+ ECC.generate(curve="prime384v1")
+
+ def test_construct(self):
+
+ curve = _curves['p384']
+ key = ECC.construct(curve="P-384", d=1)
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ, _curves['p384'].G)
+
+ key = ECC.construct(curve="P-384", point_x=curve.Gx, point_y=curve.Gy)
+ self.assertFalse(key.has_private())
+ self.assertEqual(key.pointQ, curve.G)
+
+ # Other names
+ ECC.construct(curve="p384", d=1)
+ ECC.construct(curve="secp384r1", d=1)
+ ECC.construct(curve="prime384v1", d=1)
+
+ def test_negative_construct(self):
+ coord = dict(point_x=10, point_y=4)
+ coordG = dict(point_x=_curves['p384'].Gx, point_y=_curves['p384'].Gy)
+
+ self.assertRaises(ValueError, ECC.construct, curve="P-384", **coord)
+ self.assertRaises(ValueError, ECC.construct, curve="P-384", d=2, **coordG)
+
+
+class TestEccModule_P521(unittest.TestCase):
+
+ def test_generate(self):
+
+ curve = _curves['p521']
+ key = ECC.generate(curve="P-521")
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ, EccPoint(curve.Gx, curve.Gy, "p521") * key.d)
+
+ # Other names
+ ECC.generate(curve="secp521r1")
+ ECC.generate(curve="prime521v1")
+
+ def test_construct(self):
+
+ curve = _curves['p521']
+ key = ECC.construct(curve="P-521", d=1)
+ self.assertTrue(key.has_private())
+ self.assertEqual(key.pointQ, _curves['p521'].G)
+
+ key = ECC.construct(curve="P-521", point_x=curve.Gx, point_y=curve.Gy)
+ self.assertFalse(key.has_private())
+ self.assertEqual(key.pointQ, curve.G)
+
+ # Other names
+ ECC.construct(curve="p521", d=1)
+ ECC.construct(curve="secp521r1", d=1)
+ ECC.construct(curve="prime521v1", d=1)
+
+ def test_negative_construct(self):
+ coord = dict(point_x=10, point_y=4)
+ coordG = dict(point_x=_curves['p521'].Gx, point_y=_curves['p521'].Gy)
+
+ self.assertRaises(ValueError, ECC.construct, curve="P-521", **coord)
+ self.assertRaises(ValueError, ECC.construct, curve="P-521", d=2, **coordG)
+
+
+def get_tests(config={}):
+ tests = []
+ tests += list_test_cases(TestEccPoint)
+ tests += list_test_cases(TestEccPoint_NIST_P192)
+ tests += list_test_cases(TestEccPoint_NIST_P224)
+ tests += list_test_cases(TestEccPoint_NIST_P256)
+ tests += list_test_cases(TestEccPoint_NIST_P384)
+ tests += list_test_cases(TestEccPoint_NIST_P521)
+ tests += list_test_cases(TestEccPoint_PAI_P192)
+ tests += list_test_cases(TestEccPoint_PAI_P224)
+ tests += list_test_cases(TestEccPoint_PAI_P256)
+ tests += list_test_cases(TestEccPoint_PAI_P384)
+ tests += list_test_cases(TestEccPoint_PAI_P521)
+ tests += list_test_cases(TestEccKey_P192)
+ tests += list_test_cases(TestEccKey_P224)
+ tests += list_test_cases(TestEccKey_P256)
+ tests += list_test_cases(TestEccKey_P384)
+ tests += list_test_cases(TestEccKey_P521)
+ tests += list_test_cases(TestEccModule_P192)
+ tests += list_test_cases(TestEccModule_P224)
+ tests += list_test_cases(TestEccModule_P256)
+ tests += list_test_cases(TestEccModule_P384)
+ tests += list_test_cases(TestEccModule_P521)
+ return tests
+
+
+if __name__ == '__main__':
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
diff --git a/lib/Crypto/SelfTest/PublicKey/test_ElGamal.py b/lib/Crypto/SelfTest/PublicKey/test_ElGamal.py
new file mode 100644
index 0000000..0b394ae
--- /dev/null
+++ b/lib/Crypto/SelfTest/PublicKey/test_ElGamal.py
@@ -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')
+
diff --git a/lib/Crypto/SelfTest/PublicKey/test_RSA.py b/lib/Crypto/SelfTest/PublicKey/test_RSA.py
new file mode 100644
index 0000000..e7b5b90
--- /dev/null
+++ b/lib/Crypto/SelfTest/PublicKey/test_RSA.py
@@ -0,0 +1,317 @@
+# -*- 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._encrypt, rsa_obj.n)
+
+ self.assertRaises(ValueError, rsa_obj._decrypt, -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
+
+ 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))
+
+ # 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:
diff --git a/lib/Crypto/SelfTest/PublicKey/test_import_DSA.py b/lib/Crypto/SelfTest/PublicKey/test_import_DSA.py
new file mode 100644
index 0000000..266b46f
--- /dev/null
+++ b/lib/Crypto/SelfTest/PublicKey/test_import_DSA.py
@@ -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')
+
diff --git a/lib/Crypto/SelfTest/PublicKey/test_import_ECC.py b/lib/Crypto/SelfTest/PublicKey/test_import_ECC.py
new file mode 100644
index 0000000..f9222c8
--- /dev/null
+++ b/lib/Crypto/SelfTest/PublicKey/test_import_ECC.py
@@ -0,0 +1,2643 @@
+# ===================================================================
+#
+# Copyright (c) 2015, 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 os
+import errno
+import warnings
+import unittest
+from binascii import unhexlify
+
+from Crypto.SelfTest.st_common import list_test_cases
+from Crypto.Util.py3compat import bord, tostr, FileNotFoundError
+from Crypto.Util.asn1 import DerSequence, DerBitString
+from Crypto.Util.number import bytes_to_long
+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
+
+
+class MissingTestVectorException(ValueError):
+ pass
+
+
+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 MissingTestVectorException("Missing %s" % file_name)
+
+ return results
+
+
+def compact(lines):
+ ext = b"".join(lines)
+ return unhexlify(tostr(ext).replace(" ", "").replace(":", ""))
+
+
+def create_ref_keys_p192():
+ key_len = 24
+ key_lines = load_file("ecc_p192.txt").splitlines()
+ private_key_d = bytes_to_long(compact(key_lines[2:4]))
+ public_key_xy = compact(key_lines[5:9])
+ assert bord(public_key_xy[0]) == 4 # Uncompressed
+ public_key_x = bytes_to_long(public_key_xy[1:key_len+1])
+ public_key_y = bytes_to_long(public_key_xy[key_len+1:])
+
+ return (ECC.construct(curve="P-192", d=private_key_d),
+ ECC.construct(curve="P-192", point_x=public_key_x, point_y=public_key_y))
+
+
+def create_ref_keys_p224():
+ key_len = 28
+ key_lines = load_file("ecc_p224.txt").splitlines()
+ private_key_d = bytes_to_long(compact(key_lines[2:4]))
+ public_key_xy = compact(key_lines[5:9])
+ assert bord(public_key_xy[0]) == 4 # Uncompressed
+ public_key_x = bytes_to_long(public_key_xy[1:key_len+1])
+ public_key_y = bytes_to_long(public_key_xy[key_len+1:])
+
+ return (ECC.construct(curve="P-224", d=private_key_d),
+ ECC.construct(curve="P-224", point_x=public_key_x, point_y=public_key_y))
+
+
+def create_ref_keys_p256():
+ key_len = 32
+ key_lines = load_file("ecc_p256.txt").splitlines()
+ private_key_d = bytes_to_long(compact(key_lines[2:5]))
+ public_key_xy = compact(key_lines[6:11])
+ assert bord(public_key_xy[0]) == 4 # Uncompressed
+ public_key_x = bytes_to_long(public_key_xy[1:key_len+1])
+ public_key_y = bytes_to_long(public_key_xy[key_len+1:])
+
+ return (ECC.construct(curve="P-256", d=private_key_d),
+ ECC.construct(curve="P-256", point_x=public_key_x, point_y=public_key_y))
+
+
+def create_ref_keys_p384():
+ key_len = 48
+ key_lines = load_file("ecc_p384.txt").splitlines()
+ private_key_d = bytes_to_long(compact(key_lines[2:6]))
+ public_key_xy = compact(key_lines[7:14])
+ assert bord(public_key_xy[0]) == 4 # Uncompressed
+ public_key_x = bytes_to_long(public_key_xy[1:key_len+1])
+ public_key_y = bytes_to_long(public_key_xy[key_len+1:])
+
+ return (ECC.construct(curve="P-384", d=private_key_d),
+ ECC.construct(curve="P-384", point_x=public_key_x, point_y=public_key_y))
+
+
+def create_ref_keys_p521():
+ key_len = 66
+ key_lines = load_file("ecc_p521.txt").splitlines()
+ private_key_d = bytes_to_long(compact(key_lines[2:7]))
+ public_key_xy = compact(key_lines[8:17])
+ assert bord(public_key_xy[0]) == 4 # Uncompressed
+ public_key_x = bytes_to_long(public_key_xy[1:key_len+1])
+ public_key_y = bytes_to_long(public_key_xy[key_len+1:])
+
+ return (ECC.construct(curve="P-521", d=private_key_d),
+ ECC.construct(curve="P-521", point_x=public_key_x, point_y=public_key_y))
+
+
+def create_ref_keys_ed25519():
+ key_lines = load_file("ecc_ed25519.txt").splitlines()
+ seed = compact(key_lines[5:8])
+ key = ECC.construct(curve="Ed25519", seed=seed)
+ return (key, key.public_key())
+
+
+def create_ref_keys_ed448():
+ key_lines = load_file("ecc_ed448.txt").splitlines()
+ seed = compact(key_lines[6:10])
+ key = ECC.construct(curve="Ed448", seed=seed)
+ return (key, key.public_key())
+
+
+# Create reference key pair
+# ref_private, ref_public = create_ref_keys_p521()
+
+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"")
+
+
+class TestImport_P192(unittest.TestCase):
+
+ def __init__(self, *args, **kwargs):
+ super(TestImport_P192, self).__init__(*args, **kwargs)
+ self.ref_private, self.ref_public = create_ref_keys_p192()
+
+ def test_import_public_der(self):
+ key_file = load_file("ecc_p192_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_sec1_uncompressed(self):
+ key_file = load_file("ecc_p192_public.der")
+ value = extract_bitstring_from_spki(key_file)
+ key = ECC.import_key(key_file, curve_name='P192')
+ self.assertEqual(self.ref_public, key)
+
+ def test_import_sec1_compressed(self):
+ key_file = load_file("ecc_p192_public_compressed.der")
+ value = extract_bitstring_from_spki(key_file)
+ key = ECC.import_key(key_file, curve_name='P192')
+ self.assertEqual(self.ref_public, key)
+
+ def test_import_rfc5915_der(self):
+ key_file = load_file("ecc_p192_private.der")
+
+ key = ECC._import_rfc5915_der(key_file, None)
+ self.assertEqual(self.ref_private, key)
+
+ 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_clear(self):
+ key_file = load_file("ecc_p192_private_p8_clear.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_in_pem_clear(self):
+ key_file = load_file("ecc_p192_private_p8_clear.pem")
+
+ 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_p192_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_p192_private_p8.pem")
+
+ key = ECC.import_key(key_file, "secret")
+ self.assertEqual(self.ref_private, key)
+
+ def test_import_x509_der(self):
+ key_file = load_file("ecc_p192_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_p192_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_p192_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", "aes256_gcm":
+ key_file = load_file("ecc_p192_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_p192_x509.pem")
+
+ key = ECC.import_key(key_file)
+ self.assertEqual(self.ref_public, key)
+
+
+class TestImport_P224(unittest.TestCase):
+
+ def __init__(self, *args, **kwargs):
+ super(TestImport_P224, self).__init__(*args, **kwargs)
+ self.ref_private, self.ref_public = create_ref_keys_p224()
+
+ def test_import_public_der(self):
+ key_file = load_file("ecc_p224_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_sec1_uncompressed(self):
+ key_file = load_file("ecc_p224_public.der")
+ value = extract_bitstring_from_spki(key_file)
+ key = ECC.import_key(key_file, curve_name='P224')
+ self.assertEqual(self.ref_public, key)
+
+ def test_import_sec1_compressed(self):
+ key_file = load_file("ecc_p224_public_compressed.der")
+ value = extract_bitstring_from_spki(key_file)
+ key = ECC.import_key(key_file, curve_name='P224')
+ self.assertEqual(self.ref_public, key)
+
+ def test_import_rfc5915_der(self):
+ key_file = load_file("ecc_p224_private.der")
+
+ key = ECC._import_rfc5915_der(key_file, None)
+ self.assertEqual(self.ref_private, key)
+
+ 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_clear(self):
+ key_file = load_file("ecc_p224_private_p8_clear.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_in_pem_clear(self):
+ key_file = load_file("ecc_p224_private_p8_clear.pem")
+
+ 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_p224_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_p224_private_p8.pem")
+
+ key = ECC.import_key(key_file, "secret")
+ self.assertEqual(self.ref_private, key)
+
+ def test_import_x509_der(self):
+ key_file = load_file("ecc_p224_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_p224_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_p224_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", "aes256_gcm":
+ key_file = load_file("ecc_p224_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_p224_x509.pem")
+
+ key = ECC.import_key(key_file)
+ self.assertEqual(self.ref_public, key)
+
+
+class TestImport_P256(unittest.TestCase):
+
+ def __init__(self, *args, **kwargs):
+ super(TestImport_P256, self).__init__(*args, **kwargs)
+ self.ref_private, self.ref_public = create_ref_keys_p256()
+
+ def test_import_public_der(self):
+ key_file = load_file("ecc_p256_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_sec1_uncompressed(self):
+ key_file = load_file("ecc_p256_public.der")
+ value = extract_bitstring_from_spki(key_file)
+ key = ECC.import_key(key_file, curve_name='P256')
+ self.assertEqual(self.ref_public, key)
+
+ def test_import_sec1_compressed(self):
+ key_file = load_file("ecc_p256_public_compressed.der")
+ value = extract_bitstring_from_spki(key_file)
+ key = ECC.import_key(key_file, curve_name='P256')
+ self.assertEqual(self.ref_public, key)
+
+ def test_import_rfc5915_der(self):
+ key_file = load_file("ecc_p256_private.der")
+
+ key = ECC._import_rfc5915_der(key_file, None)
+ self.assertEqual(self.ref_private, key)
+
+ 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_clear(self):
+ key_file = load_file("ecc_p256_private_p8_clear.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_in_pem_clear(self):
+ key_file = load_file("ecc_p256_private_p8_clear.pem")
+
+ 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_p256_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_p256_private_p8.pem")
+
+ key = ECC.import_key(key_file, "secret")
+ self.assertEqual(self.ref_private, key)
+
+ def test_import_x509_der(self):
+ key_file = load_file("ecc_p256_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_p256_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_p256_private.pem")
+
+ key = ECC.import_key(key_file)
+ self.assertEqual(self.ref_private, key)
+
+ def test_import_private_pem_with_ecparams(self):
+ key_file = load_file("ecc_p256_private_ecparams.pem")
+ key = ECC.import_key(key_file)
+ # We just check if the import succeeds
+
+ def test_import_private_pem_encrypted(self):
+ for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm":
+ key_file = load_file("ecc_p256_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_p256_x509.pem")
+
+ key = ECC.import_key(key_file)
+ self.assertEqual(self.ref_public, key)
+
+ def test_import_openssh_public(self):
+ key_file = load_file("ecc_p256_public_openssh.txt")
+
+ key = ECC._import_openssh_public(key_file)
+ self.assertEqual(self.ref_public, key)
+
+ key = ECC.import_key(key_file)
+ self.assertEqual(self.ref_public, key)
+
+ def test_import_openssh_private_clear(self):
+ key_file = load_file("ecc_p256_private_openssh.pem")
+ key_file_old = load_file("ecc_p256_private_openssh_old.pem")
+
+ key = ECC.import_key(key_file)
+ key_old = ECC.import_key(key_file_old)
+ self.assertEqual(key, key_old)
+
+ def test_import_openssh_private_password(self):
+ key_file = load_file("ecc_p256_private_openssh_pwd.pem")
+ key_file_old = load_file("ecc_p256_private_openssh_pwd_old.pem")
+
+ key = ECC.import_key(key_file, b"password")
+ key_old = ECC.import_key(key_file_old)
+ self.assertEqual(key, key_old)
+
+
+class TestImport_P384(unittest.TestCase):
+
+ def __init__(self, *args, **kwargs):
+ super(TestImport_P384, self).__init__(*args, **kwargs)
+ self.ref_private, self.ref_public = create_ref_keys_p384()
+
+ def test_import_public_der(self):
+ key_file = load_file("ecc_p384_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_sec1_uncompressed(self):
+ key_file = load_file("ecc_p384_public.der")
+ value = extract_bitstring_from_spki(key_file)
+ key = ECC.import_key(key_file, curve_name='P384')
+ self.assertEqual(self.ref_public, key)
+
+ def test_import_sec1_compressed(self):
+ key_file = load_file("ecc_p384_public_compressed.der")
+ value = extract_bitstring_from_spki(key_file)
+ key = ECC.import_key(key_file, curve_name='P384')
+ self.assertEqual(self.ref_public, key)
+
+ def test_import_rfc5915_der(self):
+ key_file = load_file("ecc_p384_private.der")
+
+ key = ECC._import_rfc5915_der(key_file, None)
+ self.assertEqual(self.ref_private, key)
+
+ 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_clear(self):
+ key_file = load_file("ecc_p384_private_p8_clear.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_in_pem_clear(self):
+ key_file = load_file("ecc_p384_private_p8_clear.pem")
+
+ 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_p384_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_p384_private_p8.pem")
+
+ key = ECC.import_key(key_file, "secret")
+ self.assertEqual(self.ref_private, key)
+
+ def test_import_x509_der(self):
+ key_file = load_file("ecc_p384_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_p384_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_p384_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", "aes256_gcm":
+ key_file = load_file("ecc_p384_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_p384_x509.pem")
+
+ key = ECC.import_key(key_file)
+ self.assertEqual(self.ref_public, key)
+
+ def test_import_openssh_public(self):
+ key_file = load_file("ecc_p384_public_openssh.txt")
+
+ key = ECC._import_openssh_public(key_file)
+ self.assertEqual(self.ref_public, key)
+
+ key = ECC.import_key(key_file)
+ self.assertEqual(self.ref_public, key)
+
+ def test_import_openssh_private_clear(self):
+ key_file = load_file("ecc_p384_private_openssh.pem")
+ key_file_old = load_file("ecc_p384_private_openssh_old.pem")
+
+ key = ECC.import_key(key_file)
+ key_old = ECC.import_key(key_file_old)
+ self.assertEqual(key, key_old)
+
+ def test_import_openssh_private_password(self):
+ key_file = load_file("ecc_p384_private_openssh_pwd.pem")
+ key_file_old = load_file("ecc_p384_private_openssh_pwd_old.pem")
+
+ key = ECC.import_key(key_file, b"password")
+ key_old = ECC.import_key(key_file_old)
+ self.assertEqual(key, key_old)
+
+
+class TestImport_P521(unittest.TestCase):
+
+ def __init__(self, *args, **kwargs):
+ super(TestImport_P521, self).__init__(*args, **kwargs)
+ self.ref_private, self.ref_public = create_ref_keys_p521()
+
+ def test_import_public_der(self):
+ key_file = load_file("ecc_p521_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_sec1_uncompressed(self):
+ key_file = load_file("ecc_p521_public.der")
+ value = extract_bitstring_from_spki(key_file)
+ key = ECC.import_key(key_file, curve_name='P521')
+ self.assertEqual(self.ref_public, key)
+
+ def test_import_sec1_compressed(self):
+ key_file = load_file("ecc_p521_public_compressed.der")
+ value = extract_bitstring_from_spki(key_file)
+ key = ECC.import_key(key_file, curve_name='P521')
+ self.assertEqual(self.ref_public, key)
+
+ def test_import_rfc5915_der(self):
+ key_file = load_file("ecc_p521_private.der")
+
+ key = ECC._import_rfc5915_der(key_file, None)
+ self.assertEqual(self.ref_private, key)
+
+ 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_clear(self):
+ key_file = load_file("ecc_p521_private_p8_clear.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_in_pem_clear(self):
+ key_file = load_file("ecc_p521_private_p8_clear.pem")
+
+ 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_p521_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_p521_private_p8.pem")
+
+ key = ECC.import_key(key_file, "secret")
+ self.assertEqual(self.ref_private, key)
+
+ def test_import_x509_der(self):
+ key_file = load_file("ecc_p521_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_p521_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_p521_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", "aes256_gcm":
+ key_file = load_file("ecc_p521_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_p521_x509.pem")
+
+ key = ECC.import_key(key_file)
+ self.assertEqual(self.ref_public, key)
+
+ def test_import_openssh_public(self):
+ key_file = load_file("ecc_p521_public_openssh.txt")
+
+ key = ECC._import_openssh_public(key_file)
+ self.assertEqual(self.ref_public, key)
+
+ key = ECC.import_key(key_file)
+ self.assertEqual(self.ref_public, key)
+
+ def test_import_openssh_private_clear(self):
+ key_file = load_file("ecc_p521_private_openssh.pem")
+ key_file_old = load_file("ecc_p521_private_openssh_old.pem")
+
+ key = ECC.import_key(key_file)
+ key_old = ECC.import_key(key_file_old)
+ self.assertEqual(key, key_old)
+
+ def test_import_openssh_private_password(self):
+ key_file = load_file("ecc_p521_private_openssh_pwd.pem")
+ key_file_old = load_file("ecc_p521_private_openssh_pwd_old.pem")
+
+ key = ECC.import_key(key_file, b"password")
+ key_old = ECC.import_key(key_file_old)
+ self.assertEqual(key, key_old)
+
+
+class TestExport_P192(unittest.TestCase):
+
+ def __init__(self, *args, **kwargs):
+ super(TestExport_P192, self).__init__(*args, **kwargs)
+ self.ref_private, self.ref_public = create_ref_keys_p192()
+
+ def test_export_public_der_uncompressed(self):
+ key_file = load_file("ecc_p192_public.der")
+
+ encoded = self.ref_public._export_subjectPublicKeyInfo(False)
+ 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_public_der_compressed(self):
+ key_file = load_file("ecc_p192_public.der")
+ pub_key = ECC.import_key(key_file)
+ key_file_compressed = pub_key.export_key(format="DER", compress=True)
+
+ key_file_compressed_ref = load_file("ecc_p192_public_compressed.der")
+ self.assertEqual(key_file_compressed, key_file_compressed_ref)
+
+ def test_export_public_sec1_uncompressed(self):
+ key_file = load_file("ecc_p192_public.der")
+ value = extract_bitstring_from_spki(key_file)
+
+ encoded = self.ref_public.export_key(format="SEC1")
+ self.assertEqual(value, encoded)
+
+ def test_export_public_sec1_compressed(self):
+ key_file = load_file("ecc_p192_public.der")
+ encoded = self.ref_public.export_key(format="SEC1", compress=True)
+
+ key_file_compressed_ref = load_file("ecc_p192_public_compressed.der")
+ value = extract_bitstring_from_spki(key_file_compressed_ref)
+ self.assertEqual(value, encoded)
+
+ def test_export_rfc5915_private_der(self):
+ key_file = load_file("ecc_p192_private.der")
+
+ encoded = self.ref_private._export_rfc5915_private_der()
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="DER", use_pkcs8=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_private_pkcs8_clear(self):
+ key_file = load_file("ecc_p192_private_p8_clear.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)
+
+ 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)
+
+ def test_export_public_pem_uncompressed(self):
+ key_file = load_file("ecc_p192_public.pem", "rt").strip()
+
+ encoded = self.ref_private._export_public_pem(False)
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_public.export_key(format="PEM")
+ self.assertEqual(key_file, encoded)
+
+ encoded = self.ref_public.export_key(format="PEM", compress=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_public_pem_compressed(self):
+ key_file = load_file("ecc_p192_public.pem", "rt").strip()
+ pub_key = ECC.import_key(key_file)
+
+ key_file_compressed = pub_key.export_key(format="PEM", compress=True)
+ key_file_compressed_ref = load_file("ecc_p192_public_compressed.pem", "rt").strip()
+
+ self.assertEqual(key_file_compressed, key_file_compressed_ref)
+
+ def test_export_private_pem_clear(self):
+ key_file = load_file("ecc_p192_private.pem", "rt").strip()
+
+ encoded = self.ref_private._export_private_pem(None)
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_private_pem_encrypted(self):
+ encoded = self.ref_private._export_private_pem(passphrase=b"secret")
+
+ # This should prove that the output is password-protected
+ self.assertRaises(ValueError, ECC.import_key, encoded)
+
+ assert "EC PRIVATE KEY" in encoded
+
+ decoded = ECC.import_key(encoded, "secret")
+ self.assertEqual(self.ref_private, decoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM",
+ passphrase="secret",
+ use_pkcs8=False)
+ decoded = ECC.import_key(encoded, "secret")
+ self.assertEqual(self.ref_private, decoded)
+
+ def test_export_private_pkcs8_and_pem_1(self):
+ # PKCS8 inside PEM with both unencrypted
+ key_file = load_file("ecc_p192_private_p8_clear.pem", "rt").strip()
+
+ encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem()
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM")
+ self.assertEqual(key_file, encoded)
+
+ def test_export_private_pkcs8_and_pem_2(self):
+ # PKCS8 inside PEM with PKCS8 encryption
+ encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("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)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM",
+ passphrase="secret",
+ protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
+ decoded = ECC.import_key(encoded, "secret")
+ self.assertEqual(self.ref_private, decoded)
+
+ 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)
+
+ # ---
+
+ encoded1 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase="secret",
+ randfunc=get_fixed_prng())
+ encoded2 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase="secret",
+ randfunc=get_fixed_prng())
+ self.assertEqual(encoded1, encoded2)
+
+ def test_byte_or_string_passphrase(self):
+ encoded1 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase="secret",
+ randfunc=get_fixed_prng())
+ encoded2 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase=b"secret",
+ 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.ref_private.export_key(format="PEM", passphrase="secret",
+ use_pkcs8=False)
+ self.assertRaises(ValueError, self.ref_private.export_key, format="PEM",
+ passphrase="secret")
+
+ # DER format but no PKCS#8
+ self.assertRaises(ValueError, self.ref_private.export_key, format="DER",
+ passphrase="secret",
+ use_pkcs8=False,
+ protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
+
+ # Incorrect parameters for public keys
+ self.assertRaises(ValueError, self.ref_public.export_key, format="DER",
+ use_pkcs8=False)
+
+ # 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")
+
+ def test_compressed_curve(self):
+
+ # Compressed P-192 curve (Y-point is even)
+ pem1 = """-----BEGIN EC PRIVATE KEY-----
+ MF8CAQEEGHvhXmIW95JxZYfd4AUPu9BwknjuvS36aqAKBggqhkjOPQMBAaE0AzIA
+ BLJZCyTu35DQIlqvMlBynn3k1Ig+dWfg/brRhHecxptrbloqFSP8ITw0CwbGF+2X
+ 5g==
+ -----END EC PRIVATE KEY-----"""
+
+ # Compressed P-192 curve (Y-point is odd)
+ pem2 = """-----BEGIN EC PRIVATE KEY-----
+ MF8CAQEEGA3rAotUaWl7d47eX6tz9JmLzOMJwl13XaAKBggqhkjOPQMBAaE0AzIA
+ BG4tHlTBBBGokcWmGm2xubVB0NvPC/Ou5AYwivs+3iCxmEjsymVAj6iiuX2Lxr6g
+ /Q==
+ -----END EC PRIVATE KEY-----"""
+
+ key1 = ECC.import_key(pem1)
+ low16 = int(key1.pointQ.y % 65536)
+ self.assertEqual(low16, 0x97E6)
+
+ key2 = ECC.import_key(pem2)
+ low16 = int(key2.pointQ.y % 65536)
+ self.assertEqual(low16, 0xA0FD)
+
+
+class TestExport_P224(unittest.TestCase):
+
+ def __init__(self, *args, **kwargs):
+ super(TestExport_P224, self).__init__(*args, **kwargs)
+ self.ref_private, self.ref_public = create_ref_keys_p224()
+
+ def test_export_public_der_uncompressed(self):
+ key_file = load_file("ecc_p224_public.der")
+
+ encoded = self.ref_public._export_subjectPublicKeyInfo(False)
+ 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_public_der_compressed(self):
+ key_file = load_file("ecc_p224_public.der")
+ pub_key = ECC.import_key(key_file)
+ key_file_compressed = pub_key.export_key(format="DER", compress=True)
+
+ key_file_compressed_ref = load_file("ecc_p224_public_compressed.der")
+ self.assertEqual(key_file_compressed, key_file_compressed_ref)
+
+ def test_export_public_sec1_uncompressed(self):
+ key_file = load_file("ecc_p224_public.der")
+ value = extract_bitstring_from_spki(key_file)
+
+ encoded = self.ref_public.export_key(format="SEC1")
+ self.assertEqual(value, encoded)
+
+ def test_export_public_sec1_compressed(self):
+ key_file = load_file("ecc_p224_public.der")
+ encoded = self.ref_public.export_key(format="SEC1", compress=True)
+
+ key_file_compressed_ref = load_file("ecc_p224_public_compressed.der")
+ value = extract_bitstring_from_spki(key_file_compressed_ref)
+ self.assertEqual(value, encoded)
+
+ def test_export_rfc5915_private_der(self):
+ key_file = load_file("ecc_p224_private.der")
+
+ encoded = self.ref_private._export_rfc5915_private_der()
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="DER", use_pkcs8=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_private_pkcs8_clear(self):
+ key_file = load_file("ecc_p224_private_p8_clear.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)
+
+ 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)
+
+ def test_export_public_pem_uncompressed(self):
+ key_file = load_file("ecc_p224_public.pem", "rt").strip()
+
+ encoded = self.ref_private._export_public_pem(False)
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_public.export_key(format="PEM")
+ self.assertEqual(key_file, encoded)
+
+ encoded = self.ref_public.export_key(format="PEM", compress=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_public_pem_compressed(self):
+ key_file = load_file("ecc_p224_public.pem", "rt").strip()
+ pub_key = ECC.import_key(key_file)
+
+ key_file_compressed = pub_key.export_key(format="PEM", compress=True)
+ key_file_compressed_ref = load_file("ecc_p224_public_compressed.pem", "rt").strip()
+
+ self.assertEqual(key_file_compressed, key_file_compressed_ref)
+
+ def test_export_private_pem_clear(self):
+ key_file = load_file("ecc_p224_private.pem", "rt").strip()
+
+ encoded = self.ref_private._export_private_pem(None)
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_private_pem_encrypted(self):
+ encoded = self.ref_private._export_private_pem(passphrase=b"secret")
+
+ # This should prove that the output is password-protected
+ self.assertRaises(ValueError, ECC.import_key, encoded)
+
+ assert "EC PRIVATE KEY" in encoded
+
+ decoded = ECC.import_key(encoded, "secret")
+ self.assertEqual(self.ref_private, decoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM",
+ passphrase="secret",
+ use_pkcs8=False)
+ decoded = ECC.import_key(encoded, "secret")
+ self.assertEqual(self.ref_private, decoded)
+
+ def test_export_private_pkcs8_and_pem_1(self):
+ # PKCS8 inside PEM with both unencrypted
+ key_file = load_file("ecc_p224_private_p8_clear.pem", "rt").strip()
+
+ encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem()
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM")
+ self.assertEqual(key_file, encoded)
+
+ def test_export_private_pkcs8_and_pem_2(self):
+ # PKCS8 inside PEM with PKCS8 encryption
+ encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("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)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM",
+ passphrase="secret",
+ protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
+ decoded = ECC.import_key(encoded, "secret")
+ self.assertEqual(self.ref_private, decoded)
+
+ 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)
+
+ # ---
+
+ encoded1 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase="secret",
+ randfunc=get_fixed_prng())
+ encoded2 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase="secret",
+ randfunc=get_fixed_prng())
+ self.assertEqual(encoded1, encoded2)
+
+ def test_byte_or_string_passphrase(self):
+ encoded1 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase="secret",
+ randfunc=get_fixed_prng())
+ encoded2 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase=b"secret",
+ 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.ref_private.export_key(format="PEM", passphrase="secret",
+ use_pkcs8=False)
+ self.assertRaises(ValueError, self.ref_private.export_key, format="PEM",
+ passphrase="secret")
+
+ # DER format but no PKCS#8
+ self.assertRaises(ValueError, self.ref_private.export_key, format="DER",
+ passphrase="secret",
+ use_pkcs8=False,
+ protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
+
+ # Incorrect parameters for public keys
+ self.assertRaises(ValueError, self.ref_public.export_key, format="DER",
+ use_pkcs8=False)
+
+ # 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")
+
+ def test_compressed_curve(self):
+
+ # Compressed P-224 curve (Y-point is even)
+ pem1 = """-----BEGIN EC PRIVATE KEY-----
+ MGgCAQEEHPYicBNI9nd6wDKAX2l+f3A0Q+KWUQeMqSt5GoOgBwYFK4EEACGhPAM6
+ AATCL6rUIDT14zXKoS5GQUMDP/tpc+1iI/FyEZikt2roKDkhU5q08srmqaysbfJN
+ eUr7Xf1lnCVGag==
+ -----END EC PRIVATE KEY-----"""
+
+ # Compressed P-224 curve (Y-point is odd)
+ pem2 = """-----BEGIN EC PRIVATE KEY-----
+ MGgCAQEEHEFjbaVPLJ3ngZyCibCvT0RLUqSlHjC5Z3e0FtugBwYFK4EEACGhPAM6
+ AAT5IvL2V6m48y1JLMGr6ZbnOqNKP9hMf9mxyVkk6/SaRoBoJVkXrNIpYL0P7DS7
+ QF8E/OGeZRwvow==
+ -----END EC PRIVATE KEY-----"""
+
+ key1 = ECC.import_key(pem1)
+ low16 = int(key1.pointQ.y % 65536)
+ self.assertEqual(low16, 0x466A)
+
+ key2 = ECC.import_key(pem2)
+ low16 = int(key2.pointQ.y % 65536)
+ self.assertEqual(low16, 0x2FA3)
+
+
+class TestExport_P256(unittest.TestCase):
+
+ def __init__(self, *args, **kwargs):
+ super(TestExport_P256, self).__init__(*args, **kwargs)
+ self.ref_private, self.ref_public = create_ref_keys_p256()
+
+ def test_export_public_der_uncompressed(self):
+ key_file = load_file("ecc_p256_public.der")
+
+ encoded = self.ref_public._export_subjectPublicKeyInfo(False)
+ 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_public_der_compressed(self):
+ key_file = load_file("ecc_p256_public.der")
+ pub_key = ECC.import_key(key_file)
+ key_file_compressed = pub_key.export_key(format="DER", compress=True)
+
+ key_file_compressed_ref = load_file("ecc_p256_public_compressed.der")
+ self.assertEqual(key_file_compressed, key_file_compressed_ref)
+
+ def test_export_public_sec1_uncompressed(self):
+ key_file = load_file("ecc_p256_public.der")
+ value = extract_bitstring_from_spki(key_file)
+
+ encoded = self.ref_public.export_key(format="SEC1")
+ self.assertEqual(value, encoded)
+
+ def test_export_public_sec1_compressed(self):
+ key_file = load_file("ecc_p256_public.der")
+ encoded = self.ref_public.export_key(format="SEC1", compress=True)
+
+ key_file_compressed_ref = load_file("ecc_p256_public_compressed.der")
+ value = extract_bitstring_from_spki(key_file_compressed_ref)
+ self.assertEqual(value, encoded)
+
+ def test_export_rfc5915_private_der(self):
+ key_file = load_file("ecc_p256_private.der")
+
+ encoded = self.ref_private._export_rfc5915_private_der()
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="DER", use_pkcs8=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_private_pkcs8_clear(self):
+ key_file = load_file("ecc_p256_private_p8_clear.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)
+
+ 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)
+
+ def test_export_public_pem_uncompressed(self):
+ key_file = load_file("ecc_p256_public.pem", "rt").strip()
+
+ encoded = self.ref_private._export_public_pem(False)
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_public.export_key(format="PEM")
+ self.assertEqual(key_file, encoded)
+
+ encoded = self.ref_public.export_key(format="PEM", compress=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_public_pem_compressed(self):
+ key_file = load_file("ecc_p256_public.pem", "rt").strip()
+ pub_key = ECC.import_key(key_file)
+
+ key_file_compressed = pub_key.export_key(format="PEM", compress=True)
+ key_file_compressed_ref = load_file("ecc_p256_public_compressed.pem", "rt").strip()
+
+ self.assertEqual(key_file_compressed, key_file_compressed_ref)
+
+ def test_export_private_pem_clear(self):
+ key_file = load_file("ecc_p256_private.pem", "rt").strip()
+
+ encoded = self.ref_private._export_private_pem(None)
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_private_pem_encrypted(self):
+ encoded = self.ref_private._export_private_pem(passphrase=b"secret")
+
+ # This should prove that the output is password-protected
+ self.assertRaises(ValueError, ECC.import_key, encoded)
+
+ assert "EC PRIVATE KEY" in encoded
+
+ decoded = ECC.import_key(encoded, "secret")
+ self.assertEqual(self.ref_private, decoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM",
+ passphrase="secret",
+ use_pkcs8=False)
+ decoded = ECC.import_key(encoded, "secret")
+ self.assertEqual(self.ref_private, decoded)
+
+ def test_export_private_pkcs8_and_pem_1(self):
+ # PKCS8 inside PEM with both unencrypted
+ key_file = load_file("ecc_p256_private_p8_clear.pem", "rt").strip()
+
+ encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem()
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM")
+ self.assertEqual(key_file, encoded)
+
+ def test_export_private_pkcs8_and_pem_2(self):
+ # PKCS8 inside PEM with PKCS8 encryption
+ encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("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)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM",
+ passphrase="secret",
+ protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
+ decoded = ECC.import_key(encoded, "secret")
+ self.assertEqual(self.ref_private, decoded)
+
+ def test_export_openssh_uncompressed(self):
+ key_file = load_file("ecc_p256_public_openssh.txt", "rt")
+
+ encoded = self.ref_public._export_openssh(False)
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_public.export_key(format="OpenSSH")
+ self.assertEqual(key_file, encoded)
+
+ encoded = self.ref_public.export_key(format="OpenSSH", compress=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_openssh_compressed(self):
+ key_file = load_file("ecc_p256_public_openssh.txt", "rt")
+ pub_key = ECC.import_key(key_file)
+
+ key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True)
+ assert len(key_file) > len(key_file_compressed)
+ self.assertEqual(pub_key, ECC.import_key(key_file_compressed))
+
+ 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)
+
+ # ---
+
+ encoded1 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase="secret",
+ randfunc=get_fixed_prng())
+ encoded2 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase="secret",
+ randfunc=get_fixed_prng())
+ self.assertEqual(encoded1, encoded2)
+
+ def test_byte_or_string_passphrase(self):
+ encoded1 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase="secret",
+ randfunc=get_fixed_prng())
+ encoded2 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase=b"secret",
+ 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.ref_private.export_key(format="PEM", passphrase="secret",
+ use_pkcs8=False)
+ self.assertRaises(ValueError, self.ref_private.export_key, format="PEM",
+ passphrase="secret")
+
+ # DER format but no PKCS#8
+ self.assertRaises(ValueError, self.ref_private.export_key, format="DER",
+ passphrase="secret",
+ use_pkcs8=False,
+ protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
+
+ # Incorrect parameters for public keys
+ self.assertRaises(ValueError, self.ref_public.export_key, format="DER",
+ use_pkcs8=False)
+
+ # 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")
+
+
+ def test_compressed_curve(self):
+
+ # Compressed P-256 curve (Y-point is even)
+ pem1 = """-----BEGIN EC PRIVATE KEY-----
+ MFcCAQEEIHTuc09jC51xXomV6MVCDN+DpAAvSmaJWZPTEHM6D5H1oAoGCCqGSM49
+ AwEHoSQDIgACWFuGbHe8yJ43rir7PMTE9w8vHz0BSpXHq90Xi7/s+a0=
+ -----END EC PRIVATE KEY-----"""
+
+ # Compressed P-256 curve (Y-point is odd)
+ pem2 = """-----BEGIN EC PRIVATE KEY-----
+ MFcCAQEEIFggiPN9SQP+FAPTCPp08fRUz7rHp2qNBRcBJ1DXhb3ZoAoGCCqGSM49
+ AwEHoSQDIgADLpph1trTIlVfa8NJvlMUPyWvL+wP+pW3BJITUL/wj9A=
+ -----END EC PRIVATE KEY-----"""
+
+ key1 = ECC.import_key(pem1)
+ low16 = int(key1.pointQ.y % 65536)
+ self.assertEqual(low16, 0xA6FC)
+
+ key2 = ECC.import_key(pem2)
+ low16 = int(key2.pointQ.y % 65536)
+ self.assertEqual(low16, 0x6E57)
+
+
+class TestExport_P384(unittest.TestCase):
+
+ def __init__(self, *args, **kwargs):
+ super(TestExport_P384, self).__init__(*args, **kwargs)
+ self.ref_private, self.ref_public = create_ref_keys_p384()
+
+ def test_export_public_der_uncompressed(self):
+ key_file = load_file("ecc_p384_public.der")
+
+ encoded = self.ref_public._export_subjectPublicKeyInfo(False)
+ 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_public_der_compressed(self):
+ key_file = load_file("ecc_p384_public.der")
+ pub_key = ECC.import_key(key_file)
+ key_file_compressed = pub_key.export_key(format="DER", compress=True)
+
+ key_file_compressed_ref = load_file("ecc_p384_public_compressed.der")
+ self.assertEqual(key_file_compressed, key_file_compressed_ref)
+
+ def test_export_public_sec1_uncompressed(self):
+ key_file = load_file("ecc_p384_public.der")
+ value = extract_bitstring_from_spki(key_file)
+
+ encoded = self.ref_public.export_key(format="SEC1")
+ self.assertEqual(value, encoded)
+
+ def test_export_public_sec1_compressed(self):
+ key_file = load_file("ecc_p384_public.der")
+ encoded = self.ref_public.export_key(format="SEC1", compress=True)
+
+ key_file_compressed_ref = load_file("ecc_p384_public_compressed.der")
+ value = extract_bitstring_from_spki(key_file_compressed_ref)
+ self.assertEqual(value, encoded)
+
+ def test_export_rfc5915_private_der(self):
+ key_file = load_file("ecc_p384_private.der")
+
+ encoded = self.ref_private._export_rfc5915_private_der()
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="DER", use_pkcs8=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_private_pkcs8_clear(self):
+ key_file = load_file("ecc_p384_private_p8_clear.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)
+
+ 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)
+
+ def test_export_public_pem_uncompressed(self):
+ key_file = load_file("ecc_p384_public.pem", "rt").strip()
+
+ encoded = self.ref_private._export_public_pem(False)
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_public.export_key(format="PEM")
+ self.assertEqual(key_file, encoded)
+
+ encoded = self.ref_public.export_key(format="PEM", compress=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_public_pem_compressed(self):
+ key_file = load_file("ecc_p384_public.pem", "rt").strip()
+ pub_key = ECC.import_key(key_file)
+
+ key_file_compressed = pub_key.export_key(format="PEM", compress=True)
+ key_file_compressed_ref = load_file("ecc_p384_public_compressed.pem", "rt").strip()
+
+ self.assertEqual(key_file_compressed, key_file_compressed_ref)
+
+ def test_export_private_pem_clear(self):
+ key_file = load_file("ecc_p384_private.pem", "rt").strip()
+
+ encoded = self.ref_private._export_private_pem(None)
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_private_pem_encrypted(self):
+ encoded = self.ref_private._export_private_pem(passphrase=b"secret")
+
+ # This should prove that the output is password-protected
+ self.assertRaises(ValueError, ECC.import_key, encoded)
+
+ assert "EC PRIVATE KEY" in encoded
+
+ decoded = ECC.import_key(encoded, "secret")
+ self.assertEqual(self.ref_private, decoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM",
+ passphrase="secret",
+ use_pkcs8=False)
+ decoded = ECC.import_key(encoded, "secret")
+ self.assertEqual(self.ref_private, decoded)
+
+ def test_export_private_pkcs8_and_pem_1(self):
+ # PKCS8 inside PEM with both unencrypted
+ key_file = load_file("ecc_p384_private_p8_clear.pem", "rt").strip()
+
+ encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem()
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM")
+ self.assertEqual(key_file, encoded)
+
+ def test_export_private_pkcs8_and_pem_2(self):
+ # PKCS8 inside PEM with PKCS8 encryption
+ encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("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)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM",
+ passphrase="secret",
+ protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
+ decoded = ECC.import_key(encoded, "secret")
+ self.assertEqual(self.ref_private, decoded)
+
+ def test_export_openssh_uncompressed(self):
+ key_file = load_file("ecc_p384_public_openssh.txt", "rt")
+
+ encoded = self.ref_public._export_openssh(False)
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_public.export_key(format="OpenSSH")
+ self.assertEqual(key_file, encoded)
+
+ encoded = self.ref_public.export_key(format="OpenSSH", compress=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_openssh_compressed(self):
+ key_file = load_file("ecc_p384_public_openssh.txt", "rt")
+ pub_key = ECC.import_key(key_file)
+
+ key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True)
+ assert len(key_file) > len(key_file_compressed)
+ self.assertEqual(pub_key, ECC.import_key(key_file_compressed))
+
+ 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)
+
+ # ---
+
+ encoded1 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase="secret",
+ randfunc=get_fixed_prng())
+ encoded2 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase="secret",
+ randfunc=get_fixed_prng())
+ self.assertEqual(encoded1, encoded2)
+
+ def test_byte_or_string_passphrase(self):
+ encoded1 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase="secret",
+ randfunc=get_fixed_prng())
+ encoded2 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase=b"secret",
+ 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.ref_private.export_key(format="PEM", passphrase="secret",
+ use_pkcs8=False)
+ self.assertRaises(ValueError, self.ref_private.export_key, format="PEM",
+ passphrase="secret")
+
+ # DER format but no PKCS#8
+ self.assertRaises(ValueError, self.ref_private.export_key, format="DER",
+ passphrase="secret",
+ use_pkcs8=False,
+ protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
+
+ # Incorrect parameters for public keys
+ self.assertRaises(ValueError, self.ref_public.export_key, format="DER",
+ use_pkcs8=False)
+
+ # 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")
+
+ def test_compressed_curve(self):
+
+ # Compressed P-384 curve (Y-point is even)
+ # openssl ecparam -name secp384p1 -genkey -noout -conv_form compressed -out /tmp/a.pem
+ # openssl ec -in /tmp/a.pem -text -noout
+ pem1 = """-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDAM0lEIhvXuekK2SWtdbgOcZtBaxa9TxfpO/GcDFZLCJ3JVXaTgwken
+QT+C+XLtD6WgBwYFK4EEACKhZANiAATs0kZMhFDu8DoBC21jrSDPyAUn4aXZ/DM4
+ylhDfWmb4LEbeszXceIzfhIUaaGs5y1xXaqf5KXTiAAYx2pKUzAAM9lcGUHCGKJG
+k4AgUmVJON29XoUilcFrzjDmuye3B6Q=
+-----END EC PRIVATE KEY-----"""
+
+ # Compressed P-384 curve (Y-point is odd)
+ pem2 = """-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDDHPFTslYLltE16fHdSDTtE/2HTmd3M8mqy5MttAm4wZ833KXiGS9oe
+kFdx9sNV0KygBwYFK4EEACKhZANiAASLIE5RqVMtNhtBH/u/p/ifqOAlKnK/+RrQ
+YC46ZRsnKNayw3wATdPjgja7L/DSII3nZK0G6KOOVwJBznT/e+zudUJYhZKaBLRx
+/bgXyxUtYClOXxb1Y/5N7txLstYRyP0=
+-----END EC PRIVATE KEY-----"""
+
+ key1 = ECC.import_key(pem1)
+ low16 = int(key1.pointQ.y % 65536)
+ self.assertEqual(low16, 0x07a4)
+
+ key2 = ECC.import_key(pem2)
+ low16 = int(key2.pointQ.y % 65536)
+ self.assertEqual(low16, 0xc8fd)
+
+
+class TestExport_P521(unittest.TestCase):
+
+ def __init__(self, *args, **kwargs):
+ super(TestExport_P521, self).__init__(*args, **kwargs)
+ self.ref_private, self.ref_public = create_ref_keys_p521()
+
+ def test_export_public_der_uncompressed(self):
+ key_file = load_file("ecc_p521_public.der")
+
+ encoded = self.ref_public._export_subjectPublicKeyInfo(False)
+ 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_public_der_compressed(self):
+ key_file = load_file("ecc_p521_public.der")
+ pub_key = ECC.import_key(key_file)
+ key_file_compressed = pub_key.export_key(format="DER", compress=True)
+
+ key_file_compressed_ref = load_file("ecc_p521_public_compressed.der")
+ self.assertEqual(key_file_compressed, key_file_compressed_ref)
+
+ def test_export_public_sec1_uncompressed(self):
+ key_file = load_file("ecc_p521_public.der")
+ value = extract_bitstring_from_spki(key_file)
+
+ encoded = self.ref_public.export_key(format="SEC1")
+ self.assertEqual(value, encoded)
+
+ encoded = self.ref_public.export_key(format="raw")
+ self.assertEqual(value, encoded)
+
+ def test_export_public_sec1_compressed(self):
+ key_file = load_file("ecc_p521_public.der")
+ encoded = self.ref_public.export_key(format="SEC1", compress=True)
+
+ key_file_compressed_ref = load_file("ecc_p521_public_compressed.der")
+ value = extract_bitstring_from_spki(key_file_compressed_ref)
+ self.assertEqual(value, encoded)
+
+ encoded = self.ref_public.export_key(format="raw", compress=True)
+ self.assertEqual(value, encoded)
+
+ def test_export_rfc5915_private_der(self):
+ key_file = load_file("ecc_p521_private.der")
+
+ encoded = self.ref_private._export_rfc5915_private_der()
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="DER", use_pkcs8=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_private_pkcs8_clear(self):
+ key_file = load_file("ecc_p521_private_p8_clear.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)
+
+ 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)
+
+ def test_export_public_pem_uncompressed(self):
+ key_file = load_file("ecc_p521_public.pem", "rt").strip()
+
+ encoded = self.ref_private._export_public_pem(False)
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_public.export_key(format="PEM")
+ self.assertEqual(key_file, encoded)
+
+ encoded = self.ref_public.export_key(format="PEM", compress=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_public_pem_compressed(self):
+ key_file = load_file("ecc_p521_public.pem", "rt").strip()
+ pub_key = ECC.import_key(key_file)
+
+ key_file_compressed = pub_key.export_key(format="PEM", compress=True)
+ key_file_compressed_ref = load_file("ecc_p521_public_compressed.pem", "rt").strip()
+
+ self.assertEqual(key_file_compressed, key_file_compressed_ref)
+
+ def test_export_private_pem_clear(self):
+ key_file = load_file("ecc_p521_private.pem", "rt").strip()
+
+ encoded = self.ref_private._export_private_pem(None)
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_private_pem_encrypted(self):
+ encoded = self.ref_private._export_private_pem(passphrase=b"secret")
+
+ # This should prove that the output is password-protected
+ self.assertRaises(ValueError, ECC.import_key, encoded)
+
+ assert "EC PRIVATE KEY" in encoded
+
+ decoded = ECC.import_key(encoded, "secret")
+ self.assertEqual(self.ref_private, decoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM",
+ passphrase="secret",
+ use_pkcs8=False)
+ decoded = ECC.import_key(encoded, "secret")
+ self.assertEqual(self.ref_private, decoded)
+
+ def test_export_private_pkcs8_and_pem_1(self):
+ # PKCS8 inside PEM with both unencrypted
+ key_file = load_file("ecc_p521_private_p8_clear.pem", "rt").strip()
+
+ encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem()
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM")
+ self.assertEqual(key_file, encoded)
+
+ def test_export_private_pkcs8_and_pem_2(self):
+ # PKCS8 inside PEM with PKCS8 encryption
+ encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("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)
+
+ # ---
+
+ encoded = self.ref_private.export_key(format="PEM",
+ passphrase="secret",
+ protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
+ decoded = ECC.import_key(encoded, "secret")
+ self.assertEqual(self.ref_private, decoded)
+
+ def test_export_openssh_uncompressed(self):
+ key_file = load_file("ecc_p521_public_openssh.txt", "rt")
+
+ encoded = self.ref_public._export_openssh(False)
+ self.assertEqual(key_file, encoded)
+
+ # ---
+
+ encoded = self.ref_public.export_key(format="OpenSSH")
+ self.assertEqual(key_file, encoded)
+
+ encoded = self.ref_public.export_key(format="OpenSSH", compress=False)
+ self.assertEqual(key_file, encoded)
+
+ def test_export_openssh_compressed(self):
+ key_file = load_file("ecc_p521_public_openssh.txt", "rt")
+ pub_key = ECC.import_key(key_file)
+
+ key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True)
+ assert len(key_file) > len(key_file_compressed)
+ self.assertEqual(pub_key, ECC.import_key(key_file_compressed))
+
+ 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)
+
+ # ---
+
+ encoded1 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase="secret",
+ randfunc=get_fixed_prng())
+ encoded2 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase="secret",
+ randfunc=get_fixed_prng())
+ self.assertEqual(encoded1, encoded2)
+
+ def test_byte_or_string_passphrase(self):
+ encoded1 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase="secret",
+ randfunc=get_fixed_prng())
+ encoded2 = self.ref_private.export_key(format="PEM",
+ use_pkcs8=False,
+ passphrase=b"secret",
+ 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.ref_private.export_key(format="PEM", passphrase="secret",
+ use_pkcs8=False)
+ self.assertRaises(ValueError, self.ref_private.export_key, format="PEM",
+ passphrase="secret")
+
+ # DER format but no PKCS#8
+ self.assertRaises(ValueError, self.ref_private.export_key, format="DER",
+ passphrase="secret",
+ use_pkcs8=False,
+ protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
+
+ # Incorrect parameters for public keys
+ self.assertRaises(ValueError, self.ref_public.export_key, format="DER",
+ use_pkcs8=False)
+
+ # 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")
+
+ def test_compressed_curve(self):
+
+ # Compressed P-521 curve (Y-point is even)
+ # openssl ecparam -name secp521r1 -genkey -noout -conv_form compressed -out /tmp/a.pem
+ # openssl ec -in /tmp/a.pem -text -noout
+ pem1 = """-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIAnm1CEjVjvNfXEN730p+D6su5l+mOztdc5XmTEoti+s2R4GQ4mAv3
+0zYLvyklvOHw0+yy8d0cyGEJGb8T3ZVKmg2gBwYFK4EEACOhgYkDgYYABAHzjTI1
+ckxQ3Togi0LAxiG0PucdBBBs5oIy3df95xv6SInp70z+4qQ2EltEmdNMssH8eOrl
+M5CYdZ6nbcHMVaJUvQEzTrYxvFjOgJiOd+E9eBWbLkbMNqsh1UKVO6HbMbW0ohCI
+uGxO8tM6r3w89/qzpG2SvFM/fvv3mIR30wSZDD84qA==
+-----END EC PRIVATE KEY-----"""
+
+ # Compressed P-521 curve (Y-point is odd)
+ pem2 = """-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIB84OfhJluLBRLn3+cC/RQ37C2SfQVP/t0gQK2tCsTf5avRcWYRrOJ
+PmX9lNnkC0Hobd75QFRmdxrB0Wd1/M4jZOWgBwYFK4EEACOhgYkDgYYABAAMZcdJ
+1YLCGHt3bHCEzdidVy6+brlJIbv1aQ9fPQLF7WKNv4c8w3H8d5a2+SDZilBOsk5c
+6cNJDMz2ExWQvxl4CwDJtJGt1+LHVKFGy73NANqVxMbRu+2F8lOxkNp/ziFTbVyV
+vv6oYkMIIi7r5oQWAiQDrR2mlrrFDL9V7GH/r8SWQw==
+-----END EC PRIVATE KEY-----"""
+
+ key1 = ECC.import_key(pem1)
+ low16 = int(key1.pointQ.y % 65536)
+ self.assertEqual(low16, 0x38a8)
+
+ key2 = ECC.import_key(pem2)
+ low16 = int(key2.pointQ.y % 65536)
+ self.assertEqual(low16, 0x9643)
+
+
+class TestImport_Ed25519(unittest.TestCase):
+
+ def __init__(self, *args, **kwargs):
+ super(TestImport_Ed25519, self).__init__(*args, **kwargs)
+ self.ref_private, self.ref_public = create_ref_keys_ed25519()
+
+ def test_import_public_der(self):
+ key_file = load_file("ecc_ed25519_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_ed25519_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_ed25519_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_ed25519_private_p8.pem")
+
+ key = ECC.import_key(key_file, "secret")
+ self.assertEqual(self.ref_private, key)
+
+ def test_import_x509_der(self):
+ key_file = load_file("ecc_ed25519_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_ed25519_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_ed25519_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_ed25519_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_ed25519_x509.pem")
+
+ key = ECC.import_key(key_file)
+ self.assertEqual(self.ref_public, key)
+
+ def test_import_openssh_public(self):
+ key_file = load_file("ecc_ed25519_public_openssh.txt")
+ key = ECC._import_openssh_public(key_file)
+ self.failIf(key.has_private())
+ key = ECC.import_key(key_file)
+ self.failIf(key.has_private())
+
+ def test_import_openssh_private_clear(self):
+ key_file = load_file("ecc_ed25519_private_openssh.pem")
+ key = ECC.import_key(key_file)
+
+ def test_import_openssh_private_password(self):
+ key_file = load_file("ecc_ed25519_private_openssh_pwd.pem")
+ key = ECC.import_key(key_file, b"password")
+
+
+class TestExport_Ed25519(unittest.TestCase):
+
+ def __init__(self, *args, **kwargs):
+ super(TestExport_Ed25519, self).__init__(*args, **kwargs)
+ self.ref_private, self.ref_public = create_ref_keys_ed25519()
+
+ def test_export_public_der(self):
+ key_file = load_file("ecc_ed25519_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_public_sec1(self):
+ self.assertRaises(ValueError, self.ref_public.export_key, format="SEC1")
+
+ def test_export_private_pkcs8_clear(self):
+ key_file = load_file("ecc_ed25519_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)
+
+ def test_export_public_pem(self):
+ key_file_ref = load_file("ecc_ed25519_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_ed25519_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_openssh(self):
+ key_file = load_file("ecc_ed25519_public_openssh.txt", "rt")
+ public_key = ECC.import_key(key_file)
+ key_file = " ".join(key_file.split(' ')[:2]) # remove comment
+
+ encoded = public_key._export_openssh(False)
+ self.assertEqual(key_file, encoded.strip())
+
+ encoded = public_key.export_key(format="OpenSSH")
+ self.assertEqual(key_file, encoded.strip())
+
+ def test_export_raw(self):
+ encoded = self.ref_public.export_key(format='raw')
+ self.assertEqual(encoded, unhexlify(b'bc85b8cf585d20a4de47e84d1cb6183f63d9ba96223fcbc886e363ffdea20cff'))
+
+ 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_Ed448(unittest.TestCase):
+
+ def __init__(self, *args, **kwargs):
+ super(TestImport_Ed448, self).__init__(*args, **kwargs)
+ self.ref_private, self.ref_public = create_ref_keys_ed448()
+
+ def test_import_public_der(self):
+ key_file = load_file("ecc_ed448_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_ed448_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_ed448_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_ed448_private_p8.pem")
+
+ key = ECC.import_key(key_file, "secret")
+ self.assertEqual(self.ref_private, key)
+
+ def test_import_x509_der(self):
+ key_file = load_file("ecc_ed448_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_ed448_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_ed448_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_ed448_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_ed448_x509.pem")
+
+ key = ECC.import_key(key_file)
+ self.assertEqual(self.ref_public, key)
+
+
+class TestExport_Ed448(unittest.TestCase):
+
+ def __init__(self, *args, **kwargs):
+ super(TestExport_Ed448, self).__init__(*args, **kwargs)
+ self.ref_private, self.ref_public = create_ref_keys_ed448()
+
+ def test_export_public_der(self):
+ key_file = load_file("ecc_ed448_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_public_sec1(self):
+ self.assertRaises(ValueError, self.ref_public.export_key, format="SEC1")
+
+ def test_export_private_pkcs8_clear(self):
+ key_file = load_file("ecc_ed448_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)
+
+ def test_export_public_pem(self):
+ key_file_ref = load_file("ecc_ed448_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_ed448_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_openssh(self):
+ # Not supported
+ self.assertRaises(ValueError, self.ref_public.export_key, format="OpenSSH")
+
+ def test_export_raw(self):
+ encoded = self.ref_public.export_key(format='raw')
+ self.assertEqual(encoded, unhexlify(b'899014ddc0a0e1260cfc1085afdf952019e9fd63372e3e366e26dad32b176624884330a14617237e3081febd9d1a15069e7499433d2f55dd80'))
+
+ 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")
+
+
+def get_tests(config={}):
+ tests = []
+ tests += list_test_cases(TestImport)
+ try:
+ tests += list_test_cases(TestImport_P192)
+ tests += list_test_cases(TestImport_P224)
+ tests += list_test_cases(TestImport_P256)
+ tests += list_test_cases(TestImport_P384)
+ tests += list_test_cases(TestImport_P521)
+ tests += list_test_cases(TestImport_Ed25519)
+ tests += list_test_cases(TestImport_Ed448)
+
+ tests += list_test_cases(TestExport_P192)
+ tests += list_test_cases(TestExport_P224)
+ tests += list_test_cases(TestExport_P256)
+ tests += list_test_cases(TestExport_P384)
+ tests += list_test_cases(TestExport_P521)
+ tests += list_test_cases(TestExport_Ed25519)
+ tests += list_test_cases(TestExport_Ed448)
+
+ except MissingTestVectorException:
+ pass
+ return tests
+
+
+if __name__ == '__main__':
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
diff --git a/lib/Crypto/SelfTest/PublicKey/test_import_RSA.py b/lib/Crypto/SelfTest/PublicKey/test_import_RSA.py
new file mode 100644
index 0000000..fa92fb0
--- /dev/null
+++ b/lib/Crypto/SelfTest/PublicKey/test_import_RSA.py
@@ -0,0 +1,590 @@
+# -*- 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 Crypto.PublicKey import RSA
+from Crypto.SelfTest.st_common import a2b_hex, list_test_cases
+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("Warning: skipping extended tests for RSA",
+ UserWarning,
+ stacklevel=2)
+
+ 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 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_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)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+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__':
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
+
+# vim:set ts=4 sw=4 sts=4 expandtab: