2022-11-12 22:10:15 +00:00
import pytest
from django . test . client import RequestFactory
from pytest_httpx import HTTPXMock
from core . signatures import HttpSignature , LDSignature , VerificationError
2022-11-22 03:10:01 +00:00
def test_sign_ld ( keypair ) :
2022-11-12 22:10:15 +00:00
"""
Tests signing JSON - LD documents by round - tripping them through the
verifier .
"""
# Create the signature
document = {
2023-10-26 16:01:03 +00:00
" @context " : [ " https://www.w3.org/ns/activitystreams " ] ,
2022-11-12 22:10:15 +00:00
" id " : " https://example.com/test-create " ,
" type " : " Create " ,
" actor " : " https://example.com/test-actor " ,
" object " : {
" id " : " https://example.com/test-object " ,
" type " : " Note " ,
} ,
}
signature_section = LDSignature . create_signature (
document ,
2022-11-22 03:10:01 +00:00
keypair [ " private_key " ] ,
keypair [ " public_key_id " ] ,
2022-11-12 22:10:15 +00:00
)
# Check it and assign it to the document
assert " signatureValue " in signature_section
assert signature_section [ " type " ] == " RsaSignature2017 "
document [ " signature " ] = signature_section
# Now verify it ourselves
2022-11-22 03:10:01 +00:00
LDSignature . verify_signature ( document , keypair [ " public_key " ] )
2022-11-12 22:10:15 +00:00
2022-11-22 03:10:01 +00:00
def test_verifying_ld ( keypair ) :
2022-11-12 22:10:15 +00:00
"""
Tests verifying JSON - LD signatures from a known - good document
"""
document = {
2023-10-26 16:01:03 +00:00
" @context " : [ " https://www.w3.org/ns/activitystreams " ] ,
2022-11-12 22:10:15 +00:00
" id " : " https://example.com/test-create " ,
" type " : " Create " ,
" actor " : " https://example.com/test-actor " ,
" object " : { " id " : " https://example.com/test-object " , " type " : " Note " } ,
" signature " : {
" @context " : " https://w3id.org/identity/v1 " ,
" creator " : " https://example.com/test-actor#test-key " ,
2023-10-26 16:01:03 +00:00
" created " : " 2023-10-25T08:08:47.702Z " ,
" signatureValue " : " ajg4ukZzCtBWjflO1u6MlTc4tBVO6MsqzBr/L+kO5VI2ucutFaUdDa/Kx4W12ZCm9oYvTyMQMnoeELx5BifslRWEeMmo1wWMPXmg2/BMKgm8Spt+Zanq68uTlYGyKvuw1Q0FyNq84N2PbRZRXu2Yhlj2KnAVTRtKrsfEiCg3yNfVQ7lbUpDtlXvXLAq2yBN8H/BnZDoynjaDlafFW9Noq8025q1K/lz5jNzBEL22CSrKsD2qYWq1TK3s3h6SJ+j3J+5s0Ni3F/TH7W/5VeGBpzx4z6MSjmn7aHAS3JNCnAWDW9Rf6yKLg2y5htj6FpexiGcoEjO3VqjLoIP4f/115Q== " ,
2022-11-12 22:10:15 +00:00
" type " : " RsaSignature2017 " ,
} ,
}
# Ensure it verifies with correct data
2022-11-22 03:10:01 +00:00
LDSignature . verify_signature ( document , keypair [ " public_key " ] )
2023-10-26 16:01:03 +00:00
# signature should remain in document if it was valid
assert " signature " in document
2022-11-12 22:10:15 +00:00
# Mutate it slightly and ensure it does not verify
with pytest . raises ( VerificationError ) :
document [ " actor " ] = " https://example.com/evil-actor "
2022-11-22 03:10:01 +00:00
LDSignature . verify_signature ( document , keypair [ " public_key " ] )
2022-11-12 22:10:15 +00:00
2022-11-22 03:10:01 +00:00
def test_sign_http ( httpx_mock : HTTPXMock , keypair ) :
2022-11-12 22:10:15 +00:00
"""
Tests signing HTTP requests by round - tripping them through our verifier
"""
# Create document
document = {
" id " : " https://example.com/test-create " ,
" type " : " Create " ,
" actor " : " https://example.com/test-actor " ,
" object " : {
" id " : " https://example.com/test-object " ,
" type " : " Note " ,
} ,
}
# Send the signed request to the mock library
httpx_mock . add_response ( )
2023-07-17 06:37:47 +00:00
HttpSignature . signed_request (
2022-11-12 22:10:15 +00:00
uri = " https://example.com/test-actor " ,
body = document ,
2022-11-22 03:10:01 +00:00
private_key = keypair [ " private_key " ] ,
key_id = keypair [ " public_key_id " ] ,
2022-11-12 22:10:15 +00:00
)
# Retrieve it and construct a fake request object
outbound_request = httpx_mock . get_request ( )
fake_request = RequestFactory ( ) . post (
path = " /test-actor " ,
data = outbound_request . content ,
content_type = outbound_request . headers [ " content-type " ] ,
HTTP_HOST = " example.com " ,
HTTP_DATE = outbound_request . headers [ " date " ] ,
HTTP_SIGNATURE = outbound_request . headers [ " signature " ] ,
HTTP_DIGEST = outbound_request . headers [ " digest " ] ,
)
# Verify that
2022-11-22 03:10:01 +00:00
HttpSignature . verify_request ( fake_request , keypair [ " public_key " ] )
2022-11-12 22:10:15 +00:00
2022-11-22 03:10:01 +00:00
def test_verify_http ( keypair ) :
2022-11-12 22:10:15 +00:00
"""
Tests verifying HTTP requests against a known good example
"""
# Make our predictable request
fake_request = RequestFactory ( ) . post (
path = " /test-actor " ,
data = b ' { " id " : " https://example.com/test-create " , " type " : " Create " , " actor " : " https://example.com/test-actor " , " object " : { " id " : " https://example.com/test-object " , " type " : " Note " }} ' ,
content_type = " application/json " ,
HTTP_HOST = " example.com " ,
HTTP_DATE = " Sat, 12 Nov 2022 21:57:18 GMT " ,
HTTP_SIGNATURE = ' keyId= " https://example.com/test-actor#test-key " ,headers= " (request-target) host date digest content-type " ,signature= " IRduYoDJIh90mprjUgOIdxY1iaBWHs5ou9vsDlcmSekg6DXMZTiXjmZxbNIrnpEbNFu3wTcqz1nv9H97Gp7orbYMuHm6j2ecxsvzSr37T9jxBbt3Ov3xSfuYWwhv6PuTWNxHtUQWNuAIc3wHDAQt8Flnak/uHe7swoAq4uHq2kt18iMW6CEV9XA5ESFho2HSUgRaifoNxJlIWbHYPJiP0t9aktgGBkpQoZ8ulOj3Ew4RwC1lwk9kzWiLIjU4tSAie8RbIy2g0aUvA1tQh9Uge1by3o7+349SL5iooj+B6WSCEvvjEl52wo3xoEQmv0ptYuSPLUgB9tP8q7DoHEc8Dw== " ,algorithm= " rsa-sha256 " ' ,
HTTP_DIGEST = " SHA-256=07sIbQ3GlOHWMbFMNajtPNtmUQXXu20UuvrIYLlI3kc= " ,
)
# Verify that
2022-11-22 03:10:01 +00:00
HttpSignature . verify_request ( fake_request , keypair [ " public_key " ] , skip_date = True )
2023-07-20 15:55:06 +00:00
def test_verify_http_bad_signature ( keypair ) :
"""
Tests that a signature missing the algorithm does not work
"""
# Make our predictable request
fake_request = RequestFactory ( ) . post (
path = " /test-actor " ,
data = b ' { " id " : " https://example.com/test-create " , " type " : " Create " , " actor " : " https://example.com/test-actor " , " object " : { " id " : " https://example.com/test-object " , " type " : " Note " }} ' ,
content_type = " application/json " ,
HTTP_HOST = " example.com " ,
HTTP_DATE = " Sat, 12 Nov 2022 21:57:18 GMT " ,
HTTP_SIGNATURE = ' keyId= " https://example.com/test-actor#test-key " ,headers= " (request-target) host date digest content-type " ,signature= " IRduYoDJIh90mprjUgOIdxY1iaBWHs5ou9vsDlcmSekg6DXMZTiXjmZxbNIrnpEbNFu3wTcqz1nv9H97Gp7orbYMuHm6j2ecxsvzSr37T9jxBbt3Ov3xSfuYWwhv6PuTWNxHtUQWNuAIc3wHDAQt8Flnak/uHe7swoAq4uHq2kt18iMW6CEV9XA5ESFho2HSUgRaifoNxJlIWbHYPJiP0t9aktgGBkpQoZ8ulOj3Ew4RwC1lwk9kzWiLIjU4tSAie8RbIy2g0aUvA1tQh9Uge1by3o7+349SL5iooj+B6WSCEvvjEl52wo3xoEQmv0ptYuSPLUgB9tP8q7DoHEc8Dw== " ' ,
HTTP_DIGEST = " SHA-256=07sIbQ3GlOHWMbFMNajtPNtmUQXXu20UuvrIYLlI3kc= " ,
)
# Verify that
with pytest . raises ( VerificationError ) :
HttpSignature . verify_request (
fake_request , keypair [ " public_key " ] , skip_date = True
)