hi', 1758412800000 ) ),
hash( 'sha256', "BNS-SITE1\nexample.bch\nindex.html\n" . hash( 'sha256', '
hi
' ) . "\n1758412800000" ),
'the upload digest matches the gateway formula'
);
$headers = SP_Message::site_headers( 'example.bch', 'index.html', 'hi
', $key['private'], 1758412800000 );
T::is( $headers['x-bns-ts'], '1758412800000', 'the timestamp header is the one signed' );
T::is( strlen( base64_decode( $headers['x-bns-sig'], true ) ), 65, 'the signature header decodes to 65 bytes' );
// The gateway recovers the signer and compares it to the on-chain owner.
// Reproduce that here so a change to either side is caught.
T::is(
SP_CashAddr::from_public_key(
SP_Secp256k1::recover(
base64_decode( $headers['x-bns-sig'], true ),
SP_Message::site_digest( 'example.bch', 'index.html', 'hi
', 1758412800000 )
),
'bchtest'
),
$key['address'],
'the gateway would recover the publishing address from the header'
);
// Changing any signed component must invalidate it.
T::ok(
SP_CashAddr::from_public_key(
SP_Secp256k1::recover(
base64_decode( $headers['x-bns-sig'], true ),
SP_Message::site_digest( 'example.bch', 'index.html', 'TAMPERED
', 1758412800000 )
),
'bchtest'
) !== $key['address'],
'altered upload bytes no longer recover the publishing address'
);
T::group( 'canonical JSON' );
T::is(
SP_Message::canonical_json( array( 'b' => 1, 'a' => 2 ) ),
'{"a":2,"b":1}',
'keys are sorted'
);
T::is(
SP_Message::canonical_json( array( 'a' => null, 'b' => 1 ) ),
'{"b":1}',
'null members are dropped'
);
T::is(
SP_Message::canonical_json( array( 'z' => array( 'y' => 1, 'x' => 2 ) ) ),
'{"z":{"x":2,"y":1}}',
'nested keys are sorted too'
);
T::is(
SP_Message::canonical_json( array( 'url' => 'https://a/b' ) ),
'{"url":"https://a/b"}',
'slashes are not escaped, matching JSON.stringify'
);
// Written as a concatenation so the expected value cannot itself be stored as
// a literal e-acute, which would make this assertion test nothing.
T::is(
SP_Message::canonical_json( array( 'note' => 'caf' . chr( 0xc3 ) . chr( 0xa9 ) ) ),
'{"note":"caf' . chr( 92 ) . 'u00e9"}',
'non-ASCII is backslash-u escaped'
);
T::is(
SP_Message::canonical_json( array( 'list' => array( 3, 1, 2 ) ) ),
'{"list":[3,1,2]}',
'array order is preserved'
);
exit( T::summary() );