Index
WebAuthn.WebAuthnWebAuthn.EC2PublicKeyWebAuthn.OKPPublicKeyWebAuthn.RSAPublicKeyWebAuthn.WebAuthnPublicKeyWebAuthn.assetWebAuthn.asset_pathWebAuthn.authentication_optionsWebAuthn.base64urldecodeWebAuthn.base64urlencodeWebAuthn.cose_key_parseWebAuthn.cose_key_to_pemWebAuthn.der_to_pemWebAuthn.enforce_signcountWebAuthn.enforce_up_uvWebAuthn.extract_credential_public_keyWebAuthn.extract_pubkey_pem_from_derWebAuthn.generate_challengeWebAuthn.parse_assertionWebAuthn.parse_attestation_objectWebAuthn.parse_clientdata_jsonWebAuthn.parse_credential_public_keyWebAuthn.parse_ec_pem_xyWebAuthn.parse_ed25519_pem_xWebAuthn.parse_rsa_pem_neWebAuthn.pem_to_derWebAuthn.registration_optionsWebAuthn.verify_attestation_objectWebAuthn.verify_attestation_packedWebAuthn.verify_challengeWebAuthn.verify_originWebAuthn.verify_p256_signature_raw_xyWebAuthn.verify_rsa_signature_raw_neWebAuthn.verify_webauthn_signature
API
WebAuthn.WebAuthn — Modulemodule WebAuthnA Julia package for WebAuthn/FIDO2 credential registration and authentication in web applications.
Supports all required cryptographic formats: CBOR/COSE, Ed25519 (OKP), ECDSA (P-256), RSA public keys, base64url, and PEM export. Utility functions simplify browser-challenge generation, and parsing and verification of registration and authentication responses.
WebAuthn.EC2PublicKey — Typestruct EC2PublicKeyRepresent a COSE kty=2 EC2 public key (P-256/ES256).
Fields:
- x::Vector{UInt8} # x coordinate
- y::Vector{UInt8} # y coordinate
- alg::Int # COSE alg, usually -7
- crv::Int # COSE curve, usually 1 (P-256)
See also: RSAPublicKey and OKPPublicKey.
WebAuthn.OKPPublicKey — Typestruct OKPPublicKeyRepresent a COSE kty=1 OKP public key (Ed25519).
Fields:
- x::Vector{UInt8} # public key bytes
- alg::Int # COSE alg, usually -8
- crv::Int # COSE curve ID, usually 6
See also: EC2PublicKey and RSAPublicKey.
WebAuthn.RSAPublicKey — Typestruct RSAPublicKeyRepresent a COSE kty=3 RSA public key.
Fields:
- n::Vector{UInt8} # modulus
- e::Vector{UInt8} # exponent
- alg::Int # COSE alg, usually -257
See also: EC2PublicKey and OKPPublicKey.
WebAuthn.WebAuthnPublicKey — Typeabstract type WebAuthnPublicKeyAbstract supertype for all WebAuthn public key structs.
WebAuthn.asset — Methodasset(name::AbstractString)::StringRead and return the contents of an asset script (e.g. JS file) shipped with WebAuthn.jl. Example: WebAuthn.asset("webauthn_register.js")
WebAuthn.asset_path — Methodasset_path(name::AbstractString)::StringGet absolute path to an asset shipped with WebAuthn.jl.
WebAuthn.authentication_options — Methodauthentication_options(rpid; allow_credential_ids=[],
challenge=nothing, timeout=60000, kwargs...)::DictBuild a browser authentication options dictionary for navigator.credentials.get.
Keywords
allow_credential_ids: List of credential IDs (strings) that are allowed (default: empty).challenge: Challenge string to use (default: random).timeout: Timeout in milliseconds (default: 60000).kwargs: Any additional field for WebAuthn/PublicKeyCredentialRequestOptions; future extensions or browser-specific options can be passed directly as keywords.
Examples
julia> using WebAuthn
julia> opts = authentication_options("example.com";
allow_credential_ids=["id1", "id2"], userVerification="required",
extensions=Dict("appid"=>true));
julia> opts["rpId"]
"example.com"
julia> opts["allowCredentials"][1]["id"]
"id1"
julia> opts["userVerification"]
"required"
julia> opts["extensions"]["appid"]
trueSee also: registration_options.
WebAuthn.base64urldecode — Methodbase64urldecode(s::AbstractString)::Vector{UInt8}Decode a base64url string (URL-safe, no padding) to a byte vector.
Restores standard base64 alphabet and adds padding if necessary before decoding.
Examples
julia> using WebAuthn
julia> base64urldecode("AQID")
3-element Vector{UInt8}:
0x01
0x02
0x03See also: base64urlencode.
WebAuthn.base64urlencode — Methodbase64urlencode(bytes::Vector{UInt8})::StringEncode a byte vector to a base64url string without padding.
Replaces + with - and / with _ for URL safety, then removes padding characters.
Examples
julia> using WebAuthn
julia> base64urlencode(UInt8[1, 2, 3])
"AQID"See also: base64urldecode.
WebAuthn.cose_key_parse — Methodcose_key_parse(cose::Dict)::WebAuthnPublicKeyParse a COSE_Key dictionary to the appropriate public key struct.
Examples
julia> using WebAuthn
julia> cose = Dict(1=>2, 3=>-7, -1=>1, -2=>rand(UInt8,32), -3=>rand(UInt8,32));
julia> key = cose_key_parse(cose);See also: EC2PublicKey, RSAPublicKey and OKPPublicKey.
WebAuthn.cose_key_to_pem — Methodcose_key_to_pem(key::WebAuthnPublicKey)::StringConvert a WebAuthn public key struct to PEM SubjectPublicKeyInfo string.
Creates a standard PEM format public key from a parsed WebAuthn/COSE public key (e.g., EC2PublicKey, RSAPublicKey, or OKPPublicKey) for use with external cryptographic libraries.
Examples
julia> using WebAuthn
julia> key = EC2PublicKey(rand(UInt8,32), rand(UInt8,32), -7, 1);
julia> pem = cose_key_to_pem(key);See also: cose_key_parse.
WebAuthn.der_to_pem — Functionder_to_pem(derbytes::Vector{UInt8}, label::String = "CERTIFICATE")::StringConvert DER-encoded bytes to a PEM string with the specified label.
Formats binary DER data as a PEM-encoded string, splitting base64 lines to 64 characters and adding header and footer lines for the given type.
Examples
julia> using WebAuthn
julia> pem = WebAuthn.der_to_pem(rand(UInt8, 90), "PUBLIC KEY");See also: cose_key_to_pem.
WebAuthn.enforce_signcount — Methodenforce_signcount(old::Integer, new::Integer)Reject cloned/replayed credentials per WebAuthn spec.
Examples
julia> enforce_signcount(0, 20) # Initial use, old is 0: always OK
true
julia> enforce_signcount(10, 11) # Normal monotonic increase
true
julia> enforce_signcount(5, 5) # No increase (should fail)
ERROR: ArgumentError:
[...]
julia> enforce_signcount(10, 3) # Replay/clone (should fail)
ERROR: ArgumentError:
[...]WebAuthn.enforce_up_uv — Methodenforce_up_uv(authData::Vector{UInt8}; require_uv=false)Check user presence (UP) and user verification (UV) flags in authenticatorData.
Examples
```jldoctest julia> # UP (bit 0) set, UV (bit 2) not set
julia> enforceupuv([zeros(UInt8,33); 0x01]) true
julia> # UP and UV set
julia> enforceupuv([zeros(UInt8,33); 0x05]) true
julia> # UP not set
julia> enforceupuv([zeros(UInt8,33); 0x00]) ERROR: [...]
julia> # UP set, require UV (but UV not set)
julia> enforceupuv([zeros(UInt8,33); 0x01]; require_uv=true) ERROR: [...]
julia> # UP and UV set, require UV (pass)
julia> enforceupuv([zeros(UInt8,33); 0x05]; require_uv=true) true
WebAuthn.extract_credential_public_key — Methodextract_credential_public_key(authData::Vector{UInt8})::Vector{UInt8}Extract the credential public key bytes from authenticator data.
Returns the raw CBOR-encoded public key (COSE_Key) after parsing authData as specified by the WebAuthn/FIDO2 standard.
Examples
julia> using WebAuthn
julia> fake_pk = UInt8[0xa5, 0x01, 0x02, 0x03, 0x38, 0x20, 0x01, 0x33, 0x58,
0x20];
julia> authData = vcat(zeros(UInt8, 37+16),
0x00, 0x10, rand(UInt8, 16), fake_pk);
julia> pkbytes = extract_credential_public_key(authData);See also: parse_credential_public_key
WebAuthn.extract_pubkey_pem_from_der — Methodextract_pubkey_pem_from_der(der::Vector{UInt8})::StringExtract a PEM-encoded EC public key from a DER-encoded X.509 certificate.
Searches the provided DER bytes for a known EC OID and extracts the embedded public key, returning it as a PEM-encoded SubjectPublicKeyInfo suitable for cryptographic libraries.
OpenSSL's ASN.1/X.509 parsing APIs do not validate the integrity or structure of the input data prior to parsing. Calling them directly on arbitrary or malformed input can cause process crashes, memory corruption, or security issues. Only use these functions on properly validated certificate data, and never on arbitrary or possibly-truncated buffers. Always fallback gracefully on parse failure, and avoid forwarding unverified input to OpenSSL from adversarial sources.
Examples
julia> using WebAuthn
julia> der = [
0x30,0x59,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,
0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,0x03,0x42,0x00,
0x04,0xac,0x21,0x45,0xb3,0x77,0x1d,0xdd,0xab,0xbd,0x1c,0x34,0x5e,
0xed,0x9d,0x6a,0x81,0xd9,0x32,0x42,0xe0,0xaf,0xf4,0x77,0x07,0xf0,
0x65,0x64,0x69,0xae,0x95,0x50,0xfe,0x86,0x21,0xba,0xcf,0xb5,0x43,
0xaf,0x90,0xe2,0xda,0xf4,0x2f,0x9f,0x9b,0x71,0x09,0x55,0x7a,0x53,
0xc3,0x63,0x1e,0xb9,0xa9,0x3f,0xfb,0x66,0x32,0xfa,0x3a,0x49,0x01,
0x01 ];
julia> pem = WebAuthn.extract_pubkey_pem_from_der(der);See also: cose_key_to_pem and der_to_pem.
WebAuthn.generate_challenge — Functiongenerate_challenge([n=32])::StringGenerate a random base64url-encoded challenge of n bytes.
Examples
julia> using WebAuthn
julia> challenge = generate_challenge();
julia> length(base64urldecode(challenge))
32WebAuthn.parse_assertion — Methodparse_assertion(authdata_b64, sig_b64) -> (authData, signature)Base64url-decode authenticatorData and signature as a tuple of byte vectors.
Returns the authenticator data and signature, each as a vector of bytes.
Examples
julia> using WebAuthn
julia> ad_b64 = base64urlencode(rand(UInt8, 37));
julia> sig_b64 = base64urlencode(rand(UInt8, 64));
julia> ad, sig = parse_assertion(ad_b64, sig_b64);See also: parse_attestation_object and parse_clientdata_json.
WebAuthn.parse_attestation_object — Methodparse_attestation_object(b64::String)::DictParse a base64url-encoded attestationObject to a dictionary.
Decodes and parses the CBOR-encoded attestation object returned during WebAuthn registration.
Examples
julia> using WebAuthn, CBOR
julia> attObj_b64 =
"o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVikgokmRebwXda2X9CScZAt1" *
"FS1U7jvFi6aDLY8eyICQjhBAAAAAcDiKS6EGVQBSZ3UWJ8FVioAIJYypOb6RxF" *
"Q4ocIvwK78qeEYp67CAWrj59jW99h8_tNpQECAyYgASFYIOyFijz315Yd_Aexkt" *
"5l6YaFK4MK2CQgRZPXQqGGD06MIlgg54dhMxLg9u84Y3urvWdHrViXea0aMYq7v" *
"7QI-DP1Duk";
julia> obj = parse_attestation_object(attObj_b64);See also: parse_clientdata_json.
WebAuthn.parse_clientdata_json — Methodparse_clientdata_json(b64::String)::DictParse a base64url-encoded clientDataJSON to a dictionary.
Decodes the clientDataJSON, converting from base64url and UTF-8 JSON to a Julia dictionary.
Examples
julia> using WebAuthn
julia> json = """{"type": "webauthn.get"}""";
julia> cdj_b64 = base64urlencode(Vector{UInt8}(json));
julia> cdj = parse_clientdata_json(cdj_b64)
Dict{String, Any} with 1 entry:
"type" => "webauthn.get"See also: parse_attestation_object.
WebAuthn.parse_credential_public_key — Methodparse_credential_public_key(authData::Vector{UInt8})::WebAuthnPublicKeyExtract and parse credential public key from authenticator data.
Reads the CBOR-encoded credentialPublicKey field from authData and returns the corresponding parsed struct (e.g., EC2PublicKey, RSAPublicKey, or OKPPublicKey).
Examples
julia> using WebAuthn, CBOR
julia> fake_pk = CBOR.encode(Dict(1=>2, 3=>-7, -1=>1, -2=>rand(UInt8,32),
-3=>rand(UInt8,32)));
julia> authData = vcat(zeros(UInt8, 37+16), 0x00, 0x20, rand(UInt8, 32),
fake_pk);
julia> key = parse_credential_public_key(authData);
See also: extract_credential_public_key and cose_key_parse.
WebAuthn.parse_ec_pem_xy — Methodparse_ec_pem_xy(pem::AbstractString)Extract XY EC coordinates from a PEM/SPKI P-256 public key.
Parses a PEM-encoded (or plain DER) SubjectPublicKeyInfo containing a P-256 (secp256r1) uncompressed EC public key, as produced for WebAuthn and most browsers or OpenSSL tools. Returns X and Y coordinates of the EC point, each as a 32-byte vector.
Handles both short- and long-form DER length encodings, and scans all BIT STRING tags for an uncompressed point (0x04 prefix, 65 bytes total). Raises an error if not found.
Example
julia> using WebAuthn
julia> pem = """
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK4CWBHImRgAVPXrmUD7VhNFW1sUs
GI17tvaN6KEkBukdOj8cXnZSnhFuPrf8ajP8KrRoYiZqHVFy8zyrPJzFnw==
-----END PUBLIC KEY-----
""";
julia> x, y = parse_ec_pem_xy(pem);
julia> length(x), length(y)
(32, 32)See also: pem_to_der, parse_rsa_pem_ne and parse_ed25519_pem_x.
WebAuthn.parse_ed25519_pem_x — Methodparse_ed25519_pem_x(pem::AbstractString)::x::Vector{UInt8}Extract the x-coordinate (32 bytes) from an Ed25519 public key (PEM/SPKI).
Parses a PEM-encoded Ed25519 SubjectPublicKeyInfo as generated by OpenSSL or Python and returns the 32-byte raw public key (x). This is useful for verifying Ed25519 signatures.
Example
julia> using WebAuthn
julia> pem = """
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAoi3rnmJUD+qXNlp2pBkQWpXCUUjccW+6Ue5r0QDPF94=
-----END PUBLIC KEY-----
""";
julia> x = parse_ed25519_pem_x(pem);
julia> length(x)
32See also: pem_to_der and parse_ec_pem_xy.
WebAuthn.parse_rsa_pem_ne — Methodparse_rsa_pem_ne(pem::AbstractString)Extract the modulus (n) and exponent (e) from an RSA public key (PEM/SPKI).
Reads a PEM-encoded RSA SubjectPublicKeyInfo (as produced by OpenSSL, browser tools, etc.) and returns the modulus and exponent as byte vectors suitable for cryptographic use.
Raises an error if the ASN.1 structure is unexpected or unsupported.
Example
julia> using WebAuthn
julia> pem = """
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2auHrQvvpQv/DI1wQAmd
YCUYzOr8hWU2rMtDEae/p5Cu5pyNJRdv7DjOdOeWeWq1rA/Od/GY/HYazst1lWMC
XjiW3nf0yV1jHoXl9Dc1wFTxl7EKrykK2EsijB8f93f4scxEalIyfjauXC6hIPi4
/yWGS8cJOuj35ac/7N6GrUMIdzCj0qumTrUhRkmsJo2HtGm3dKkEZxHnL7fs/hln
wwVOl2rqH0EcaVBSZwvjuEt6EfVMhqINp9FhRaIq5gx0ZpBR6OpFPM5oXrtMgsKO
vIdZK7yZPcKw0JLmymZMi5gjgGVTX48YHoM8Mi6KtB4k2Rbp3Ouqc56odpLx2K2S
cwIDAQAB
-----END PUBLIC KEY-----
""";
julia> n, e = parse_rsa_pem_ne(pem);
julia> length(n) > 200 && e == UInt8[0x01, 0x00, 0x01]
trueSee also: pem_to_der and parse_ec_pem_xy.
WebAuthn.pem_to_der — Methodpem_to_der(pem::AbstractString)::Vector{UInt8}Decode a PEM-formatted string (e.g., a PEM public key or certificate) to a DER-encoded byte vector.
Strips header/footer and whitespace, decodes the enclosed base64.
Example
julia> using WebAuthn
julia> pem = """
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK4CWBHImRgAVPXrmUD7VhNFW1sUs
GI17tvaN6KEkBukdOj8cXnZSnhFuPrf8ajP8KrRoYiZqHVFy8zyrPJzFnw==
-----END PUBLIC KEY-----
""";
julia> der = WebAuthn.pem_to_der(pem);WebAuthn.registration_options — Methodregistration_options(rpid, rpname, user_id, user_name, user_display;
exclude_ids=[], challenge=nothing,
attestation="none", timeout=60000, kwargs...)::DictConstruct WebAuthn registration options for navigator.credentials.create.
Arguments
rpid: relying party identifier (e.g., "example.com").rpname: display name of the RP.user_id: user handle (string or byte vector).user_name: username (string).user_display: display name (string).
Keywords
exclude_ids: vector of credential IDs to exclude (default empty).challenge: challenge string to use (default: random).attestation: "none" (default), "packed", "direct", "enterprise", etc.timeout: timeout in ms (default 60000).kwargs: any additional WebAuthn/PublicKeyCredentialCreationOptions fields; future extensions can be set directly as keywords.
Examples
julia> using WebAuthn
julia> opts = registration_options("foo.com", "Demo", 123, "bob",
"Bob", attestation="packed", extensions=Dict("my_custom"=>"hi"));
julia> opts["attestation"]
"packed"
julia> opts["extensions"]["my_custom"]
"hi"See also: authentication_options.
WebAuthn.verify_attestation_object — Methodverify_attestation_object(attObj_b64, clientDataJSON)::BoolVerify a WebAuthn attestation object of format "none" or "packed".
Examples
julia> using WebAuthn
julia> attObj_b64 =
"o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVikgokmRebwXda2X9CScZAt1" *
"FS1U7jvFi6aDLY8eyICQjhBAAAAAcDiKS6EGVQBSZ3UWJ8FVioAIJYypOb6RxF" *
"Q4ocIvwK78qeEYp67CAWrj59jW99h8_tNpQECAyYgASFYIOyFijz315Yd_Aexkt" *
"5l6YaFK4MK2CQgRZPXQqGGD06MIlgg54dhMxLg9u84Y3urvWdHrViXea0aMYq7v" *
"7QI-DP1Duk";
julia> cdj_b64 =
"eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiazF6eV9hU0N" *
"PTDdOMFBWVmFVVElpVm5BU1ZGVDE4MDB1TWJVa1R2dUdKSSIsIm9yaWdpbiI6Im" *
"h0dHBzOi8vd2ViYXV0aG4tdGVzdC5sb2NhbCIsImNyb3NzT3JpZ2luIjpmYWxze" *
"X0";
julia> clientDataJSON = WebAuthn.base64urldecode(cdj_b64);
julia> ok = verify_attestation_object(attObj_b64, clientDataJSON)
trueSee also: verify_webauthn_signature.
WebAuthn.verify_attestation_packed — Methodverify_attestation_packed(attStmt::Dict, msg::Vector{UInt8},
authData::Vector{UInt8}[, clientDataJSON::Vector{UInt8}])::BoolVerify a WebAuthn "packed" attestation statement (e.g., self-attested Ed25519 / ECDSA / RSA, as used in device authentication).
On success, returns true; otherwise, returns false. For Ed25519 (OKP, alg -8), the signature must be over SHA256(clientDataJSON) (not the full authData || SHA256(clientDataJSON)).
Examples
julia> using WebAuthn, CBOR, Sodium, SHA
julia> pk = Vector{UInt8}(undef, Sodium.crypto_sign_PUBLICKEYBYTES);
julia> sk = Vector{UInt8}(undef, Sodium.crypto_sign_SECRETKEYBYTES);
julia> Sodium.crypto_sign_keypair(pk, sk);
julia> cose = Dict(1=>1, 3=>-8, -1=>6, -2=>pk);
julia> cbor_pk = CBOR.encode(cose);
julia> rpId = "example.com";
julia> rpIdHash = SHA.sha256(Vector{UInt8}(rpId));
julia> flags = 0x41; signCount = UInt8[0,0,0,1]; aaguid = zeros(UInt8,16);
julia> credId = rand(UInt8,16); credIdLen = [UInt8(length(credId) >> 8),
UInt8(length(credId)&0xff)];
julia> authData = vcat(rpIdHash, flags, signCount, aaguid, credIdLen,
credId, cbor_pk);
julia> clientDataJSON = b"""{"type":"webauthn.create","challenge":"abc",
"origin":"https://example.com"}""";
julia> clientDataHash = SHA.sha256(clientDataJSON);
julia> sig = Vector{UInt8}(undef, Sodium.crypto_sign_BYTES);
julia> sl = Ref{UInt64}();
julia> Sodium.crypto_sign_detached(sig, sl, clientDataHash,
length(clientDataHash), sk);
julia> msg = vcat(authData, clientDataHash);
julia> attStmt = Dict("sig"=>sig, "alg"=>-8);
julia> verify_attestation_packed(attStmt, msg, authData)
true
julia> attStmt_bad = deepcopy(attStmt); attStmt_bad["sig"][1] ⊻= 0xFF;
julia> verify_attestation_packed(attStmt_bad, msg, authData)
falseWebAuthn.verify_challenge — Methodverify_challenge(clientDataJSON_b64, expected_challenge_b64)::BoolVerify the clientDataJSON challenge matches the expected challenge.
Examples
julia> using WebAuthn, JSON3
julia> challenge = generate_challenge(16);
julia> cdj = JSON3.write(Dict("type"=>"webauthn.create",
"challenge"=>challenge, "origin"=>"https://site"));
julia> cdj_b64 = base64urlencode(Vector{UInt8}(cdj));
julia> verify_challenge(cdj_b64, challenge)
trueSee also: generate_challenge
WebAuthn.verify_origin — Methodverify_origin(cdj::Dict, expected::String)Check that the 'origin' field in the parsed clientDataJSON matches what you expect.
Examples
julia> verify_origin(Dict("origin" => "https://demo.test"), "https://demo.test")
true
julia> verify_origin(Dict("origin" => "https://evil.site"), "https://demo.test")
ERROR: ArgumentError:
[...]
julia> # If 'origin' key is missing in dict
julia> verify_origin(Dict("foo" => 42), "https://demo.test")
ERROR: ArgumentError:
[...]WebAuthn.verify_p256_signature_raw_xy — Methodverify_p256_signature_raw_xy(x, y, digest, sig)::BoolVerify a P-256 ECDSA sig with OpenSSL using raw pubkey XY, SHA256 digest, and DER-encoded signature.
Examples
julia> using WebAuthn, SHA
julia> x = UInt8[
0x7d, 0xf1, 0xb2, 0x85, 0x1d, 0xdc, 0x04, 0x29,
0xdf, 0x71, 0xbd, 0x49, 0x9f, 0xea, 0x1d, 0xef,
0xca, 0x63, 0x4c, 0x5c, 0xbe, 0x8e, 0xaa, 0xa5,
0xcd, 0x3b, 0xa6, 0x65, 0xb7, 0xba, 0x3e, 0x32
];
julia> y = UInt8[
0x6e, 0x33, 0x03, 0x54, 0xd9, 0x5f, 0x0d, 0xb7,
0x28, 0x69, 0xec, 0x9a, 0x47, 0x82, 0x99, 0xe4,
0xe9, 0x34, 0x44, 0xe4, 0x8d, 0x40, 0x8f, 0xbe,
0xa1, 0x61, 0xf9, 0x3a, 0x4f, 0xd2, 0x14, 0xb8
];
julia> msg = b"test message";
julia> digest = SHA.sha256(msg);
julia> sig = UInt8[
0x30, 0x45, 0x02, 0x21, 0x00, 0xa9, 0xe7, 0x2a,
0x18, 0x6a, 0xe2, 0xa3, 0x5d, 0x7a, 0x34, 0xa2,
0x60, 0xef, 0xff, 0x36, 0x27, 0xbb, 0x59, 0x31,
0xf9, 0xe3, 0xdb, 0xe5, 0xf8, 0x0a, 0xa2, 0xff,
0x3f, 0xad, 0x2e, 0x3c, 0x79, 0x02, 0x20, 0x74,
0x24, 0x4a, 0xb1, 0x19, 0xf2, 0x70, 0x4f, 0xa2,
0x62, 0xdc, 0x87, 0x6c, 0x6b, 0xeb, 0xda, 0x77,
0xe1, 0x5a, 0x5a, 0x13, 0xb9, 0xec, 0x87, 0x4e,
0x29, 0x4b, 0x25, 0x95, 0x83, 0xc9, 0xdf];
julia> WebAuthn.verify_p256_signature_raw_xy(x, y, digest, sig)
true
julia> sig2 = copy(sig); sig2[1] ⊻= 0xFF;
julia> WebAuthn.verify_p256_signature_raw_xy(x, y, digest, sig2)
falseWebAuthn.verify_rsa_signature_raw_ne — Methodverify_rsa_signature_raw_ne(n, e, digest, sig)::BoolVerify an RSA PKCS1v1.5/SHA256 signature using raw modulus and exponent buffers, with everything in memory.
Examples
julia> using WebAuthn, SHA, Test
julia> n = UInt8[0xc8,0xac,0xb4,0xd0,0x1c,0x87,0x78,0x45,0x1d,0xcc,0xfa,
0xee,0x0a,0xe1,0x38,0xb4,0x12,0x71,0xf2,0x85,0x9d,0x00,
0xb1,0xf8,0x01,0x74,0x01,0xb9,0xcc,0x8f,0x02,0xda,0x6b,
0xa3,0x7a,0xe3,0xd8,0x35,0x00,0x63,0x52,0x16,0x4e,0xfc,
0xe3,0x8b,0xd0,0x88,0x8e,0xa8,0x03,0x6c,0x56,0x38,0x1f,
0x85,0xfd,0xf4,0xc0,0xa4,0x5b,0x6c,0x3f,0x0d];
julia> e = UInt8[0x01, 0x00, 0x01];
julia> msg = b"hello RSA";
julia> digest = SHA.sha256(msg);
julia> sig = UInt8[0x15,0xe4,0xed,0xd0,0x0a,0xe1,0x62,0xda,0xe5,0x84,0xb6,
0x9c,0x91,0x96,0x5e,0xba,0xa8,0x3a,0x01,0x55,0xc5,0x6e,
0x06,0xce,0xd5,0xd1,0x02,0x49,0x17,0x4c,0xb4,0xbf,0x36,
0x77,0x88,0x48,0x46,0x59,0x2e,0xd9,0xac,0x3e,0xcd,0x83,
0x69,0xab,0x46,0x8a,0xfe,0xa8,0xd0,0xee,0x1f,0x9c,0xfd,
0xe1,0xd9,0x03,0x57,0x70,0x34,0xe5,0x80,0xeb];
julia> WebAuthn.verify_rsa_signature_raw_ne(n, e, digest, sig)
true
julia> sig_bad = copy(sig);
julia> sig_bad[1] ⊻= 0xFF;
julia> WebAuthn.verify_rsa_signature_raw_ne(n, e, digest, sig_bad)
falseWebAuthn.verify_webauthn_signature — Functionverify_webauthn_signature(key_or_pem, authenticatorData,
clientDataJSON)::BoolVerify a WebAuthn assertion signature for the given public key or PEM.
Examples
julia> using WebAuthn, Sodium, SHA
julia> pk = Vector{UInt8}(undef, Sodium.crypto_sign_PUBLICKEYBYTES);
julia> sk = Vector{UInt8}(undef, Sodium.crypto_sign_SECRETKEYBYTES);
julia> Sodium.crypto_sign_keypair(pk, sk);
julia> key = OKPPublicKey(pk, -8, 6);
julia> ad = rand(UInt8, 37);
julia> cdj = rand(UInt8, 32);
julia> msg = vcat(ad, SHA.sha256(cdj));
julia> sig = Vector{UInt8}(undef, Sodium.crypto_sign_BYTES);
julia> sl = Ref{Culonglong}();
julia> Sodium.crypto_sign_detached(sig, sl, msg, length(msg), sk);
julia> valid = verify_webauthn_signature(key, ad, cdj, sig)
trueSee also: cose_key_to_pem and parse_assertion.