8181# Import the PyNaCl library, if available. It is recommended this library be
8282# used over the pure python implementation of Ed25519, due to its speedier
8383# routines and side-channel protections available in the libsodium library.
84- #
85- # TODO: Version 0.2.3 of 'pynacl' prints: "UserWarning: reimporting '...' might
86- # overwrite older definitions." when importing 'nacl.signing'. Suppress user
87- # warnings temporarily (at least until this issue is fixed by PyNaCl).
88- #
89- # Note: A 'pragma: no cover' comment is intended for test 'coverage'. Lines
90- # or code blocks with this comment should not be flagged as uncovered.
91- # pynacl will always be install prior to running the unit tests.
92- with warnings .catch_warnings ():
93- warnings .simplefilter ('ignore' )
94- try :
95- import nacl .signing
96- import nacl .encoding
97-
98- # PyNaCl's 'cffi' dependency may raise an 'IOError' exception when importing
99- # 'nacl.signing'.
100- except (ImportError , IOError ): # pragma: no cover
101- pass
84+ NACL = True
85+ NO_NACL_MSG = "ed25519 key support requires the nacl library"
86+ try :
87+ import nacl .signing
88+ import nacl .encoding
89+ except ImportError :
90+ NACL = False
10291
10392# The optimized pure Python implementation of Ed25519. If
10493# PyNaCl cannot be imported and an attempt to use is made in this module, a
@@ -155,6 +144,9 @@ def generate_public_and_private():
155144 'securesystemslib.formats.ED25519SEED_SCHEMA', respectively.
156145 """
157146
147+ if not NACL : # pragma: no cover
148+ raise securesystemslib .exceptions .UnsupportedLibraryError (NO_NACL_MSG )
149+
158150 # Generate ed25519's seed key by calling os.urandom(). The random bytes
159151 # returned should be suitable for cryptographic use and is OS-specific.
160152 # Raise 'NotImplementedError' if a randomness source is not found.
@@ -165,21 +157,13 @@ def generate_public_and_private():
165157
166158 # Generate the public key. PyNaCl (i.e., 'nacl' module) performs the actual
167159 # key generation.
168- try :
169- nacl_key = nacl .signing .SigningKey (seed )
170- public = nacl_key .verify_key .encode (encoder = nacl .encoding .RawEncoder ())
171-
172- except NameError : # pragma: no cover
173- raise securesystemslib .exceptions .UnsupportedLibraryError ('The PyNaCl'
174- ' library and/or its dependencies unavailable.' )
175-
160+ nacl_key = nacl .signing .SigningKey (seed )
161+ public = nacl_key .verify_key .encode (encoder = nacl .encoding .RawEncoder ())
176162
177163 return public , seed
178164
179165
180166
181-
182-
183167def create_signature (public_key , private_key , data , scheme ):
184168 """
185169 <Purpose>
@@ -227,6 +211,9 @@ def create_signature(public_key, private_key, data, scheme):
227211
228212 securesystemslib.exceptions.CryptoError, if a signature cannot be created.
229213
214+ securesystemslib.exceptions.UnsupportedLibraryError, if the PyNaCl ('nacl')
215+ module is unavailable.
216+
230217 <Side Effects>
231218 nacl.signing.SigningKey.sign() called to generate the actual signature.
232219
@@ -237,6 +224,9 @@ def create_signature(public_key, private_key, data, scheme):
237224 returned.
238225 """
239226
227+ if not NACL : # pragma: no cover
228+ raise securesystemslib .exceptions .UnsupportedLibraryError (NO_NACL_MSG )
229+
240230 # Does 'public_key' have the correct format?
241231 # This check will ensure 'public_key' conforms to
242232 # 'securesystemslib.formats.ED25519PUBLIC_SCHEMA', which must have length 32
@@ -265,11 +255,6 @@ def create_signature(public_key, private_key, data, scheme):
265255 nacl_sig = nacl_key .sign (data )
266256 signature = nacl_sig .signature
267257
268- # The unit tests expect required libraries to be installed.
269- except NameError : # pragma: no cover
270- raise securesystemslib .exceptions .UnsupportedLibraryError ('The PyNaCl'
271- ' library and/or its dependencies unavailable.' )
272-
273258 except (ValueError , TypeError , nacl .exceptions .CryptoError ) as e :
274259 raise securesystemslib .exceptions .CryptoError ('An "ed25519" signature'
275260 ' could not be created with PyNaCl.' + str (e ))
@@ -286,7 +271,7 @@ def create_signature(public_key, private_key, data, scheme):
286271
287272
288273
289- def verify_signature (public_key , scheme , signature , data , use_pynacl = False ):
274+ def verify_signature (public_key , scheme , signature , data ):
290275 """
291276 <Purpose>
292277 Determine whether the private key corresponding to 'public_key' produced
@@ -298,14 +283,12 @@ def verify_signature(public_key, scheme, signature, data, use_pynacl=False):
298283 >>> scheme = 'ed25519'
299284 >>> signature, scheme = \
300285 create_signature(public, private, data, scheme)
301- >>> verify_signature(public, scheme, signature, data, use_pynacl=False)
302- True
303- >>> verify_signature(public, scheme, signature, data, use_pynacl=True)
286+ >>> verify_signature(public, scheme, signature, data)
304287 True
305288 >>> bad_data = b'The sly brown fox jumps over the lazy dog'
306289 >>> bad_signature, scheme = \
307290 create_signature(public, private, bad_data, scheme)
308- >>> verify_signature(public, scheme, bad_signature, data, use_pynacl=False )
291+ >>> verify_signature(public, scheme, bad_signature, data)
309292 False
310293
311294 <Arguments>
@@ -323,11 +306,6 @@ def verify_signature(public_key, scheme, signature, data, use_pynacl=False):
323306 Data object used by securesystemslib.ed25519_keys.create_signature() to
324307 generate 'signature'. 'data' is needed here to verify the signature.
325308
326- use_pynacl:
327- True, if the ed25519 signature should be verified by PyNaCl. False,
328- if the signature should be verified with the pure Python implementation
329- of ed25519 (slower).
330-
331309 <Exceptions>
332310 securesystemslib.exceptions.UnsupportedAlgorithmError. Raised if the
333311 signature scheme 'scheme' is not one supported by
@@ -337,9 +315,9 @@ def verify_signature(public_key, scheme, signature, data, use_pynacl=False):
337315 improperly formatted.
338316
339317 <Side Effects>
318+ nacl.signing.VerifyKey.verify() called if available, otherwise
340319 securesystemslib._vendor.ed25519.ed25519.checkvalid() called to do the
341- actual verification. nacl.signing.VerifyKey.verify() called if
342- 'use_pynacl' is True.
320+ verification.
343321
344322 <Returns>
345323 Boolean. True if the signature is valid, False otherwise.
@@ -357,28 +335,18 @@ def verify_signature(public_key, scheme, signature, data, use_pynacl=False):
357335 # Is 'signature' properly formatted?
358336 securesystemslib .formats .ED25519SIGNATURE_SCHEMA .check_match (signature )
359337
360- # Is 'use_pynacl' properly formatted?
361- securesystemslib .formats .BOOLEAN_SCHEMA .check_match (use_pynacl )
362-
363338 # Verify 'signature'. Before returning the Boolean result, ensure 'ed25519'
364- # was used as the signature scheme. Raise
365- # 'securesystemslib.exceptions.UnsupportedLibraryError' if 'use_pynacl' is
366- # True but 'nacl' is unavailable.
339+ # was used as the signature scheme.
367340 public = public_key
368341 valid_signature = False
369342
370343 if scheme in _SUPPORTED_ED25519_SIGNING_SCHEMES :
371- if use_pynacl :
344+ if NACL :
372345 try :
373346 nacl_verify_key = nacl .signing .VerifyKey (public )
374347 nacl_message = nacl_verify_key .verify (data , signature )
375348 valid_signature = True
376349
377- # The unit tests expect PyNaCl to be installed.
378- except NameError : # pragma: no cover
379- raise securesystemslib .exceptions .UnsupportedLibraryError ('The PyNaCl'
380- ' library and/or its dependencies unavailable.' )
381-
382350 except nacl .exceptions .BadSignatureError :
383351 pass
384352
0 commit comments