Skip to content

Commit 57df28a

Browse files
author
Athan Massouras
committed
fix: add test for advanced sign/verify for bitstring status list
Signed-off-by: Athan Massouras <[email protected]>
1 parent 051295d commit 57df28a

File tree

3 files changed

+93
-16
lines changed

3 files changed

+93
-16
lines changed

src/bitstring_status_list/verifier.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,11 @@ def verify_jwt(
9696
# Enveloping proof
9797

9898
# Check that message is in valid JWT format
99-
headers_bytes, payload_bytes, signature = sl_response.split(b".")
99+
headers_bytes, payload_bytes, signature = sl_response.split(b".", maxsplit=3)
100100
assert headers_bytes and payload_bytes and signature
101101

102102
# Verify signature. verifier must be of type EnvelopingTokenVerifier
103-
if not verifier(headers_bytes + b"." + payload_bytes, b64url_decode(signature)):
103+
if not verifier(headers_bytes + b"." + payload_bytes, signature):
104104
raise StatusVerificationError("Invalid signature on payload.")
105105

106106
# Extract data

tests/test_bitstring_status_list.py

Lines changed: 91 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import pytest
2-
from time import time
32

43
from google.auth.crypt.es256 import ES256Signer, ES256Verifier
54
from cryptography.hazmat.primitives.asymmetric import ec
6-
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
75

8-
from bit_array import BitArray
9-
from bitstring_status_list.issuer import BitstringStatusListIssuer, MIN_LIST_LENGTH
10-
from bitstring_status_list.verifier import BitstringStatusListVerifier
6+
from bit_array import b64url_encode, b64url_decode
7+
from bitstring_status_list.issuer import BitstringStatusListIssuer, EmbeddingTokenSigner, EnvelopingTokenSigner, MIN_LIST_LENGTH
8+
from bitstring_status_list.verifier import BitstringStatusListVerifier, EmbeddingTokenVerifier, EnvelopingTokenVerifier
119

1210
@pytest.fixture
1311
def status():
@@ -31,6 +29,38 @@ def trivial_embedding_verifier(payload: bytes, signature: dict) -> bool:
3129
""" Trivial verifier: always says that the signature is valid. """
3230
return True
3331

32+
33+
# More advanced verification
34+
ES256_KEY = ec.generate_private_key(ec.SECT233K1())
35+
36+
@pytest.fixture
37+
def es256_enveloping_signer():
38+
signer = ES256Signer(ES256_KEY)
39+
def sign(payload: bytes) -> bytes:
40+
return signer.sign(payload)
41+
yield sign
42+
43+
@pytest.fixture
44+
def es256_enveloping_verifier():
45+
verifier = ES256Verifier(ES256_KEY.public_key())
46+
def verify(payload: bytes, signature: bytes) -> bool:
47+
return verifier.verify(payload, signature)
48+
yield verify
49+
50+
@pytest.fixture
51+
def es256_embedding_signer():
52+
signer = ES256Signer(ES256_KEY)
53+
def sign(payload: bytes) -> dict:
54+
return {"proofValue": b64url_encode(signer.sign(payload)).decode()}
55+
yield sign
56+
57+
@pytest.fixture
58+
def es256_embedding_verifier():
59+
verifier = ES256Verifier(ES256_KEY.public_key())
60+
def verify(payload: bytes, signature: dict) -> bool:
61+
return verifier.verify(payload, b64url_decode(signature["proofValue"].encode()))
62+
yield verify
63+
3464
def test_verify_jwt_basic_enveloping(status: BitstringStatusListIssuer):
3565
encoded_jwt = status.sign_jwt_enveloping(
3666
signer=trivial_enveloping_signer,
@@ -157,3 +187,59 @@ def test_status_message():
157187
"valid": not bool(bitstring[i]),
158188
"message": str(bitstring[i]),
159189
}
190+
191+
def test_verify_es256_enveloping(
192+
status: BitstringStatusListIssuer,
193+
es256_enveloping_signer: EnvelopingTokenSigner,
194+
es256_enveloping_verifier: EnvelopingTokenVerifier,
195+
):
196+
encoded_jwt = status.sign_jwt_enveloping(
197+
signer=es256_enveloping_signer,
198+
alg="ES256",
199+
kid="12",
200+
status_purpose="revocation",
201+
)
202+
203+
credential_status = {
204+
"id": "https://example.com/credentials/status/3#94567",
205+
"type": "BitstringStatusListEntry",
206+
"statusPurpose": "revocation",
207+
"statusListIndex": "0",
208+
"statusListCredential": "https://example.com/credentials/status/3"
209+
}
210+
211+
verifier = BitstringStatusListVerifier(credential_status)
212+
verifier.verify_jwt(encoded_jwt, verifier=es256_enveloping_verifier)
213+
214+
for i in range(status.status_list.size):
215+
assert verifier.get_status(i) == {
216+
"status": status[i],
217+
"valid": not bool(status[i])
218+
}
219+
220+
def test_verify_es256_embedding(
221+
status: BitstringStatusListIssuer,
222+
es256_embedding_signer: EmbeddingTokenSigner,
223+
es256_embedding_verifier: EmbeddingTokenVerifier,
224+
):
225+
encoded_jwt = status.sign_jwt_embedding(
226+
signer=es256_embedding_signer,
227+
status_purpose="revocation",
228+
)
229+
230+
credential_status = {
231+
"id": "https://example.com/credentials/status/3#94567",
232+
"type": "BitstringStatusListEntry",
233+
"statusPurpose": "revocation",
234+
"statusListIndex": "0",
235+
"statusListCredential": "https://example.com/credentials/status/3"
236+
}
237+
238+
verifier = BitstringStatusListVerifier(credential_status)
239+
verifier.verify_jwt(encoded_jwt, verifier=es256_embedding_verifier)
240+
241+
for i in range(status.status_list.size):
242+
assert verifier.get_status(i) == {
243+
"status": status[i],
244+
"valid": not bool(status[i])
245+
}

tests/test_token_status_list_verifier.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
from google.auth.crypt.es256 import ES256Signer, ES256Verifier
77
from cryptography.hazmat.primitives.asymmetric import ec
8-
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
98

109
from bit_array import BitArray
1110
from token_status_list.issuer import TokenStatusListIssuer, ALG, KID, TYP, ISS, SUB, AUD, EXP, NBF, IAT, CTI, STATUS_LIST, TTL, KNOWN_ALGS_TO_CWT_ALG
@@ -38,14 +37,6 @@ def sign(payload: bytes) -> bytes:
3837
@pytest.fixture
3938
def es256_verifier():
4039
verifier = ES256Verifier(ES256_KEY.public_key())
41-
42-
p_key = ES256_KEY.public_key()
43-
public_key_b = p_key.public_bytes(Encoding.X962, PublicFormat.UncompressedPoint)
44-
print(public_key_b)
45-
46-
public_key_ds = ec.EllipticCurvePublicKey.from_encoded_point(ec.SECT233K1(), public_key_b)
47-
print(p_key == public_key_ds)
48-
4940
def verify(payload: bytes, signature: bytes) -> bool:
5041
return verifier.verify(payload, signature)
5142
yield verify

0 commit comments

Comments
 (0)