botan 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +219 -0
- data/lib/botan.rb +25 -0
- data/lib/botan/bcrypt.rb +49 -0
- data/lib/botan/cipher.rb +214 -0
- data/lib/botan/defaults.rb +21 -0
- data/lib/botan/digest.rb +145 -0
- data/lib/botan/error.rb +8 -0
- data/lib/botan/ffi/libbotan.rb +573 -0
- data/lib/botan/kdf.rb +87 -0
- data/lib/botan/mac.rb +90 -0
- data/lib/botan/pk/mceies.rb +62 -0
- data/lib/botan/pk/op/decrypt.rb +59 -0
- data/lib/botan/pk/op/encrypt.rb +62 -0
- data/lib/botan/pk/op/keyagreement.rb +59 -0
- data/lib/botan/pk/op/sign.rb +68 -0
- data/lib/botan/pk/op/verify.rb +71 -0
- data/lib/botan/pk/privatekey.rb +288 -0
- data/lib/botan/pk/publickey.rb +161 -0
- data/lib/botan/rng.rb +62 -0
- data/lib/botan/utils.rb +104 -0
- data/lib/botan/version.rb +8 -0
- data/lib/botan/x509/certificate.rb +139 -0
- data/lib/botan/x509/constraints.rb +20 -0
- metadata +197 -0
data/lib/botan/kdf.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# (c) 2017 Ribose Inc.
|
4
|
+
|
5
|
+
require 'ffi'
|
6
|
+
|
7
|
+
require 'botan/defaults'
|
8
|
+
require 'botan/utils'
|
9
|
+
|
10
|
+
module Botan
|
11
|
+
# Key Derivation Functions
|
12
|
+
#
|
13
|
+
# == Examples
|
14
|
+
# === examples/kdf.rb
|
15
|
+
# {include:file:examples/kdf.rb}
|
16
|
+
module KDF
|
17
|
+
# Derives a key using the given KDF algorithm.
|
18
|
+
#
|
19
|
+
# @param secret [String] the secret input
|
20
|
+
# @param key_length [Integer] the desired length of the key to produce
|
21
|
+
# @param label [String] purpose for the derived keying material
|
22
|
+
# @param algo [String] the KDF algorithm name
|
23
|
+
# @param salt [String] the randomly chosen salt
|
24
|
+
# @return [String] the derived key
|
25
|
+
def self.kdf(secret:, key_length:,
|
26
|
+
label: '',
|
27
|
+
algo: DEFAULT_KDF_ALGO,
|
28
|
+
salt: RNG.get(DEFAULT_KDF_SALT_LENGTH))
|
29
|
+
out_buf = FFI::MemoryPointer.new(:uint8, key_length)
|
30
|
+
|
31
|
+
secret_buf = FFI::MemoryPointer.from_data(secret)
|
32
|
+
salt_buf = FFI::MemoryPointer.from_data(salt)
|
33
|
+
label_buf = FFI::MemoryPointer.from_data(label)
|
34
|
+
Botan.call_ffi(:botan_kdf,
|
35
|
+
algo, out_buf, out_buf.size,
|
36
|
+
secret_buf, secret_buf.size,
|
37
|
+
salt_buf, salt_buf.size,
|
38
|
+
label_buf, label_buf.size)
|
39
|
+
out_buf.read_bytes(key_length)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Derives a key using the given PBKDF algorithm.
|
43
|
+
#
|
44
|
+
# @param password [String] the password to derive the key from
|
45
|
+
# @param key_length [Integer] the desired length of the key to produce
|
46
|
+
# @param algo [String] the PBKDF algorithm name
|
47
|
+
# @param iterations [Integer] the number of iterations to use
|
48
|
+
# @param salt [String] the randomly chosen salt
|
49
|
+
# @return [String] the derived key
|
50
|
+
def self.pbkdf(password:, key_length:,
|
51
|
+
algo: DEFAULT_PBKDF_ALGO,
|
52
|
+
iterations: DEFAULT_KDF_ITERATIONS,
|
53
|
+
salt: RNG.get(DEFAULT_KDF_SALT_LENGTH))
|
54
|
+
out_buf = FFI::MemoryPointer.new(:uint8, key_length)
|
55
|
+
salt_buf = FFI::MemoryPointer.from_data(salt)
|
56
|
+
Botan.call_ffi(:botan_pbkdf,
|
57
|
+
algo, out_buf, key_length,
|
58
|
+
password, salt_buf, salt_buf.size, iterations)
|
59
|
+
out_buf.read_bytes(key_length)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Derives a key using the given PBKDF algorithm.
|
63
|
+
#
|
64
|
+
# @param password [String] the password to derive the key from
|
65
|
+
# @param key_length [Integer] teh desired length of the key to rpoduce
|
66
|
+
# @param milliseconds [Integer] the number of milliseconds to run
|
67
|
+
# @param algo [String] the PBKDF algorithm name
|
68
|
+
# @param salt [String] the randomly chosen salt
|
69
|
+
# @return [Hash<Symbol>]
|
70
|
+
# * :iterations [Integer] the iteration count used
|
71
|
+
# * :key [String] the derived key
|
72
|
+
def self.pbkdf_timed(password:, key_length:, milliseconds:,
|
73
|
+
algo: DEFAULT_PBKDF_ALGO,
|
74
|
+
salt: RNG.get(DEFAULT_KDF_SALT_LENGTH))
|
75
|
+
out_buf = FFI::MemoryPointer.new(:uint8, key_length)
|
76
|
+
salt_buf = FFI::MemoryPointer.from_data(salt)
|
77
|
+
iterations_ptr = FFI::MemoryPointer.new(:size_t)
|
78
|
+
Botan.call_ffi(:botan_pbkdf_timed,
|
79
|
+
algo, out_buf, key_length,
|
80
|
+
password, salt_buf, salt_buf.size,
|
81
|
+
milliseconds, iterations_ptr)
|
82
|
+
{ iterations: iterations_ptr.read(:size_t),
|
83
|
+
key: out_buf.read_bytes(key_length) }
|
84
|
+
end
|
85
|
+
end # module
|
86
|
+
end # module
|
87
|
+
|
data/lib/botan/mac.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# (c) 2017 Ribose Inc.
|
4
|
+
|
5
|
+
require 'ffi'
|
6
|
+
|
7
|
+
require 'botan/error'
|
8
|
+
require 'botan/ffi/libbotan'
|
9
|
+
require 'botan/utils'
|
10
|
+
|
11
|
+
module Botan
|
12
|
+
# Message Authentication Code
|
13
|
+
#
|
14
|
+
# == Examples
|
15
|
+
# === examples/mac.rb
|
16
|
+
# {include:file:examples/mac.rb}
|
17
|
+
class MAC
|
18
|
+
# @param algo [String] the MAC algorithm name
|
19
|
+
def initialize(algo)
|
20
|
+
flags = 0
|
21
|
+
ptr = FFI::MemoryPointer.new(:pointer)
|
22
|
+
Botan.call_ffi(:botan_mac_init, ptr, algo, flags)
|
23
|
+
ptr = ptr.read_pointer
|
24
|
+
raise Botan::Error, 'botan_mac_init returned NULL' if ptr.null?
|
25
|
+
@ptr = FFI::AutoPointer.new(ptr, self.class.method(:destroy))
|
26
|
+
end
|
27
|
+
|
28
|
+
# @api private
|
29
|
+
def self.destroy(ptr)
|
30
|
+
LibBotan.botan_mac_destroy(ptr)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Resets the instace back to a clean state, as if no key and
|
34
|
+
# input have been supplied.
|
35
|
+
#
|
36
|
+
# @return [self]
|
37
|
+
def reset
|
38
|
+
Botan.call_ffi(:botan_mac_clear, @ptr)
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
# Retrieve the output length of the MAC.
|
43
|
+
#
|
44
|
+
# @return [Integer]
|
45
|
+
def output_length
|
46
|
+
length_ptr = FFI::MemoryPointer.new(:size_t)
|
47
|
+
Botan.call_ffi(:botan_mac_output_length, @ptr, length_ptr)
|
48
|
+
length_ptr.read(:size_t)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Sets the key for the MAC.
|
52
|
+
# This must be called before {#update}.
|
53
|
+
#
|
54
|
+
# @param [String] key
|
55
|
+
def key=(key)
|
56
|
+
Botan.call_ffi(:botan_mac_set_key, @ptr, key, key.bytesize)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Adds input to the MAC computation.
|
60
|
+
#
|
61
|
+
# @param [String] data
|
62
|
+
# @return [self]
|
63
|
+
def update(data)
|
64
|
+
Botan.call_ffi(:botan_mac_update, @ptr, data, data.bytesize)
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def digest
|
69
|
+
out_buf = FFI::MemoryPointer.new(:uint8, output_length)
|
70
|
+
Botan.call_ffi(:botan_mac_final, @ptr, out_buf)
|
71
|
+
out_buf.read_bytes(out_buf.size)
|
72
|
+
end
|
73
|
+
|
74
|
+
def hexdigest
|
75
|
+
Botan.hex_encode(digest)
|
76
|
+
end
|
77
|
+
|
78
|
+
def inspect
|
79
|
+
Botan.inspect_ptr(self)
|
80
|
+
end
|
81
|
+
|
82
|
+
alias << update
|
83
|
+
|
84
|
+
# TODO: it's not safe to do this at the moment, since these
|
85
|
+
# methods mutate the state.
|
86
|
+
# alias inspect hexdigest
|
87
|
+
# alias to_s hexdigest
|
88
|
+
end # class
|
89
|
+
end # module
|
90
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# (c) 2017 Ribose Inc.
|
4
|
+
|
5
|
+
require 'ffi'
|
6
|
+
|
7
|
+
require 'botan/ffi/libbotan'
|
8
|
+
require 'botan/utils'
|
9
|
+
|
10
|
+
module Botan
|
11
|
+
module PK
|
12
|
+
# Encrypts with McEliece.
|
13
|
+
#
|
14
|
+
# @param public_key [Botan::PK::PublicKey] the public key
|
15
|
+
# @param plaintext [String] the data to encrypt
|
16
|
+
# @param ad [String] the associated data
|
17
|
+
# @param aead [String] the (AEAD) cipher+mode
|
18
|
+
# @param rng [Botan::RNG] the RNG to use
|
19
|
+
# @return [String] the encrypted data
|
20
|
+
def self.mceies_encrypt(public_key:, plaintext:, ad:,
|
21
|
+
aead: DEFAULT_AEAD,
|
22
|
+
rng: Botan::RNG.new)
|
23
|
+
pt_buf = FFI::MemoryPointer.from_data(plaintext)
|
24
|
+
ad_buf = FFI::MemoryPointer.from_data(ad)
|
25
|
+
Botan.call_ffi_with_buffer(lambda { |b, bl|
|
26
|
+
LibBotan.botan_mceies_encrypt(public_key.ptr,
|
27
|
+
rng.ptr,
|
28
|
+
aead,
|
29
|
+
pt_buf,
|
30
|
+
pt_buf.size,
|
31
|
+
ad_buf,
|
32
|
+
ad_buf.size,
|
33
|
+
b,
|
34
|
+
bl)
|
35
|
+
})
|
36
|
+
end
|
37
|
+
|
38
|
+
# Decrypts with McEliece.
|
39
|
+
#
|
40
|
+
# @param private_key [Botan::PK::PrivateKey] the private key
|
41
|
+
# @param ciphertext [String] the data to decrypt
|
42
|
+
# @param ad [String] the associated data
|
43
|
+
# @param aead [String] the (AEAD) cipher+mode
|
44
|
+
# @return [String] the decrypted data
|
45
|
+
def self.mceies_decrypt(private_key:, ciphertext:, ad:,
|
46
|
+
aead: DEFAULT_AEAD)
|
47
|
+
ct_buf = FFI::MemoryPointer.from_data(ciphertext)
|
48
|
+
ad_buf = FFI::MemoryPointer.from_data(ad)
|
49
|
+
Botan.call_ffi_with_buffer(lambda { |b, bl|
|
50
|
+
LibBotan.botan_mceies_decrypt(private_key.ptr,
|
51
|
+
aead,
|
52
|
+
ct_buf,
|
53
|
+
ct_buf.size,
|
54
|
+
ad_buf,
|
55
|
+
ad.size,
|
56
|
+
b,
|
57
|
+
bl)
|
58
|
+
})
|
59
|
+
end
|
60
|
+
end # module
|
61
|
+
end # module
|
62
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# (c) 2017 Ribose Inc.
|
4
|
+
|
5
|
+
require 'ffi'
|
6
|
+
|
7
|
+
require 'botan/defaults'
|
8
|
+
require 'botan/error'
|
9
|
+
require 'botan/ffi/libbotan'
|
10
|
+
require 'botan/pk/privatekey'
|
11
|
+
require 'botan/utils'
|
12
|
+
|
13
|
+
module Botan
|
14
|
+
module PK
|
15
|
+
# Public Key Decrypt Operation
|
16
|
+
#
|
17
|
+
# See {Botan::PK::PrivateKey#decrypt} for a simpler interface.
|
18
|
+
class Decrypt
|
19
|
+
# @param key [Botan::PK::PrivateKey] the private key
|
20
|
+
# @param padding [String] the padding method name
|
21
|
+
def initialize(key:, padding: nil)
|
22
|
+
padding ||= Botan::DEFAULT_EME
|
23
|
+
unless key.instance_of?(PrivateKey)
|
24
|
+
raise Botan::Error, 'Decryption requires an instance of PrivateKey'
|
25
|
+
end
|
26
|
+
ptr = FFI::MemoryPointer.new(:pointer)
|
27
|
+
flags = 0
|
28
|
+
Botan.call_ffi(:botan_pk_op_decrypt_create,
|
29
|
+
ptr, key.ptr, padding, flags)
|
30
|
+
ptr = ptr.read_pointer
|
31
|
+
if ptr.null?
|
32
|
+
raise Botan::Error, 'botan_pk_op_decrypt_create returned NULL'
|
33
|
+
end
|
34
|
+
@ptr = FFI::AutoPointer.new(ptr, self.class.method(:destroy))
|
35
|
+
end
|
36
|
+
|
37
|
+
# @api private
|
38
|
+
def self.destroy(ptr)
|
39
|
+
LibBotan.botan_pk_op_decrypt_destroy(ptr)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Decrypts the provided data.
|
43
|
+
#
|
44
|
+
# @param msg [String] the data
|
45
|
+
# @return [String] the decrypted data
|
46
|
+
def decrypt(msg)
|
47
|
+
msg_buf = FFI::MemoryPointer.from_data(msg)
|
48
|
+
Botan.call_ffi_with_buffer(lambda { |b, bl|
|
49
|
+
LibBotan.botan_pk_op_decrypt(@ptr, b, bl, msg_buf, msg_buf.size)
|
50
|
+
})
|
51
|
+
end
|
52
|
+
|
53
|
+
def inspect
|
54
|
+
Botan.inspect_ptr(self)
|
55
|
+
end
|
56
|
+
end # class
|
57
|
+
end # module
|
58
|
+
end # module
|
59
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# (c) 2017 Ribose Inc.
|
4
|
+
|
5
|
+
require 'ffi'
|
6
|
+
|
7
|
+
require 'botan/defaults'
|
8
|
+
require 'botan/error'
|
9
|
+
require 'botan/ffi/libbotan'
|
10
|
+
require 'botan/pk/publickey'
|
11
|
+
require 'botan/rng'
|
12
|
+
require 'botan/utils'
|
13
|
+
|
14
|
+
module Botan
|
15
|
+
module PK
|
16
|
+
# Public Key Encrypt Operation
|
17
|
+
#
|
18
|
+
# See {Botan::PK::PublicKey#encrypt} for a simpler interface.
|
19
|
+
class Encrypt
|
20
|
+
# @param key [Botan::PK::PublicKey] the public key
|
21
|
+
# @param padding [String] the padding method name
|
22
|
+
def initialize(key:, padding: nil)
|
23
|
+
padding ||= Botan::DEFAULT_EME
|
24
|
+
unless key.instance_of?(PublicKey)
|
25
|
+
raise Botan::Error, 'Encryption requires an instance of PublicKey'
|
26
|
+
end
|
27
|
+
ptr = FFI::MemoryPointer.new(:pointer)
|
28
|
+
flags = 0
|
29
|
+
Botan.call_ffi(:botan_pk_op_encrypt_create,
|
30
|
+
ptr, key.ptr, padding, flags)
|
31
|
+
ptr = ptr.read_pointer
|
32
|
+
if ptr.null?
|
33
|
+
raise Botan::Error, 'botan_pk_op_encrypt_create returned NULL'
|
34
|
+
end
|
35
|
+
@ptr = FFI::AutoPointer.new(ptr, self.class.method(:destroy))
|
36
|
+
end
|
37
|
+
|
38
|
+
# @api private
|
39
|
+
def self.destroy(ptr)
|
40
|
+
LibBotan.botan_pk_op_encrypt_destroy(ptr)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Encrypts the provided data.
|
44
|
+
#
|
45
|
+
# @param msg [String] the data
|
46
|
+
# @param rng [Botan::PK::RNG] the RNG to use
|
47
|
+
# @return [String] the encrypted data
|
48
|
+
def encrypt(msg, rng: Botan::RNG.new)
|
49
|
+
msg_buf = FFI::MemoryPointer.from_data(msg)
|
50
|
+
Botan.call_ffi_with_buffer(lambda { |b, bl|
|
51
|
+
LibBotan.botan_pk_op_encrypt(@ptr, rng.ptr, b, bl,
|
52
|
+
msg_buf, msg_buf.size)
|
53
|
+
})
|
54
|
+
end
|
55
|
+
|
56
|
+
def inspect
|
57
|
+
Botan.inspect_ptr(self)
|
58
|
+
end
|
59
|
+
end # class
|
60
|
+
end # module
|
61
|
+
end # module
|
62
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# (c) 2017 Ribose Inc.
|
4
|
+
|
5
|
+
require 'ffi'
|
6
|
+
|
7
|
+
require 'botan/defaults'
|
8
|
+
require 'botan/error'
|
9
|
+
require 'botan/ffi/libbotan'
|
10
|
+
require 'botan/pk/privatekey'
|
11
|
+
require 'botan/utils'
|
12
|
+
|
13
|
+
module Botan
|
14
|
+
module PK
|
15
|
+
# Public Key Key Agreement Operation
|
16
|
+
class KeyAgreement
|
17
|
+
attr_reader :public_value
|
18
|
+
# @param key [Botan::PK::PrivateKey] the private key
|
19
|
+
# @param kdf [String] the KDF algorithm name
|
20
|
+
def initialize(key:, kdf: Botan::DEFAULT_KDF_ALGO)
|
21
|
+
unless key.instance_of?(PrivateKey)
|
22
|
+
raise Botan::Error, 'KeyAgreement requires an instance of PrivateKey'
|
23
|
+
end
|
24
|
+
ptr = FFI::MemoryPointer.new(:pointer)
|
25
|
+
flags = 0
|
26
|
+
Botan.call_ffi(:botan_pk_op_key_agreement_create,
|
27
|
+
ptr, key.ptr, kdf, flags)
|
28
|
+
ptr = ptr.read_pointer
|
29
|
+
if ptr.null?
|
30
|
+
raise Botan::Error, 'botan_pk_op_key_agreement_create returned NULL'
|
31
|
+
end
|
32
|
+
@ptr = FFI::AutoPointer.new(ptr, self.class.method(:destroy))
|
33
|
+
@public_value = Botan.call_ffi_with_buffer(lambda { |b, bl|
|
34
|
+
LibBotan.botan_pk_op_key_agreement_export_public(key.ptr, b, bl)
|
35
|
+
})
|
36
|
+
end
|
37
|
+
|
38
|
+
# @api private
|
39
|
+
def self.destroy(ptr)
|
40
|
+
LibBotan.botan_pk_op_key_agreement_destroy(ptr)
|
41
|
+
end
|
42
|
+
|
43
|
+
def agree(other_key:, key_length:, salt:)
|
44
|
+
other_buf = FFI::MemoryPointer.from_data(other_key)
|
45
|
+
salt_buf = FFI::MemoryPointer.from_data(salt)
|
46
|
+
Botan.call_ffi_with_buffer(lambda { |b, bl|
|
47
|
+
LibBotan.botan_pk_op_key_agreement(@ptr, b, bl,
|
48
|
+
other_buf, other_buf.size,
|
49
|
+
salt_buf, salt_buf.size)
|
50
|
+
}, guess: key_length)
|
51
|
+
end
|
52
|
+
|
53
|
+
def inspect
|
54
|
+
Botan.inspect_ptr(self)
|
55
|
+
end
|
56
|
+
end # class
|
57
|
+
end # module
|
58
|
+
end # module
|
59
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# (c) 2017 Ribose Inc.
|
4
|
+
|
5
|
+
require 'ffi'
|
6
|
+
|
7
|
+
require 'botan/defaults'
|
8
|
+
require 'botan/error'
|
9
|
+
require 'botan/ffi/libbotan'
|
10
|
+
require 'botan/pk/privatekey'
|
11
|
+
require 'botan/rng'
|
12
|
+
require 'botan/utils'
|
13
|
+
|
14
|
+
module Botan
|
15
|
+
module PK
|
16
|
+
# Public Key Sign Operation
|
17
|
+
#
|
18
|
+
# See {Botan::PK::PrivateKey#sign} for a simpler interface.
|
19
|
+
class Sign
|
20
|
+
# @param key [Botan::PK::PrivateKey] the private key
|
21
|
+
# @param padding [String] the padding method name
|
22
|
+
def initialize(key:, padding: nil)
|
23
|
+
padding ||= Botan::DEFAULT_EMSA[key.algo]
|
24
|
+
unless key.instance_of?(PrivateKey)
|
25
|
+
raise Botan::Error, 'Signing requires an instance of PrivateKey'
|
26
|
+
end
|
27
|
+
ptr = FFI::MemoryPointer.new(:pointer)
|
28
|
+
flags = 0
|
29
|
+
Botan.call_ffi(:botan_pk_op_sign_create, ptr, key.ptr, padding, flags)
|
30
|
+
ptr = ptr.read_pointer
|
31
|
+
raise Botan::Error, 'botan_pk_op_sign_create returned NULL' if ptr.null?
|
32
|
+
@ptr = FFI::AutoPointer.new(ptr, self.class.method(:destroy))
|
33
|
+
end
|
34
|
+
|
35
|
+
# @api private
|
36
|
+
def self.destroy(ptr)
|
37
|
+
LibBotan.botan_pk_op_sign_destroy(ptr)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Adds data to the message currently being signed.
|
41
|
+
#
|
42
|
+
# @param msg [String] the data to add
|
43
|
+
# @return [self]
|
44
|
+
def update(msg)
|
45
|
+
msg_buf = FFI::MemoryPointer.from_data(msg)
|
46
|
+
Botan.call_ffi(:botan_pk_op_sign_update, @ptr, msg_buf, msg_buf.size)
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
# Finalizes the signature operation.
|
51
|
+
#
|
52
|
+
# @param rng [Botan::PK::RNG] the RNG to use
|
53
|
+
# @return [String] the signature
|
54
|
+
def finish(rng = Botan::RNG.new)
|
55
|
+
Botan.call_ffi_with_buffer(lambda { |b, bl|
|
56
|
+
LibBotan.botan_pk_op_sign_finish(@ptr, rng.ptr, b, bl)
|
57
|
+
})
|
58
|
+
end
|
59
|
+
|
60
|
+
def inspect
|
61
|
+
Botan.inspect_ptr(self)
|
62
|
+
end
|
63
|
+
|
64
|
+
alias << update
|
65
|
+
end # class
|
66
|
+
end # module
|
67
|
+
end # module
|
68
|
+
|