2
2
from jose .constants import ALGORITHMS
3
3
from jose .exceptions import JOSEError , JWKError
4
4
5
- from jose .backends .ecdsa_backend import ECDSAECKey
6
- from jose .backends .cryptography_backend import CryptographyECKey
5
+ from jose .backends import ECKey
6
+ try :
7
+ from jose .backends .ecdsa_backend import ECDSAECKey
8
+ import ecdsa
9
+ except ImportError :
10
+ ECDSAECKey = ecdsa = None
11
+
12
+ try :
13
+ from jose .backends .cryptography_backend import CryptographyECKey
14
+ except ImportError :
15
+ CryptographyECKey = None
7
16
8
- import ecdsa
9
17
import pytest
10
18
11
19
private_key = """-----BEGIN EC PRIVATE KEY-----
14
22
WkG0HJWIORlPbvXME+DRh6G/yVOKnTm88Q==
15
23
-----END EC PRIVATE KEY-----"""
16
24
25
+ # Private key generated using NIST256p curve
26
+ TOO_SHORT_PRIVATE_KEY = b"""\
27
+ -----BEGIN EC PRIVATE KEY-----
28
+ MHcCAQEEIMlUyYGOpjV4bbW0C9FKS2zkspD0L/5vJLnr6sJoLdc+oAoGCCqGSM49
29
+ AwEHoUQDQgAE6TDUNj5QXl+RKdZvBV+cg7Td6cJRB+Ta8XAhIuCAzonq0Ix//1+C
30
+ pNSsy11sIKmMl61YJzxvZ6WkNluBmkDPCQ==
31
+ -----END EC PRIVATE KEY-----
32
+ """
33
+
34
+
35
+ def _backend_exception_types ():
36
+ """Build the backend exception types based on available backends."""
37
+ if None not in (ECDSAECKey , ecdsa ):
38
+ yield ECDSAECKey , ecdsa .BadDigestError
39
+
40
+ if CryptographyECKey is not None :
41
+ yield CryptographyECKey , TypeError
17
42
18
- class TestECAlgorithm :
19
43
20
- @pytest .mark .parametrize ("Backend" , [ECDSAECKey , CryptographyECKey ])
21
- def test_key_from_pem (self , Backend ):
22
- assert not Backend (private_key , ALGORITHMS .ES256 ).is_public ()
44
+ @pytest .mark .ecdsa
45
+ @pytest .mark .skipif (
46
+ None in (ECDSAECKey , ecdsa ),
47
+ reason = "python-ecdsa backend not available"
48
+ )
49
+ def test_key_from_ecdsa ():
50
+ key = ecdsa .SigningKey .from_pem (private_key )
51
+ assert not ECKey (key , ALGORITHMS .ES256 ).is_public ()
52
+
53
+
54
+ class TestECAlgorithm :
23
55
24
- @pytest .mark .parametrize ("Backend" , [ECDSAECKey , CryptographyECKey ])
25
- def test_key_from_ecdsa (self , Backend ):
26
- key = ecdsa .SigningKey .from_pem (private_key )
27
- assert not Backend (key , ALGORITHMS .ES256 ).is_public ()
56
+ def test_key_from_pem (self ):
57
+ assert not ECKey (private_key , ALGORITHMS .ES256 ).is_public ()
28
58
29
- @pytest .mark .parametrize ("Backend" , [ECDSAECKey , CryptographyECKey ])
30
- def test_to_pem (self , Backend ):
31
- key = Backend (private_key , ALGORITHMS .ES256 )
59
+ def test_to_pem (self ):
60
+ key = ECKey (private_key , ALGORITHMS .ES256 )
32
61
assert not key .is_public ()
33
62
assert key .to_pem ().strip () == private_key .strip ().encode ('utf-8' )
34
63
35
64
public_pem = key .public_key ().to_pem ()
36
- assert Backend (public_pem , ALGORITHMS .ES256 ).is_public ()
37
-
38
- @pytest .mark .parametrize (
39
- "Backend,ExceptionType" ,
40
- [
41
- (ECDSAECKey , ecdsa .BadDigestError ),
42
- (CryptographyECKey , TypeError )
43
- ]
44
- )
65
+ assert ECKey (public_pem , ALGORITHMS .ES256 ).is_public ()
66
+
67
+ @pytest .mark .parametrize ("Backend,ExceptionType" , _backend_exception_types ())
45
68
def test_key_too_short (self , Backend , ExceptionType ):
46
- priv_key = ecdsa .SigningKey .generate (curve = ecdsa .NIST256p ).to_pem ()
47
- key = Backend (priv_key , ALGORITHMS .ES512 )
69
+ key = Backend (TOO_SHORT_PRIVATE_KEY , ALGORITHMS .ES512 )
48
70
with pytest .raises (ExceptionType ):
49
71
key .sign (b'foo' )
50
72
51
- @pytest .mark .parametrize ("Backend" , [ECDSAECKey , CryptographyECKey ])
52
- def test_get_public_key (self , Backend ):
53
- key = Backend (private_key , ALGORITHMS .ES256 )
73
+ def test_get_public_key (self ):
74
+ key = ECKey (private_key , ALGORITHMS .ES256 )
54
75
pubkey = key .public_key ()
55
76
pubkey2 = pubkey .public_key ()
56
77
assert pubkey == pubkey2
57
78
58
- @pytest .mark .parametrize ("Backend" , [ECDSAECKey , CryptographyECKey ])
59
- def test_string_secret (self , Backend ):
79
+ def test_string_secret (self ):
60
80
key = 'secret'
61
81
with pytest .raises (JOSEError ):
62
- Backend (key , ALGORITHMS .ES256 )
82
+ ECKey (key , ALGORITHMS .ES256 )
63
83
64
- @pytest .mark .parametrize ("Backend" , [ECDSAECKey , CryptographyECKey ])
65
- def test_object (self , Backend ):
84
+ def test_object (self ):
66
85
key = object ()
67
86
with pytest .raises (JOSEError ):
68
- Backend (key , ALGORITHMS .ES256 )
87
+ ECKey (key , ALGORITHMS .ES256 )
69
88
70
- @pytest .mark .parametrize ("Backend" , [ECDSAECKey , CryptographyECKey ])
71
- def test_invalid_algorithm (self , Backend ):
89
+ def test_invalid_algorithm (self ):
72
90
with pytest .raises (JWKError ):
73
- Backend (private_key , 'nonexistent' )
91
+ ECKey (private_key , 'nonexistent' )
74
92
75
93
with pytest .raises (JWKError ):
76
- Backend ({'kty' : 'bla' }, ALGORITHMS .ES256 )
94
+ ECKey ({'kty' : 'bla' }, ALGORITHMS .ES256 )
77
95
78
- @pytest .mark .parametrize ("Backend" , [ECDSAECKey , CryptographyECKey ])
79
- def test_EC_jwk (self , Backend ):
96
+ def test_EC_jwk (self ):
80
97
key = {
81
98
"kty" : "EC" ,
82
99
@@ -87,22 +104,21 @@ def test_EC_jwk(self, Backend):
87
104
"d" : "AAhRON2r9cqXX1hg-RoI6R1tX5p2rUAYdmpHZoC1XNM56KtscrX6zbKipQrCW9CGZH3T4ubpnoTKLDYJ_fF3_rJt" ,
88
105
}
89
106
90
- assert not Backend (key , ALGORITHMS .ES512 ).is_public ()
107
+ assert not ECKey (key , ALGORITHMS .ES512 ).is_public ()
91
108
92
109
del key ['d' ]
93
110
94
111
# We are now dealing with a public key.
95
- assert Backend (key , ALGORITHMS .ES512 ).is_public ()
112
+ assert ECKey (key , ALGORITHMS .ES512 ).is_public ()
96
113
97
114
del key ['x' ]
98
115
99
116
# This key is missing a required parameter.
100
117
with pytest .raises (JWKError ):
101
- Backend (key , ALGORITHMS .ES512 )
118
+ ECKey (key , ALGORITHMS .ES512 )
102
119
103
- @pytest .mark .parametrize ("Backend" , [ECDSAECKey ])
104
- def test_verify (self , Backend ):
105
- key = Backend (private_key , ALGORITHMS .ES256 )
120
+ def test_verify (self ):
121
+ key = ECKey (private_key , ALGORITHMS .ES256 )
106
122
msg = b'test'
107
123
signature = key .sign (msg )
108
124
public_key = key .public_key ()
@@ -129,23 +145,7 @@ def assert_parameters(self, as_dict, private):
129
145
# Private parameters should be absent
130
146
assert 'd' not in as_dict
131
147
132
- @pytest .mark .parametrize ("Backend" , [ECDSAECKey , CryptographyECKey ])
133
- def test_to_dict (self , Backend ):
134
- key = Backend (private_key , ALGORITHMS .ES256 )
148
+ def test_to_dict (self ):
149
+ key = ECKey (private_key , ALGORITHMS .ES256 )
135
150
self .assert_parameters (key .to_dict (), private = True )
136
151
self .assert_parameters (key .public_key ().to_dict (), private = False )
137
-
138
- @pytest .mark .parametrize ("BackendSign" , [ECDSAECKey , CryptographyECKey ])
139
- @pytest .mark .parametrize ("BackendVerify" , [ECDSAECKey , CryptographyECKey ])
140
- def test_signing_parity (self , BackendSign , BackendVerify ):
141
- key_sign = BackendSign (private_key , ALGORITHMS .ES256 )
142
- key_verify = BackendVerify (private_key , ALGORITHMS .ES256 ).public_key ()
143
-
144
- msg = b'test'
145
- sig = key_sign .sign (msg )
146
-
147
- # valid signature
148
- assert key_verify .verify (msg , sig )
149
-
150
- # invalid signature
151
- assert not key_verify .verify (msg , b'n' * 64 )
0 commit comments