1%% -*- mode: erlang; tab-width: 4; indent-tabs-mode: 1; st-rulers: [70] -*- 2%% vim: ts=4 sw=4 ft=erlang noet 3-module(jose_jwk_kty_okp_x25519_props). 4 5-include("jose_public_key.hrl"). 6 7-include_lib("proper/include/proper.hrl"). 8 9% -compile(export_all). 10 11base64url_binary() -> 12 ?LET(Binary, 13 binary(), 14 jose_jwa_base64url:encode(Binary)). 15 16binary_map() -> 17 ?LET(List, 18 list({base64url_binary(), base64url_binary()}), 19 maps:from_list(List)). 20 21x25519_secret() -> 22 binary(32). 23 24x25519_keypair(Secret) -> 25 {PK, S} = jose_curve25519:x25519_keypair(Secret), 26 PublicKey = #'jose_X25519PublicKey'{publicKey=PK}, 27 SecretKey = #'jose_X25519PrivateKey'{publicKey=PublicKey, privateKey=S}, 28 {SecretKey, PublicKey}. 29 30jwk_map() -> 31 ?LET({AliceSecret, BobSecret}, 32 {x25519_secret(), x25519_secret()}, 33 begin 34 AliceKeys = {AlicePrivateKey, _} = x25519_keypair(AliceSecret), 35 BobKeys = x25519_keypair(BobSecret), 36 AlicePrivateJWK = jose_jwk:from_key(AlicePrivateKey), 37 {_, AlicePrivateJWKMap} = jose_jwk:to_map(AlicePrivateJWK), 38 Keys = {AliceKeys, BobKeys}, 39 {Keys, AlicePrivateJWKMap} 40 end). 41 42jwk_gen() -> 43 ?LET({Keys, AlicePrivateJWKMap}, 44 jwk_map(), 45 {Keys, jose_jwk:from_map(AlicePrivateJWKMap)}). 46 47prop_from_der_and_to_der() -> 48 ?FORALL({_Keys, AlicePrivateJWK, Password}, 49 ?LET({{Keys, AlicePrivateJWK}, Bytes}, 50 {jwk_gen(), binary()}, 51 {Keys, AlicePrivateJWK, jose_jwa_base64url:encode(Bytes)}), 52 begin 53 AlicePrivateDER = element(2, jose_jwk:to_der(AlicePrivateJWK)), 54 EncryptedAlicePrivateDER = element(2, jose_jwk:to_der(Password, AlicePrivateJWK)), 55 AlicePublicJWK = jose_jwk:to_public(AlicePrivateJWK), 56 AlicePublicDER = element(2, jose_jwk:to_der(AlicePublicJWK)), 57 AlicePrivateJWK =:= jose_jwk:from_der(AlicePrivateDER) 58 andalso AlicePrivateJWK =:= jose_jwk:from_der(Password, EncryptedAlicePrivateDER) 59 andalso AlicePublicJWK =:= jose_jwk:from_der(AlicePublicDER) 60 end). 61 62prop_from_map_and_to_map() -> 63 ?FORALL({{{AlicePrivateKey, AlicePublicKey}, _}, AlicePrivateJWKMap}, 64 ?LET({{Keys, JWKMap}, Extras}, 65 {jwk_map(), binary_map()}, 66 {Keys, maps:merge(Extras, JWKMap)}), 67 begin 68 AlicePrivateJWK = jose_jwk:from_map(AlicePrivateJWKMap), 69 AlicePublicJWK = jose_jwk:to_public(AlicePrivateJWK), 70 AlicePublicJWKMap = element(2, jose_jwk:to_map(AlicePublicJWK)), 71 AlicePublicThumbprint = jose_jwk:thumbprint(AlicePublicJWK), 72 AlicePrivateJWKMap =:= element(2, jose_jwk:to_map(AlicePrivateJWK)) 73 andalso AlicePrivateKey =:= element(2, jose_jwk:to_key(AlicePrivateJWK)) 74 andalso AlicePublicKey =:= element(2, jose_jwk:to_public_key(AlicePrivateJWK)) 75 andalso AlicePublicJWKMap =:= element(2, jose_jwk:to_public_map(AlicePrivateJWK)) 76 andalso AlicePublicThumbprint =:= jose_jwk:thumbprint(AlicePrivateJWK) 77 end). 78 79prop_from_pem_and_to_pem() -> 80 ?FORALL({_Keys, AlicePrivateJWK, Password}, 81 ?LET({{Keys, AlicePrivateJWK}, Bytes}, 82 {jwk_gen(), binary()}, 83 {Keys, AlicePrivateJWK, jose_jwa_base64url:encode(Bytes)}), 84 begin 85 AlicePrivatePEM = element(2, jose_jwk:to_pem(AlicePrivateJWK)), 86 EncryptedAlicePrivatePEM = element(2, jose_jwk:to_pem(Password, AlicePrivateJWK)), 87 AlicePublicJWK = jose_jwk:to_public(AlicePrivateJWK), 88 AlicePublicPEM = element(2, jose_jwk:to_pem(AlicePublicJWK)), 89 EncryptedAlicePublicPEM = element(2, jose_jwk:to_pem(Password, AlicePublicJWK)), 90 AlicePrivateJWK =:= jose_jwk:from_pem(AlicePrivatePEM) 91 andalso AlicePrivateJWK =:= jose_jwk:from_pem(Password, EncryptedAlicePrivatePEM) 92 andalso AlicePublicJWK =:= jose_jwk:from_pem(AlicePublicPEM) 93 andalso AlicePublicJWK =:= jose_jwk:from_pem(Password, EncryptedAlicePublicPEM) 94 end). 95 96prop_box_encrypt_and_box_decrypt() -> 97 ?FORALL({{{_, {BobPrivateKey, BobPublicKey}}, AlicePrivateJWK}, PlainText}, 98 {jwk_gen(), binary()}, 99 begin 100 BobPrivateJWK = jose_jwk:from_key(BobPrivateKey), 101 BobPublicJWK = jose_jwk:from_key(BobPublicKey), 102 Encrypted = jose_jwk:box_encrypt_ecdh_es(PlainText, BobPublicJWK, AlicePrivateJWK), 103 CompactEncrypted = jose_jwe:compact(Encrypted), 104 Decrypted = {_, JWE} = jose_jwk:box_decrypt_ecdh_es(Encrypted, BobPrivateJWK), 105 {PlainText, JWE} =:= Decrypted 106 andalso {PlainText, JWE} =:= jose_jwk:block_decrypt(CompactEncrypted, BobPrivateJWK) 107 end). 108