1""" 2Tests for ECDSA keys 3""" 4 5# SPDX-License-Identifier: Apache-2.0 6 7import hashlib 8import io 9import os.path 10import sys 11import tempfile 12import unittest 13 14from cryptography.exceptions import InvalidSignature 15from cryptography.hazmat.primitives.asymmetric import ed25519 16 17sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../..'))) 18 19from imgtool.keys import load, Ed25519, Ed25519UsageError 20 21 22class Ed25519KeyGeneration(unittest.TestCase): 23 24 def setUp(self): 25 self.test_dir = tempfile.TemporaryDirectory() 26 27 def tname(self, base): 28 return os.path.join(self.test_dir.name, base) 29 30 def tearDown(self): 31 self.test_dir.cleanup() 32 33 def test_keygen(self): 34 name1 = self.tname("keygen.pem") 35 k = Ed25519.generate() 36 k.export_private(name1, b'secret') 37 38 self.assertIsNone(load(name1)) 39 40 k2 = load(name1, b'secret') 41 42 pubname = self.tname('keygen-pub.pem') 43 k2.export_public(pubname) 44 pk2 = load(pubname) 45 46 # We should be able to export the public key from the loaded 47 # public key, but not the private key. 48 pk2.export_public(self.tname('keygen-pub2.pem')) 49 self.assertRaises(Ed25519UsageError, 50 pk2.export_private, self.tname('keygen-priv2.pem')) 51 52 def test_emit(self): 53 """Basic sanity check on the code emitters.""" 54 k = Ed25519.generate() 55 56 ccode = io.StringIO() 57 k.emit_c_public(ccode) 58 self.assertIn("ed25519_pub_key", ccode.getvalue()) 59 self.assertIn("ed25519_pub_key_len", ccode.getvalue()) 60 61 rustcode = io.StringIO() 62 k.emit_rust_public(rustcode) 63 self.assertIn("ED25519_PUB_KEY", rustcode.getvalue()) 64 65 def test_emit_pub(self): 66 """Basic sanity check on the code emitters.""" 67 pubname = self.tname("public.pem") 68 k = Ed25519.generate() 69 k.export_public(pubname) 70 71 k2 = load(pubname) 72 73 ccode = io.StringIO() 74 k2.emit_c_public(ccode) 75 self.assertIn("ed25519_pub_key", ccode.getvalue()) 76 self.assertIn("ed25519_pub_key_len", ccode.getvalue()) 77 78 rustcode = io.StringIO() 79 k2.emit_rust_public(rustcode) 80 self.assertIn("ED25519_PUB_KEY", rustcode.getvalue()) 81 82 def test_sig(self): 83 k = Ed25519.generate() 84 buf = b'This is the message' 85 sha = hashlib.sha256() 86 sha.update(buf) 87 digest = sha.digest() 88 sig = k.sign_digest(digest) 89 90 # The code doesn't have any verification, so verify this 91 # manually. 92 k.key.public_key().verify(signature=sig, data=digest) 93 94 # Modify the message to make sure the signature fails. 95 sha = hashlib.sha256() 96 sha.update(b'This is thE message') 97 new_digest = sha.digest() 98 self.assertRaises(InvalidSignature, 99 k.key.public_key().verify, 100 signature=sig, 101 data=new_digest) 102 103 104if __name__ == '__main__': 105 unittest.main() 106