Class: Rnp
- Inherits:
-
Object
- Object
- Rnp
- Defined in:
- lib/rnp/rnp.rb,
lib/rnp/key.rb,
lib/rnp/misc.rb,
lib/rnp/error.rb,
lib/rnp/input.rb,
lib/rnp/utils.rb,
lib/rnp/output.rb,
lib/rnp/userid.rb,
lib/rnp/op/sign.rb,
lib/rnp/version.rb,
lib/rnp/op/verify.rb,
lib/rnp/signature.rb,
lib/rnp/op/encrypt.rb,
lib/rnp/op/generate.rb
Overview
© 2018-2023 Ribose Inc.
Defined Under Namespace
Classes: BadFormatError, BadPasswordError, Encrypt, Error, FeatureNotAvailableError, Generate, Input, InvalidSignatureError, Key, NoSuitableKeyError, Output, Sign, Signature, UserID, Verify
Constant Summary collapse
- FEATURES =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
{ # Support for setting hash, creation, and expiration time for individual # signatures in a sign operation. Older versions of rnp returned a # "not implemented" error. "per-signature-opts" => Rnp.version > Rnp.version("0.11.0") || Rnp.commit_time >= 1546035818, # Correct grip calculation for Elgamal/DSA keys. This was actually before # the commit timestamp API was added, so this isn't accurate in one case. "dsa-elg-grip-calc" => Rnp.version > Rnp.version("0.11.0") || Rnp.commit_time >= 1538219020, # Input reader callback signature was changed: # ssize_t(void *app_ctx, void *buf, size_t len) # bool(void *app_ctx, void *buf, size_t len, size_t *read) "input-reader-cb-no-ssize_t" => Rnp.version >= Rnp.version("0.14.0") || Rnp.commit_time >= 1585833163, # Behavior on primary userid retrieveing was changed: # Now userid is not considered as primary if it is revoked/expired/etc. "primary-userid-must-be-valid" => Rnp.version >= Rnp.version("0.14.0") || Rnp.commit_time >= 1605875599, # Behavior was changed in v0.15.2 (issue #1509): # userid is valid even if key expiration in userid expiration expires key. "relax-userid-validity-checks" => Rnp.version >= Rnp.version("0.15.2") || Rnp.commit_time >= 1624526708, # Behavior on default key expiration time was changed: # Now default key expiration time is 2 years "default-key-expiration-2-years" => Rnp.version >= Rnp.version("0.16.1") || Rnp.commit_time >= 1645578982, # Behaviour on signature validation was changed: # Now at least one valid signature is required for success "require-single-valid-signature" => Rnp.version >= Rnp.version("0.16.1") || Rnp.commit_time >= 1661781294, }.freeze
- ERRORS_MAP =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
{ LibRnp::RNP_ERROR_BAD_PASSWORD => BadPasswordError, LibRnp::RNP_ERROR_SIGNATURE_INVALID => InvalidSignatureError, LibRnp::RNP_ERROR_BAD_FORMAT => BadFormatError, LibRnp::RNP_ERROR_NO_SUITABLE_KEY => NoSuitableKeyError }.freeze
- VERSION =
"1.0.5"
Instance Attribute Summary collapse
- #ptr ⇒ Object readonly private
Class Method Summary collapse
-
.call_ffi(fn, *args) ⇒ void
private
Calls the LibRnp FFI function indicated.
-
.commit_time ⇒ Integer
Retrieve the commit time of the latest commit.
-
.dearmor(input:, output: nil) ⇒ nil, String
Remove ASCII Armor from data.
-
.default_homedir ⇒ String
Get the default homedir for RNP.
- .destroy(ptr) ⇒ Object private
-
.disable_debug ⇒ void
Disable previously-enabled debugging.
-
.enable_debug(file = nil) ⇒ void
Enable debugging.
-
.enarmor(input:, output: nil, type: nil) ⇒ nil, String
Add ASCII Armor to data.
-
.guess_contents(input) ⇒ String
Guess the contents of an input.
- .has?(feature) ⇒ Boolean
-
.homedir_info(homedir) ⇒ Hash<Symbol>
Attempt to detect information about a homedir.
- .inspect_ptr(myself) ⇒ Object private
-
.key_format(key_data) ⇒ String
Attempt to detect the format of a key.
-
.parse(input:, mpi: false, raw: false, grip: false) ⇒ Array
Parse OpenPGP data to JSON.
- .raise_error(msg, rc = nil) ⇒ Object private
-
.s2k_iterations(hash:, msec:) ⇒ Integer
Calculate s2k iterations.
-
.supported_features(type) ⇒ Array
Get a list of supported features (by type).
-
.supports?(type, name) ⇒ Boolean
Check if a specific feature is supported.
-
.version(str = nil) ⇒ Integer
Get the version stamp of the rnp library as an unsigned 32-bit integer.
-
.version_for(major, minor, patch) ⇒ Integer
Encode the given major, minor, and patch numbers into a version stamp.
-
.version_major(version) ⇒ Integer
Extract the major version component from the given version stamp.
-
.version_minor(version) ⇒ Integer
Extract the minor version component from the given version stamp.
-
.version_patch(version) ⇒ Integer
Extract the patch version component from the given version stamp.
-
.version_string ⇒ String
Get the version of the rnp library as a string.
-
.version_string_full ⇒ String
Get the detailed version of the rnp library as a string.
Instance Method Summary collapse
-
#cleartext_sign(input:, output: nil, signers:, compression: nil, creation_time: nil, expiration_time: nil, hash: nil) ⇒ nil, String
Create a cleartext signature.
-
#decrypt(input:, output: nil) ⇒ nil, String
Decrypt encrypted data.
-
#detached_sign(input:, output: nil, signers:, armored: nil, compression: nil, creation_time: nil, expiration_time: nil, hash: nil) ⇒ nil, String
Create a detached signature.
-
#detached_verify(data:, signature:) ⇒ Object
Verify a detached signature.
-
#each_fingerprint(&block) ⇒ self, Enumerator
Enumerate all fingerprints.
-
#each_grip(&block) ⇒ self, Enumerator
Enumerate all grips.
-
#each_keyid(&block) ⇒ self, Enumerator
Enumerate all keyids.
-
#each_userid(&block) ⇒ self, Enumerator
Enumerate all userids.
-
#encrypt(input:, output: nil, recipients:, armored: nil, compression: nil, cipher: nil, aead: nil) ⇒ Object
Encrypt data with a public key.
-
#encrypt_and_sign(input:, output: nil, recipients:, signers:, armored: nil, compression: nil, cipher: nil, aead: nil, hash: nil, creation_time: nil, expiration_time: nil) ⇒ Object
Encrypt and sign data with a public key.
-
#find_key(criteria) ⇒ Key?
Find a key.
-
#fingerprints ⇒ Array<String>
Get a list of all fingerprints.
-
#generate(type:, userid:, bits:, curve: nil, password:, subtype: nil, subbits: 0, subcurve: nil) ⇒ Object
Generate a key and optional subkey.
-
#generate_dsa_elgamal(userid:, bits:, subbits: 0, password:) ⇒ Object
Generate a DSA (w/optional ElGamal subkey) key.
-
#generate_ecdsa_ecdh(userid:, curve:, password:) ⇒ Object
Generate an ECDSA+ECDH key pair.
-
#generate_eddsa_25519(userid:, password:) ⇒ Object
Generate an EdDSA+x25519 key pair.
-
#generate_key(description) ⇒ Hash<Symbol, Key>
Generate a new key or pair of keys.
-
#generate_rsa(userid:, bits:, subbits: 0, password:) ⇒ Object
Generate an RSA key (w/optional subkey).
-
#generate_sm2(userid:, password:) ⇒ Object
Generate an SM2 key pair.
-
#grips ⇒ Array<String>
Get a list of all grips.
-
#import_keys(input:, public_keys: true, secret_keys: true) ⇒ Hash
Import keys.
-
#import_signatures(input:) ⇒ Hash
Import signatures.
-
#initialize(pubfmt = 'GPG', secfmt = 'GPG') ⇒ Rnp
constructor
Create a new interface to RNP.
- #inspect ⇒ Object
-
#key_provider=(provider) ⇒ Object
Set a key provider.
-
#keyids ⇒ Array<String>
Get a list of all keyids.
-
#load_keys(input:, format:, public_keys: true, secret_keys: true) ⇒ void
Load keys.
-
#log=(fd) ⇒ Object
Set a logging destination.
-
#password_provider=(provider) ⇒ Object
Set a password provider.
- #public_key_count ⇒ Object
-
#save_keys(output:, format:, public_keys: false, secret_keys: false) ⇒ void
Save keys.
- #secret_key_count ⇒ Object
-
#sign(input:, output: nil, signers:, armored: nil, compression: nil, creation_time: nil, expiration_time: nil, hash: nil) ⇒ nil, String
Create a signature.
-
#start_cleartext_sign(input:, output:) ⇒ Object
Create a cleartext Sign operation.
-
#start_detached_sign(input:, output:) ⇒ Object
Create a detached Sign operation.
-
#start_detached_verify(data:, signature:) ⇒ Object
Create a detached Verify operation.
-
#start_encrypt(input:, output:) ⇒ Object
Create an Encrypt operation.
-
#start_generate(type:) ⇒ Generate
Start a Generate operation.
-
#start_generate_subkey(primary:, type:) ⇒ Generate
Start a Generate operation.
-
#start_sign(input:, output:) ⇒ Object
Create a Sign operation.
-
#start_verify(input:, output: nil) ⇒ Object
Create a Verify operation.
-
#symmetric_encrypt(input:, output: nil, passwords:, armored: nil, compression: nil, cipher: nil, aead: nil, s2k_hash: nil, s2k_iterations: 0, s2k_cipher: nil) ⇒ void
Encrypt with a password only.
- #unload_keys(public_keys: true, secret_keys: true) ⇒ Object
-
#userids ⇒ Array<String>
Get a list of all userids.
-
#verify(input:, output: nil) ⇒ Object
Verify a signature.
Constructor Details
#initialize(pubfmt = 'GPG', secfmt = 'GPG') ⇒ Rnp
Create a new interface to RNP.
28 29 30 31 32 33 34 |
# File 'lib/rnp/rnp.rb', line 28 def initialize(pubfmt = 'GPG', secfmt = 'GPG') pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_ffi_create, pptr, pubfmt, secfmt) @ptr = FFI::AutoPointer.new(pptr.read_pointer, self.class.method(:destroy)) @key_provider = nil @password_provider = nil end |
Instance Attribute Details
#ptr ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
22 23 24 |
# File 'lib/rnp/rnp.rb', line 22 def ptr @ptr end |
Class Method Details
.call_ffi(fn, *args) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Calls the LibRnp FFI function indicated. If the return code is <0, an error will be raised.
19 20 21 22 23 |
# File 'lib/rnp/utils.rb', line 19 def self.call_ffi(fn, *args) rc = LibRnp.method(fn).call(*args) Rnp.raise_error("#{fn} failed", rc) unless rc.zero? nil end |
.commit_time ⇒ Integer
Retrieve the commit time of the latest commit.
This will return 0 for release/non-master builds.
165 166 167 |
# File 'lib/rnp/misc.rb', line 165 def self.commit_time LibRnp. end |
.dearmor(input:, output: nil) ⇒ nil, String
Remove ASCII Armor from data.
98 99 100 101 102 |
# File 'lib/rnp/misc.rb', line 98 def self.dearmor(input:, output: nil) Output.default(output) do |output_| Rnp.call_ffi(:rnp_dearmor, input.ptr, output_.ptr) end end |
.default_homedir ⇒ String
Get the default homedir for RNP.
15 16 17 18 19 20 21 22 23 24 |
# File 'lib/rnp/misc.rb', line 15 def self.default_homedir pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_get_default_homedir, pptr) begin phomedir = pptr.read_pointer phomedir.read_string unless phomedir.null? ensure LibRnp.rnp_buffer_destroy(phomedir) end end |
.destroy(ptr) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
37 38 39 |
# File 'lib/rnp/rnp.rb', line 37 def self.destroy(ptr) LibRnp.rnp_ffi_destroy(ptr) end |
.disable_debug ⇒ void
This method returns an undefined value.
Disable previously-enabled debugging
213 214 215 |
# File 'lib/rnp/misc.rb', line 213 def self.disable_debug Rnp.call_ffi(:rnp_disable_debug) end |
.enable_debug(file = nil) ⇒ void
This method returns an undefined value.
Enable debugging
206 207 208 |
# File 'lib/rnp/misc.rb', line 206 def self.enable_debug(file = nil) Rnp.call_ffi(:rnp_enable_debug, file) end |
.enarmor(input:, output: nil, type: nil) ⇒ nil, String
Add ASCII Armor to data.
86 87 88 89 90 |
# File 'lib/rnp/misc.rb', line 86 def self.enarmor(input:, output: nil, type: nil) Output.default(output) do |output_| Rnp.call_ffi(:rnp_enarmor, input.ptr, output_.ptr, type) end end |
.guess_contents(input) ⇒ String
Guess the contents of an input
222 223 224 225 226 227 228 229 230 231 |
# File 'lib/rnp/misc.rb', line 222 def self.guess_contents(input) pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_guess_contents, input.ptr, pptr) begin presult = pptr.read_pointer presult.read_string unless presult.null? ensure LibRnp.rnp_buffer_destroy(presult) end end |
.has?(feature) ⇒ Boolean
293 294 295 296 |
# File 'lib/rnp/misc.rb', line 293 def self.has?(feature) raise ArgumentError unless FEATURES.include?(feature) FEATURES[feature] end |
.homedir_info(homedir) ⇒ Hash<Symbol>
Attempt to detect information about a homedir.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/rnp/misc.rb', line 36 def self.homedir_info(homedir) pptrs = FFI::MemoryPointer.new(:pointer, 4) Rnp.call_ffi(:rnp_detect_homedir_info, homedir, pptrs[0], pptrs[1], pptrs[2], pptrs[3]) ptrs = (0..3).collect { |i| pptrs[i] }.map(&:read_pointer) return if ptrs.all?(&:null?) { public: { format: ptrs[0].read_string, path: ptrs[1].read_string }, secret: { format: ptrs[2].read_string, path: ptrs[3].read_string } } ensure ptrs&.each { |ptr| LibRnp.rnp_buffer_destroy(ptr) } end |
.inspect_ptr(myself) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
26 27 28 29 30 31 |
# File 'lib/rnp/utils.rb', line 26 def self.inspect_ptr(myself) ptr_format = "0x%0#{FFI::Pointer.size * 2}x" ptr_s = format(ptr_format, myself.instance_variable_get(:@ptr).address) class_name = myself.class.to_s "#<#{class_name}:#{ptr_s}>" end |
.key_format(key_data) ⇒ String
Attempt to detect the format of a key.
60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/rnp/misc.rb', line 60 def self.key_format(key_data) pptr = FFI::MemoryPointer.new(:pointer) data = FFI::MemoryPointer.from_data(key_data) Rnp.call_ffi(:rnp_detect_key_format, data, data.size, pptr) begin pformat = pptr.read_pointer pformat.read_string unless pformat.null? ensure LibRnp.rnp_buffer_destroy(pformat) end end |
.parse(input:, mpi: false, raw: false, grip: false) ⇒ Array
Parse OpenPGP data to JSON.
176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/rnp/misc.rb', line 176 def self.parse(input:, mpi: false, raw: false, grip: false) flags = 0 flags |= LibRnp::RNP_JSON_DUMP_MPI if mpi flags |= LibRnp::RNP_JSON_DUMP_RAW if raw flags |= LibRnp::RNP_JSON_DUMP_GRIP if grip pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_dump_packets_to_json, input.ptr, flags, pptr) begin pjson = pptr.read_pointer JSON.parse(pjson.read_string) unless pjson.null? ensure LibRnp.rnp_buffer_destroy(pjson) end end |
.raise_error(msg, rc = nil) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
33 34 35 36 |
# File 'lib/rnp/error.rb', line 33 def self.raise_error(msg, rc = nil) klass = ERRORS_MAP.fetch(rc, Error) raise klass.new(msg, rc) end |
.s2k_iterations(hash:, msec:) ⇒ Integer
Calculate s2k iterations
196 197 198 199 200 |
# File 'lib/rnp/misc.rb', line 196 def self.s2k_iterations(hash:, msec:) piters = FFI::MemoryPointer.new(:size_t) Rnp.call_ffi(:rnp_calculate_iterations, hash, msec, piters) piters.read(:size_t) end |
.supported_features(type) ⇒ Array
Get a list of supported features (by type)
248 249 250 251 252 253 254 255 256 257 |
# File 'lib/rnp/misc.rb', line 248 def self.supported_features(type) pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_supported_features, type, pptr) begin presult = pptr.read_pointer JSON.parse(presult.read_string) unless presult.null? ensure LibRnp.rnp_buffer_destroy(presult) end end |
.supports?(type, name) ⇒ Boolean
Check if a specific feature is supported
238 239 240 241 242 |
# File 'lib/rnp/misc.rb', line 238 def self.supports?(type, name) presult = FFI::MemoryPointer.new(:bool) Rnp.call_ffi(:rnp_supports_feature, type, name, presult) presult.read(:bool) end |
.version(str = nil) ⇒ Integer
Get the version stamp of the rnp library as an unsigned 32-bit integer. This number can be compared against other stamps generated with version_for.
123 124 125 126 127 128 129 |
# File 'lib/rnp/misc.rb', line 123 def self.version(str = nil) if str.nil? LibRnp.rnp_version else LibRnp.rnp_version_for(*str.split('.').map(&:to_i)) end end |
.version_for(major, minor, patch) ⇒ Integer
Encode the given major, minor, and patch numbers into a version stamp.
135 136 137 |
# File 'lib/rnp/misc.rb', line 135 def self.version_for(major, minor, patch) LibRnp.rnp_version_for(major, minor, patch) end |
.version_major(version) ⇒ Integer
Extract the major version component from the given version stamp.
142 143 144 |
# File 'lib/rnp/misc.rb', line 142 def self.version_major(version) LibRnp.rnp_version_major(version) end |
.version_minor(version) ⇒ Integer
Extract the minor version component from the given version stamp.
149 150 151 |
# File 'lib/rnp/misc.rb', line 149 def self.version_minor(version) LibRnp.rnp_version_minor(version) end |
.version_patch(version) ⇒ Integer
Extract the patch version component from the given version stamp.
156 157 158 |
# File 'lib/rnp/misc.rb', line 156 def self.version_patch(version) LibRnp.rnp_version_patch(version) end |
.version_string ⇒ String
Get the version of the rnp library as a string.
107 108 109 |
# File 'lib/rnp/misc.rb', line 107 def self.version_string LibRnp.rnp_version_string end |
.version_string_full ⇒ String
Get the detailed version of the rnp library as a string.
114 115 116 |
# File 'lib/rnp/misc.rb', line 114 def self.version_string_full LibRnp.rnp_version_string_full end |
Instance Method Details
#cleartext_sign(input:, output: nil, signers:, compression: nil, creation_time: nil, expiration_time: nil, hash: nil) ⇒ nil, String
Create a cleartext signature.
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
# File 'lib/rnp/rnp.rb', line 369 def cleartext_sign(input:, output: nil, signers:, compression: nil, creation_time: nil, expiration_time: nil, hash: nil) Output.default(output) do |output_| sign = start_cleartext_sign(input: input, output: output_) sign. = { compression: compression, creation_time: creation_time, expiration_time: expiration_time, hash: hash } simple_sign(sign, signers) end end |
#decrypt(input:, output: nil) ⇒ nil, String
Decrypt encrypted data.
544 545 546 547 548 |
# File 'lib/rnp/rnp.rb', line 544 def decrypt(input:, output: nil) Output.default(output) do |output_| Rnp.call_ffi(:rnp_decrypt, @ptr, input.ptr, output_.ptr) end end |
#detached_sign(input:, output: nil, signers:, armored: nil, compression: nil, creation_time: nil, expiration_time: nil, hash: nil) ⇒ nil, String
Create a detached signature.
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 |
# File 'lib/rnp/rnp.rb', line 397 def detached_sign(input:, output: nil, signers:, armored: nil, compression: nil, creation_time: nil, expiration_time: nil, hash: nil) Output.default(output) do |output_| sign = start_detached_sign(input: input, output: output_) sign. = { armored: armored, compression: compression, creation_time: creation_time, expiration_time: expiration_time, hash: hash } simple_sign(sign, signers) end end |
#detached_verify(data:, signature:) ⇒ Object
Verify a detached signature.
429 430 431 432 |
# File 'lib/rnp/rnp.rb', line 429 def detached_verify(data:, signature:) verify = start_detached_verify(data: data, signature: signature) verify.execute end |
#each_fingerprint(&block) ⇒ self, Enumerator
Enumerate all fingerprints.
|
# File 'lib/rnp/rnp.rb', line 291
|
#each_grip(&block) ⇒ self, Enumerator
Enumerate all grips.
306 307 308 309 310 311 312 313 314 |
# File 'lib/rnp/rnp.rb', line 306 %w[userid keyid fingerprint grip].each do |identifier_type| define_method("each_#{identifier_type}".to_sym) do |&block| each_identifier(identifier_type, &block) end define_method("#{identifier_type}s".to_sym) do each_identifier(identifier_type).to_a end end |
#each_keyid(&block) ⇒ self, Enumerator
Enumerate all keyids.
|
# File 'lib/rnp/rnp.rb', line 281
|
#each_userid(&block) ⇒ self, Enumerator
Enumerate all userids.
|
# File 'lib/rnp/rnp.rb', line 271
|
#encrypt(input:, output: nil, recipients:, armored: nil, compression: nil, cipher: nil, aead: nil) ⇒ Object
Encrypt data with a public key.
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 |
# File 'lib/rnp/rnp.rb', line 444 def encrypt(input:, output: nil, recipients:, armored: nil, compression: nil, cipher: nil, aead: nil) Output.default(output) do |output_| enc = start_encrypt(input: input, output: output_) enc. = { armored: armored, compression: compression, cipher: cipher, aead: aead, } simple_encrypt(enc, recipients: recipients) end end |
#encrypt_and_sign(input:, output: nil, recipients:, signers:, armored: nil, compression: nil, cipher: nil, aead: nil, hash: nil, creation_time: nil, expiration_time: nil) ⇒ Object
Encrypt and sign data with a public key.
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 |
# File 'lib/rnp/rnp.rb', line 474 def encrypt_and_sign(input:, output: nil, recipients:, signers:, armored: nil, compression: nil, cipher: nil, aead: nil, hash: nil, creation_time: nil, expiration_time: nil) Output.default(output) do |output_| enc = start_encrypt(input: input, output: output_) enc. = { armored: armored, compression: compression, cipher: cipher, aead: aead, hash: hash, creation_time: creation_time, expiration_time: expiration_time } simple_encrypt(enc, recipients: recipients, signers: signers) end end |
#find_key(criteria) ⇒ Key?
Find a key.
256 257 258 259 260 261 262 263 264 |
# File 'lib/rnp/rnp.rb', line 256 def find_key(criteria) raise Rnp::Error, 'Invalid search criteria' if !criteria.is_a?(::Hash) || criteria.size != 1 pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_locate_key, @ptr, criteria.keys[0].to_s, criteria.values[0], pptr) pkey = pptr.read_pointer Rnp::Key.new(pkey) unless pkey.null? end |
#fingerprints ⇒ Array<String>
Get a list of all fingerprints.
|
# File 'lib/rnp/rnp.rb', line 286
|
#generate(type:, userid:, bits:, curve: nil, password:, subtype: nil, subbits: 0, subcurve: nil) ⇒ Object
Generate a key and optional subkey.
206 207 208 209 210 211 212 213 |
# File 'lib/rnp/rnp.rb', line 206 def generate(type:, userid:, bits:, curve: nil, password:, subtype: nil, subbits: 0, subcurve: nil) pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_generate_key_ex, @ptr, type, subtype, bits, subbits, curve, subcurve, userid, password, pptr) pkey = pptr.read_pointer Key.new(pkey) unless pkey.null? end |
#generate_dsa_elgamal(userid:, bits:, subbits: 0, password:) ⇒ Object
Generate a DSA (w/optional ElGamal subkey) key.
156 157 158 159 160 161 162 |
# File 'lib/rnp/rnp.rb', line 156 def generate_dsa_elgamal(userid:, bits:, subbits: 0, password:) pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_generate_key_dsa_eg, @ptr, bits, subbits, userid, password, pptr) pkey = pptr.read_pointer Key.new(pkey) unless pkey.null? end |
#generate_ecdsa_ecdh(userid:, curve:, password:) ⇒ Object
Generate an ECDSA+ECDH key pair.
170 171 172 173 174 175 |
# File 'lib/rnp/rnp.rb', line 170 def generate_ecdsa_ecdh(userid:, curve:, password:) pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_generate_key_ec, @ptr, curve, userid, password, pptr) pkey = pptr.read_pointer Key.new(pkey) unless pkey.null? end |
#generate_eddsa_25519(userid:, password:) ⇒ Object
Generate an EdDSA+x25519 key pair.
182 183 184 185 186 187 |
# File 'lib/rnp/rnp.rb', line 182 def generate_eddsa_25519(userid:, password:) pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_generate_key_25519, @ptr, userid, password, pptr) pkey = pptr.read_pointer Key.new(pkey) unless pkey.null? end |
#generate_key(description) ⇒ Hash<Symbol, Key>
The generated key(s) will be unprotected and unlocked. The application should protect and lock the keys with Rnp::Key#protect and Rnp::Key#lock.
Generate a new key or pair of keys.
Examples
examples/key_generation.rb
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/rnp/rnp.rb', line 113 def generate_key(description) description = JSON.generate(description) unless description.is_a?(String) pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_generate_key_json, @ptr, description, pptr) begin presults = pptr.read_pointer return nil if presults.null? results = JSON.parse(presults.read_string) generated = {} results.each do |k, v| key = find_key(v.keys[0].to_sym => v.values[0]) generated[k.to_sym] = key end generated ensure LibRnp.rnp_buffer_destroy(presults) end end |
#generate_rsa(userid:, bits:, subbits: 0, password:) ⇒ Object
Generate an RSA key (w/optional subkey).
140 141 142 143 144 145 146 |
# File 'lib/rnp/rnp.rb', line 140 def generate_rsa(userid:, bits:, subbits: 0, password:) pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_generate_key_rsa, @ptr, bits, subbits, userid, password, pptr) pkey = pptr.read_pointer Key.new(pkey) unless pkey.null? end |
#generate_sm2(userid:, password:) ⇒ Object
Generate an SM2 key pair.
194 195 196 197 198 199 |
# File 'lib/rnp/rnp.rb', line 194 def generate_sm2(userid:, password:) pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_generate_key_sm2, @ptr, userid, password, pptr) pkey = pptr.read_pointer Key.new(pkey) unless pkey.null? end |
#grips ⇒ Array<String>
Get a list of all grips.
|
# File 'lib/rnp/rnp.rb', line 296
|
#import_keys(input:, public_keys: true, secret_keys: true) ⇒ Hash
Import keys
632 633 634 635 636 637 638 639 640 641 642 643 644 |
# File 'lib/rnp/rnp.rb', line 632 def import_keys(input:, public_keys: true, secret_keys: true) flags = 0 flags |= LibRnp::RNP_LOAD_SAVE_PUBLIC_KEYS if public_keys flags |= LibRnp::RNP_LOAD_SAVE_SECRET_KEYS if secret_keys pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_import_keys, @ptr, input.ptr, flags, pptr) begin presults = pptr.read_pointer JSON.parse(presults.read_string) unless pptr.null? ensure LibRnp.rnp_buffer_destroy(presults) end end |
#import_signatures(input:) ⇒ Hash
Import signatures
650 651 652 653 654 655 656 657 658 659 |
# File 'lib/rnp/rnp.rb', line 650 def import_signatures(input:) pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_import_signatures, @ptr, input.ptr, 0, pptr) begin presults = pptr.read_pointer JSON.parse(presults.read_string) unless pptr.null? ensure LibRnp.rnp_buffer_destroy(presults) end end |
#inspect ⇒ Object
41 42 43 |
# File 'lib/rnp/rnp.rb', line 41 def inspect Rnp.inspect_ptr(self) end |
#key_provider=(provider) ⇒ Object
Set a key provider.
The key provider is useful if, for example, you have a database of keys and you do not want to load all of them, and you don’t know which will be needed for a given operation.
The key provider will be called to request that a key be loaded, and the key provider is responsible for loading the appropriate key (if available) using #load_keys.
The provider may be called multiple times for the same key, but with different identifiers. For example, it may first be called with a fingerprint, then (if the key was not loaded), it may be called with a keyid.
Examples
examples/key_provider.rb
74 75 76 77 78 |
# File 'lib/rnp/rnp.rb', line 74 def key_provider=(provider) @key_provider = provider @key_provider = KEY_PROVIDER.curry[provider] if provider Rnp.call_ffi(:rnp_ffi_set_key_provider, @ptr, @key_provider, nil) end |
#keyids ⇒ Array<String>
Get a list of all keyids.
|
# File 'lib/rnp/rnp.rb', line 276
|
#load_keys(input:, format:, public_keys: true, secret_keys: true) ⇒ void
This method returns an undefined value.
Load keys.
222 223 224 225 226 |
# File 'lib/rnp/rnp.rb', line 222 def load_keys(input:, format:, public_keys: true, secret_keys: true) raise ArgumentError, 'At least one of public_keys or secret_keys must be true' if !public_keys && !secret_keys flags = load_save_flags(public_keys: public_keys, secret_keys: secret_keys) Rnp.call_ffi(:rnp_load_keys, @ptr, format, input.ptr, flags) end |
#log=(fd) ⇒ Object
Set a logging destination.
49 50 51 52 |
# File 'lib/rnp/rnp.rb', line 49 def log=(fd) fd = fd.to_i if fd.is_a(::IO) Rnp.call_ffi(:rnp_ffi_set_log_fd, @ptr, fd) end |
#password_provider=(provider) ⇒ Object
Set a password provider.
The password provider is used for retrieving passwords for various operations, including:
-
Signing data
-
Decrypting data (public-key or symmetric)
-
Adding a userid to a key
-
Unlocking a key
-
Unprotecting a key
Examples
examples/password_provider.rb
95 96 97 98 99 |
# File 'lib/rnp/rnp.rb', line 95 def password_provider=(provider) @password_provider = provider @password_provider = PASS_PROVIDER.curry[provider] if provider Rnp.call_ffi(:rnp_ffi_set_pass_provider, @ptr, @password_provider, nil) end |
#public_key_count ⇒ Object
316 317 318 319 320 |
# File 'lib/rnp/rnp.rb', line 316 def public_key_count pcount = FFI::MemoryPointer.new(:size_t) Rnp.call_ffi(:rnp_get_public_key_count, @ptr, pcount) pcount.read(:size_t) end |
#save_keys(output:, format:, public_keys: false, secret_keys: false) ⇒ void
This method returns an undefined value.
Save keys.
242 243 244 245 246 |
# File 'lib/rnp/rnp.rb', line 242 def save_keys(output:, format:, public_keys: false, secret_keys: false) raise ArgumentError, 'At least one of public_keys or secret_keys must be true' if !public_keys && !secret_keys flags = load_save_flags(public_keys: public_keys, secret_keys: secret_keys) Rnp.call_ffi(:rnp_save_keys, @ptr, format, output.ptr, flags) end |
#secret_key_count ⇒ Object
322 323 324 325 326 |
# File 'lib/rnp/rnp.rb', line 322 def secret_key_count pcount = FFI::MemoryPointer.new(:size_t) Rnp.call_ffi(:rnp_get_secret_key_count, @ptr, pcount) pcount.read(:size_t) end |
#sign(input:, output: nil, signers:, armored: nil, compression: nil, creation_time: nil, expiration_time: nil, hash: nil) ⇒ nil, String
Create a signature.
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
# File 'lib/rnp/rnp.rb', line 340 def sign(input:, output: nil, signers:, armored: nil, compression: nil, creation_time: nil, expiration_time: nil, hash: nil) Output.default(output) do |output_| sign = start_sign(input: input, output: output_) sign. = { armored: armored, compression: compression, creation_time: creation_time, expiration_time: expiration_time, hash: hash } simple_sign(sign, signers) end end |
#start_cleartext_sign(input:, output:) ⇒ Object
Create a cleartext Sign operation.
586 587 588 |
# File 'lib/rnp/rnp.rb', line 586 def start_cleartext_sign(input:, output:) _start_sign(:rnp_op_sign_cleartext_create, input, output) end |
#start_detached_sign(input:, output:) ⇒ Object
Create a detached Sign operation.
594 595 596 |
# File 'lib/rnp/rnp.rb', line 594 def start_detached_sign(input:, output:) _start_sign(:rnp_op_sign_detached_create, input, output) end |
#start_detached_verify(data:, signature:) ⇒ Object
Create a detached Verify operation.
611 612 613 |
# File 'lib/rnp/rnp.rb', line 611 def start_detached_verify(data:, signature:) _start_verify(:rnp_op_verify_detached_create, data, signature) end |
#start_encrypt(input:, output:) ⇒ Object
Create an Encrypt operation.
619 620 621 622 623 624 |
# File 'lib/rnp/rnp.rb', line 619 def start_encrypt(input:, output:) pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_op_encrypt_create, pptr, @ptr, input.ptr, output.ptr) pencrypt = pptr.read_pointer Encrypt.new(pencrypt) unless pencrypt.null? end |
#start_generate(type:) ⇒ Generate
Start a Generate operation.
554 555 556 557 558 559 |
# File 'lib/rnp/rnp.rb', line 554 def start_generate(type:) pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_op_generate_create, pptr, @ptr, type.to_s) pgen = pptr.read_pointer Generate.new(pgen) unless pgen.null? end |
#start_generate_subkey(primary:, type:) ⇒ Generate
Start a Generate operation.
566 567 568 569 570 571 572 |
# File 'lib/rnp/rnp.rb', line 566 def start_generate_subkey(primary:, type:) pptr = FFI::MemoryPointer.new(:pointer) Rnp.call_ffi(:rnp_op_generate_subkey_create, pptr, @ptr, primary.ptr, type.to_s) pgen = pptr.read_pointer Generate.new(pgen) unless pgen.null? end |
#start_sign(input:, output:) ⇒ Object
Create a Sign operation.
578 579 580 |
# File 'lib/rnp/rnp.rb', line 578 def start_sign(input:, output:) _start_sign(:rnp_op_sign_create, input, output) end |
#start_verify(input:, output: nil) ⇒ Object
Create a Verify operation.
602 603 604 605 |
# File 'lib/rnp/rnp.rb', line 602 def start_verify(input:, output: nil) output = Output.to_null unless output _start_verify(:rnp_op_verify_create, input, output) end |
#symmetric_encrypt(input:, output: nil, passwords:, armored: nil, compression: nil, cipher: nil, aead: nil, s2k_hash: nil, s2k_iterations: 0, s2k_cipher: nil) ⇒ void
This method returns an undefined value.
Encrypt with a password only.
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 |
# File 'lib/rnp/rnp.rb', line 511 def symmetric_encrypt(input:, output: nil, passwords:, armored: nil, compression: nil, cipher: nil, aead: nil, s2k_hash: nil, s2k_iterations: 0, s2k_cipher: nil) Output.default(output) do |output_| enc = start_encrypt(input: input, output: output_) enc. = { armored: armored, compression: compression, cipher: cipher, aead: aead, } passwords = [passwords] if passwords.is_a?(String) passwords.each do |password| enc.add_password(password, s2k_hash: s2k_hash, s2k_iterations: s2k_iterations, s2k_cipher: s2k_cipher) end enc.execute end end |
#unload_keys(public_keys: true, secret_keys: true) ⇒ Object
228 229 230 231 232 233 |
# File 'lib/rnp/rnp.rb', line 228 def unload_keys(public_keys: true, secret_keys: true) raise ArgumentError, "At least one of public_keys or secret_keys must be true" \ if !public_keys && !secret_keys flags = unload_keys_flags(public_keys: public_keys, secret_keys: secret_keys) Rnp.call_ffi(:rnp_unload_keys, @ptr, flags) end |
#userids ⇒ Array<String>
Get a list of all userids.
|
# File 'lib/rnp/rnp.rb', line 266
|
#verify(input:, output: nil) ⇒ Object
Verify a signature.
420 421 422 423 |
# File 'lib/rnp/rnp.rb', line 420 def verify(input:, output: nil) verify = start_verify(input: input, output: output) verify.execute end |