FFI parity: verification introspection, key certifications, security profiles#15
Open
ronaldtse wants to merge 8 commits into
Open
FFI parity: verification introspection, key certifications, security profiles#15ronaldtse wants to merge 8 commits into
ronaldtse wants to merge 8 commits into
Conversation
Extend rnp_op_verify()/rnp_op_verify_detached() results with full per-signature information backed by the rnp_signature_get_*() family: signature algorithm, signer keyid and fingerprint, features, key flags and expiration, primary uid flag, trust level, revoker, revocation reason, key server and preferences, preferred algorithm lists, validation error codes (rnp_signature_error_count()/at()) and subpacket enumeration (rnp_signature_subpacket_*()). Both functions also gained an optional flags parameter (rnp_op_verify_set_flags()) and report recipients and symencs of encrypted data together with the ones used for decryption. New functions rnp_key_get_signatures() and rnp_uid_get_signatures() return the same signature information for key direct/revocation signatures and userid certifications, including the exported signature packet (rnp_signature_export()). New constants: RNP_VERIFY_*, RNP_SIGNATURE_REVALIDATE. Also make the sub_alg parameter of rnp_op_generate_key() explicitly nullable in the stub as required by the PHP 8.5 gen_stub.php.
Back the new fields with rnp_key_get_version(), rnp_key_get_revoker_count() and rnp_key_get_revoker_at().
Wrap rnp_key_certification_create(), rnp_key_direct_signature_create() and rnp_key_revocation_signature_create(). All the rnp_key_signature_set_*()/add_preferred_*() customization calls are folded into an options array of the create functions, which return an opaque RnpKeySignature object finalized with rnp_key_signature_sign(). Also add rnp_key_remove_signatures(). New constants: RNP_KEY_USAGE_*, RNP_KEY_FEATURE_*, RNP_CERTIFICATION_*, RNP_KEY_SERVER_NO_MODIFY, RNP_REVOKER_SENSITIVE, RNP_KEY_SIGNATURE_*.
Wrap rnp_add_security_rule(), rnp_get_security_rule(), rnp_remove_security_rule() and rnp_set_timestamp(), allowing to override default algorithm security rules (i.e. allow SHA1 signatures) and to set a fixed timestamp for all operations. Also wrap rnp_request_password(), which requests a password via the callback configured with rnp_ffi_set_pass_provider(). New constants: RNP_SECURITY_*.
Wrap rnp_key_protect()/rnp_key_unprotect() (password plus an options array with cipher, hash, iterations and mode), rnp_key_lock(), rnp_key_unlock() and rnp_key_set_expiration(). rnp_key_get_info() now reports the expiration time and provides rich uid entries (data, type, is_primary, is_valid, is_revoked, signature_count) instead of plain strings. Add the user-ID API: rnp_key_add_uid() with hash/expiration/ key_flags/primary options, rnp_uid_get_info() returning the uid model together with the revocation signature when present, and rnp_uid_remove(). Uid handles are always released via rnp_uid_handle_destroy() as required by the FFI. New constants: RNP_USER_ID, RNP_USER_ATTR.
Wrap rnp_enarmor()/rnp_dearmor() as string in/out functions with an optional armor type parameter (guessed from the contents when NULL), and rnp_calculate_iterations() for time-based s2k iteration counts.
Wrap rnp_key_to_json() and rnp_key_packets_to_json(), and change rnp_dump_packets_to_json() to return the decoded JSON as PHP arrays (json_decode(..., true) semantics) instead of opaque strings, matching the extension's array-shaped API. Signature listings produced by rnp_key_get_signatures()/rnp_uid_get_signatures() now also carry the decoded rnp_signature_packet_to_json() dump under the json key. JSON result buffers are wiped with rnp_buffer_clear() before release since they may contain secret key material. New constants: RNP_JSON_PUBLIC_MPIS, RNP_JSON_SECRET_MPIS, RNP_JSON_SIGNATURE_MPIS.
Exercise the file name/modification time, signature expiration time and AEAD chunk size options of the encrypt/sign options arrays in packet dumps and verification results (tests/028.phpt). Also list the recently added test files in package.xml.
ronaldtse
added a commit
to rnpgp/rnp
that referenced
this pull request
Jul 22, 2026
The signature validation error range (RNP_ERROR_SIG_*, starting at 0x14000000 and added in 1c616df) had no cases in rnp_result_to_string(), so all 28 codes fell through to "Unsupported error code". These codes reach FFI callers via rnp_signature_error_at() and rnp_op_verify_signature_get_status(), leaving downstream bindings without meaningful messages; surfaced by rnpgp/php-rnp#15. Add one case with a descriptive string per code, and extend test_result_to_string to cover the new range and to assert the exact string of every defined error code.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
FFI-parity pass against librnp 0.18.1/main. The extension exposed ~30 PHP functions of librnp's 296-symbol FFI; this PR closes the highest-value gaps — verification/signature introspection, the 0.18 key-certification API, and security profiles — with new phpt coverage.
rnp_arginfo.hwas regenerated with PHP 8.5'sgen_stub.php; the build stays warning-free.New/changed PHP API
rnp_op_verify()/rnp_op_verify_detached()accept optionalint $flags = 0(BC); per-signature arrays now includealg,keyid,key_fprint,features,key_flags,key_expiration,primary_uid,trust_level/amount,revoker,revocation_code/reason,key_server(+prefs),preferred_algs/hashes/zalgs,errors(viarnp_signature_error_count/at— covers invalid-signature reporting), andsubpackets(type/hashed/critical/data). Top level addsrecipients,symencs,used_recipient,used_symenc.rnp_key_get_signatures(),rnp_uid_get_signatures()(withvalidity_statusand exported packetdata),rnp_key_certification_create()/rnp_key_direct_signature_create()/rnp_key_revocation_signature_create()returning the new final class RnpKeySignature (all setters folded into an options array, idiomatic for this extension),rnp_key_signature_sign(),rnp_key_remove_signatures(),rnp_add/get/remove_security_rule(),rnp_set_timestamp(),rnp_request_password()(buffer cleared after copy).rnp_key_get_info()gainsversionandrevokers.RNP_VERIFY_*,RNP_SIGNATURE_REVALIDATE,RNP_KEY_USAGE_*,RNP_KEY_FEATURE_*,RNP_CERTIFICATION_*,RNP_KEY_SERVER_NO_MODIFY,RNP_REVOKER_SENSITIVE,RNP_KEY_SIGNATURE_*,RNP_SECURITY_*.Tests
tests/019.phpt(verify flags, invalid-signature error codes, subpacket + recipient/symenc enumeration),020.phpt(security-rule roundtrip: SHA-1 invalid by default → allowed via override → invalid after removal),021.phpt(certification/direct/revocation create+sign read-back, error paths, double-sign exception),022.phpt(request_password);009/013updated for the extended array shapes;package.xmlupdated.Remaining scope (noted for follow-ups)
Most of the ~240 still-unbound symbols are either already covered by options arrays (the granular
rnp_op_*setters), or out of this extension's idioms (stream/callback APIs). Notable candidates for later: key protect/lock/unlock,rnp_key_add_uid,rnp_uid_get_*,rnp_enarmor/rnp_dearmor, JSON key dumps, remaining key getters foldable intornp_key_get_info. Upstream gap found: librnp'srnp_result_to_stringreturns "Unsupported error code" for theRNP_ERROR_SIG_*range, soerrors[]entries are only partially descriptive.