| Type: | Package |
| Title: | Offline Verifier for Attestix Ed25519 Credentials and UCAN Delegations |
| Version: | 0.4.1 |
| Description: | An offline verifier for verifiable credentials and delegation chains issued by the Attestix Python core. Verifies Ed25519 (RFC 8032) signatures over W3C Verifiable Credentials, decodes Ed25519 'did:key' identifiers, and verifies UCAN delegation chains (EdDSA 'JWT's) including capability attenuation, with no Python runtime required. Reproduces the Attestix JCS-style JSON canonical form (a practical subset of RFC 8785 that additionally applies 'NFC' Unicode normalization) byte-for-byte so that signatures produced by the reference implementation verify here. Useful for compliance, research and biostatistics users who work in R and need to check AI-agent compliance credentials. See https://attestix.io for the project and https://attestix.io/spec/bundle/v1 for the bundle wire format. |
| License: | Apache License (≥ 2) |
| URL: | https://github.com/VibeTensor/attestix-r, https://attestix.io |
| BugReports: | https://github.com/VibeTensor/attestix-r/issues |
| Encoding: | UTF-8 |
| Depends: | R (≥ 4.0.0) |
| Imports: | sodium, openssl, stringi |
| Suggests: | jsonlite, testthat (≥ 3.0.0) |
| Config/testthat/edition: | 3 |
| NeedsCompilation: | no |
| Config/roxygen2/version: | 8.0.0 |
| Packaged: | 2026-06-26 15:36:15 UTC; runner |
| Author: | Pavan Kumar Dubasi [aut, cre], VibeTensor [cph, fnd] |
| Maintainer: | Pavan Kumar Dubasi <info@vibetensor.com> |
| Repository: | CRAN |
| Date/Publication: | 2026-07-04 07:00:02 UTC |
attestix: Offline verifier for Attestix credentials and delegations
Description
The attestix package verifies, fully offline, the verifiable credentials and UCAN delegation chains issued by the Attestix Python core (https://github.com/VibeTensor/attestix). No Python runtime is needed.
Details
Key entry points:
-
atx_verify_credential- verify a W3C VC (Ed25519 signature + expiry + revocation). -
atx_canonicalize- the JCS-style canonical form (NOT strict RFC 8785; it additionally NFC-normalizes). -
atx_decode_did_key- decode an Ed25519did:keyto its raw 32-byte public key. -
atx_verify_delegation_chain- verify a UCAN delegation chain (per-link EdDSA + capability attenuation).
The canonical form is the load-bearing detail: see the spec at
https://attestix.io/spec/bundle/v1 and the conformance vectors vendored
under inst/testdata/vectors.json.
Author(s)
Maintainer: Pavan Kumar Dubasi info@vibetensor.com
Authors:
Pavan Kumar Dubasi info@vibetensor.com
Other contributors:
VibeTensor [copyright holder, funder]
See Also
Useful links:
Report bugs at https://github.com/VibeTensor/attestix-r/issues
Fields excluded from the W3C VC signature (MUTABLE_FIELDS).
Description
Fields excluded from the W3C VC signature (MUTABLE_FIELDS).
Usage
.ATX_MUTABLE_FIELDS
Ed25519 multicodec prefix (0xed 0x01) for ed25519-pub.
Description
Ed25519 multicodec prefix (0xed 0x01) for ed25519-pub.
Usage
.ED25519_MULTICODEC_PREFIX
base64url decode (accepts padded or unpadded input)
Description
VC proofValue is base64url with padding; JWT compact segments
are base64url without padding. This decoder accepts both by
re-padding as needed, then delegating to openssl::base64_decode after
translating the URL alphabet (-_) to the standard alphabet
(+/).
Usage
atx_b64url_decode(s)
Arguments
s |
A length-1 base64url string. |
Value
A raw vector.
base64url encode WITH padding (matches Python base64.urlsafe_b64encode).
Description
base64url encode WITH padding (matches Python base64.urlsafe_b64encode).
Usage
atx_b64url_encode(bytes)
Arguments
bytes |
A raw vector. |
Value
A length-1 base64url string (padded).
Decode a base58btc string to raw bytes.
Description
Decode a base58btc string to raw bytes.
Usage
atx_base58_decode(s)
Arguments
s |
A length-1 character string. |
Value
A raw vector.
Encode raw bytes to a base58btc string.
Description
Encode raw bytes to a base58btc string.
Usage
atx_base58_encode(bytes)
Arguments
bytes |
A raw vector. |
Value
A length-1 character string.
Attestix JCS-style canonical JSON
Description
Reproduces attestix/auth/crypto.py::canonicalize_json byte-for-byte.
Usage
atx_canonicalize(obj)
Arguments
obj |
A JSON string, raw UTF-8 bytes, or a value tree produced by
|
Details
This is JCS-style, NOT strict RFC 8785. The two load-bearing divergences from RFC 8785 are:
NFC Unicode normalization is applied to every string value and every object key (RFC 8785 does not normalize).
Whole-number floats collapse to integers (
1.0 -> 1); non-whole floats use Python'srepr(the vectors only use integers and1.5, on which every port agrees).
Keys are sorted by Unicode code point, separators are "," and
":" with no whitespace, output is raw UTF-8 (no \uXXXX
escapes), and large integers (> 2^53) are preserved exactly.
Value
A raw vector of the canonical UTF-8 bytes.
Examples
bytes <- atx_canonicalize('{"b":2,"a":1}')
rawToChar(bytes) # {"a":1,"b":2}
Decode an Ed25519 did:key to its raw 32-byte public key
Description
Reproduces attestix/auth/crypto.py::did_key_to_public_key: strip the
did:key:z prefix, base58btc-decode the multibase payload, assert the
first two bytes are the 0xed 0x01 multicodec prefix, and return the
remaining 32 raw bytes.
Usage
atx_decode_did_key(did)
Arguments
did |
A |
Value
A raw vector of length 32 (the Ed25519 public key).
Examples
did <- "did:key:z6Mko5TBPGKHkCxSgmf3aC6p6SGj2auwCfRmBydXJFEwL4ev"
length(atx_decode_did_key(did)) # 32
Return the multibase fragment portion of a did:key
Description
The verification method is <did>#<multibase> where <multibase>
is the z... portion of the did:key. This returns that fragment with a
leading #.
Usage
atx_did_key_fragment(did)
Arguments
did |
A |
Value
The #z... fragment.
Verify an Ed25519 (RFC 8032) signature
Description
Thin wrapper over sodium::sig_verify (libsodium). Returns a logical
rather than signalling, so callers can fold it into a structured result.
Usage
atx_ed25519_verify(message, signature, public_key)
Arguments
message |
Raw vector of the signed message bytes. |
signature |
Raw vector, 64 bytes. |
public_key |
Raw vector, 32 bytes. |
Value
TRUE if the signature is valid, else FALSE.
Examples
## Not run:
atx_ed25519_verify(msg, sig, pubkey)
## End(Not run)
Hex string -> raw vector.
Description
Hex string -> raw vector.
Usage
atx_hex_to_raw(h)
Arguments
h |
A hex string (even length). |
Value
A raw vector.
Minimal, deterministic JSON parser for canonicalisation
Description
jsonlite is excellent but its number handling is ambiguous for our
needs: we must tell a big integer (9007199254740993, which must be
emitted bare with no precision loss) apart from a JSON string, and we must
know whether a numeric token was written 1.0 (whole -> int) or
1.5 (non-whole). This hand-written recursive-descent parser preserves
every number token as a tagged raw lexeme so the canonicaliser can apply the
exact Attestix number rules.
Usage
atx_json_parse(txt)
Arguments
txt |
JSON text (length-1 character) or raw UTF-8 bytes. |
Details
Returned value tree:
object -> named
list(insertion order preserved)array -> unnamed
liststring -> length-1
character(UTF-8)number -> length-1
characterwith class"atx_number"carrying the raw lexeme (e.g. "9007199254740993", "1.0")true/false -> length-1
logicalnull ->
NULLwrapped aslist(NULL)element so it survives in lists; top-level null isNULL
Empty object vs empty array are distinguished: {} -> empty
named list, [] -> empty unnamed list.
Value
The parsed value tree.
Decode a JWT compact token without verifying.
Description
Decode a JWT compact token without verifying.
Usage
atx_jwt_decode(token)
Arguments
token |
A compact JWT ( |
Value
A list with header, payload (parsed value trees),
signing_input (raw bytes of header.payload), and
signature (raw bytes).
Parse JSON into the canonicalisation value tree
Description
Convenience alias for atx_json_parse.
Usage
atx_parse_json(txt)
Arguments
txt |
JSON text or raw UTF-8 bytes. |
Value
The parsed value tree.
Encode a raw 32-byte Ed25519 public key to a did:key
Description
Inverse of atx_decode_did_key.
Usage
atx_public_key_to_did_key(pubkey)
Arguments
pubkey |
A raw vector of length 32. |
Value
A did:key:z... string.
Raw vector -> lowercase hex string.
Description
Raw vector -> lowercase hex string.
Usage
atx_raw_to_hex(r)
Arguments
r |
A raw vector. |
Value
A hex string.
Full verification method for a did:key (<did>#<multibase>).
Description
Full verification method for a did:key (<did>#<multibase>).
Usage
atx_verification_method(did)
Arguments
did |
A |
Value
The verification-method string.
Verify an Attestix W3C Verifiable Credential offline
Description
Mirrors attestix/services/credential_service.py::verify_credential.
The signing payload is the credential with the proof and
credentialStatus top-level keys removed; that payload is JCS-style
canonicalized (see atx_canonicalize) and the Ed25519 signature
in proof.proofValue is verified against the issuer public key.
Usage
atx_verify_credential(vc, public_key = NULL, now = Sys.time())
Arguments
vc |
The credential as a JSON string, raw UTF-8 bytes, or a value tree
from |
public_key |
The issuer Ed25519 public key. Accepts a raw 32-byte
vector, a 64-char hex string, or |
now |
The reference time for the expiry check, as a
|
Details
Three independent checks are ANDed:
-
signature_valid- Ed25519 verification of the canonical bytes. -
not_expired-now < expirationDate(tz-aware ISO-8601). -
not_revoked-credentialStatus$revokedis falsy.
Value
A list with logical fields signature_valid,
not_expired, not_revoked, structure_valid, and the
overall verify.
Examples
## Not run:
res <- atx_verify_credential(vc_json)
isTRUE(res$verify)
## End(Not run)
Verify a UCAN delegation chain (Ed25519 per link + attenuation)
Description
Mirrors the recursive prf-chain verification in
attestix/services/delegation_service.py. Each token in the chain is a
PyJWT EdDSA JWT; the signed message is the compact header.payload
form (base64url unpadded), NOT the JCS canonical form.
Usage
atx_verify_delegation_chain(
chain,
public_key,
now = Sys.time(),
revoked_jti = character(0)
)
Arguments
chain |
A list describing the chain. Accepts the conformance-vector
shape: |
public_key |
The Ed25519 server public key (raw 32 bytes or hex). |
now |
Reference time. Defaults to |
revoked_jti |
Optional revoked |
Details
The chain verifies iff every token's signature is valid AND every token is
unexpired and unrevoked AND each child's att is a subset of
its parent's att (capability attenuation; escalation is rejected).
Cycles (a repeated jti) are rejected.
Value
A list with parent_signature_valid,
child_signature_valid, attenuation_is_subset, and the overall
verify.
Examples
## Not run:
atx_verify_delegation_chain(list(parent_token = pt, token = ct), pk)
## End(Not run)
Verify a single UCAN JWT (signature + alg + expiry + revocation).
Description
Mirrors the per-token checks in
attestix/services/delegation_service.py::verify_delegation. Only
alg=EdDSA is accepted; alg:none (and any other alg) is rejected.
Usage
atx_verify_ucan_token(
token,
public_key,
now = Sys.time(),
revoked_jti = character(0)
)
Arguments
token |
A compact JWT string. |
public_key |
The Ed25519 server public key (raw 32 bytes or hex). |
now |
Reference time (POSIXct or ISO/epoch). Defaults to
|
revoked_jti |
Optional character vector of revoked |
Value
A list with signature_valid, not_expired,
not_revoked, alg_ok, jti, att, and valid.
Base58btc (Bitcoin alphabet) encode/decode
Description
Vendored minimal implementation, no external dependency. Used for did:key
multibase z payloads. Uses double-precision-safe big-integer-free
byte arithmetic (repeated base-256 <-> base-58 conversion on raw byte
vectors), so it is exact for arbitrary-length inputs.