1# This file is dual licensed under the terms of the Apache License, Version 2# 2.0, and the BSD License. See the LICENSE file in the root of this repository 3# for complete details. 4 5from __future__ import absolute_import, division, print_function 6 7from cryptography import exceptions, utils 8from cryptography.hazmat.primitives import serialization 9from cryptography.hazmat.primitives.asymmetric.ed448 import ( 10 Ed448PrivateKey, 11 Ed448PublicKey, 12) 13 14_ED448_KEY_SIZE = 57 15_ED448_SIG_SIZE = 114 16 17 18@utils.register_interface(Ed448PublicKey) 19class _Ed448PublicKey(object): 20 def __init__(self, backend, evp_pkey): 21 self._backend = backend 22 self._evp_pkey = evp_pkey 23 24 def public_bytes(self, encoding, format): 25 if ( 26 encoding is serialization.Encoding.Raw 27 or format is serialization.PublicFormat.Raw 28 ): 29 if ( 30 encoding is not serialization.Encoding.Raw 31 or format is not serialization.PublicFormat.Raw 32 ): 33 raise ValueError( 34 "When using Raw both encoding and format must be Raw" 35 ) 36 37 return self._raw_public_bytes() 38 39 return self._backend._public_key_bytes( 40 encoding, format, self, self._evp_pkey, None 41 ) 42 43 def _raw_public_bytes(self): 44 buf = self._backend._ffi.new("unsigned char []", _ED448_KEY_SIZE) 45 buflen = self._backend._ffi.new("size_t *", _ED448_KEY_SIZE) 46 res = self._backend._lib.EVP_PKEY_get_raw_public_key( 47 self._evp_pkey, buf, buflen 48 ) 49 self._backend.openssl_assert(res == 1) 50 self._backend.openssl_assert(buflen[0] == _ED448_KEY_SIZE) 51 return self._backend._ffi.buffer(buf, _ED448_KEY_SIZE)[:] 52 53 def verify(self, signature, data): 54 evp_md_ctx = self._backend._lib.EVP_MD_CTX_new() 55 self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) 56 evp_md_ctx = self._backend._ffi.gc( 57 evp_md_ctx, self._backend._lib.EVP_MD_CTX_free 58 ) 59 res = self._backend._lib.EVP_DigestVerifyInit( 60 evp_md_ctx, 61 self._backend._ffi.NULL, 62 self._backend._ffi.NULL, 63 self._backend._ffi.NULL, 64 self._evp_pkey, 65 ) 66 self._backend.openssl_assert(res == 1) 67 res = self._backend._lib.EVP_DigestVerify( 68 evp_md_ctx, signature, len(signature), data, len(data) 69 ) 70 if res != 1: 71 self._backend._consume_errors() 72 raise exceptions.InvalidSignature 73 74 75@utils.register_interface(Ed448PrivateKey) 76class _Ed448PrivateKey(object): 77 def __init__(self, backend, evp_pkey): 78 self._backend = backend 79 self._evp_pkey = evp_pkey 80 81 def public_key(self): 82 buf = self._backend._ffi.new("unsigned char []", _ED448_KEY_SIZE) 83 buflen = self._backend._ffi.new("size_t *", _ED448_KEY_SIZE) 84 res = self._backend._lib.EVP_PKEY_get_raw_public_key( 85 self._evp_pkey, buf, buflen 86 ) 87 self._backend.openssl_assert(res == 1) 88 self._backend.openssl_assert(buflen[0] == _ED448_KEY_SIZE) 89 public_bytes = self._backend._ffi.buffer(buf)[:] 90 return self._backend.ed448_load_public_bytes(public_bytes) 91 92 def sign(self, data): 93 evp_md_ctx = self._backend._lib.EVP_MD_CTX_new() 94 self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) 95 evp_md_ctx = self._backend._ffi.gc( 96 evp_md_ctx, self._backend._lib.EVP_MD_CTX_free 97 ) 98 res = self._backend._lib.EVP_DigestSignInit( 99 evp_md_ctx, 100 self._backend._ffi.NULL, 101 self._backend._ffi.NULL, 102 self._backend._ffi.NULL, 103 self._evp_pkey, 104 ) 105 self._backend.openssl_assert(res == 1) 106 buf = self._backend._ffi.new("unsigned char[]", _ED448_SIG_SIZE) 107 buflen = self._backend._ffi.new("size_t *", len(buf)) 108 res = self._backend._lib.EVP_DigestSign( 109 evp_md_ctx, buf, buflen, data, len(data) 110 ) 111 self._backend.openssl_assert(res == 1) 112 self._backend.openssl_assert(buflen[0] == _ED448_SIG_SIZE) 113 return self._backend._ffi.buffer(buf, buflen[0])[:] 114 115 def private_bytes(self, encoding, format, encryption_algorithm): 116 if ( 117 encoding is serialization.Encoding.Raw 118 or format is serialization.PublicFormat.Raw 119 ): 120 if ( 121 format is not serialization.PrivateFormat.Raw 122 or encoding is not serialization.Encoding.Raw 123 or not isinstance( 124 encryption_algorithm, serialization.NoEncryption 125 ) 126 ): 127 raise ValueError( 128 "When using Raw both encoding and format must be Raw " 129 "and encryption_algorithm must be NoEncryption()" 130 ) 131 132 return self._raw_private_bytes() 133 134 return self._backend._private_key_bytes( 135 encoding, format, encryption_algorithm, self, self._evp_pkey, None 136 ) 137 138 def _raw_private_bytes(self): 139 buf = self._backend._ffi.new("unsigned char []", _ED448_KEY_SIZE) 140 buflen = self._backend._ffi.new("size_t *", _ED448_KEY_SIZE) 141 res = self._backend._lib.EVP_PKEY_get_raw_private_key( 142 self._evp_pkey, buf, buflen 143 ) 144 self._backend.openssl_assert(res == 1) 145 self._backend.openssl_assert(buflen[0] == _ED448_KEY_SIZE) 146 return self._backend._ffi.buffer(buf, _ED448_KEY_SIZE)[:] 147