netpgp 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/netpgp.rb +3 -0
- data/lib/netpgp/highlevel.rb +5 -0
- data/lib/netpgp/highlevel/constants.rb +96 -0
- data/lib/netpgp/highlevel/keyring.rb +259 -0
- data/lib/netpgp/highlevel/publickey.rb +150 -0
- data/lib/netpgp/highlevel/secretkey.rb +318 -0
- data/lib/netpgp/highlevel/utils.rb +119 -0
- data/lib/netpgp/lowlevel.rb +6 -0
- data/lib/netpgp/lowlevel/constants.rb +11 -0
- data/lib/netpgp/lowlevel/dynarray.rb +129 -0
- data/lib/netpgp/lowlevel/enums.rb +243 -0
- data/lib/netpgp/lowlevel/libc.rb +28 -0
- data/lib/netpgp/lowlevel/libnetpgp.rb +213 -0
- data/lib/netpgp/lowlevel/libopenssl.rb +15 -0
- data/lib/netpgp/lowlevel/structs.rb +541 -0
- data/lib/netpgp/lowlevel/utils.rb +25 -0
- metadata +88 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: baa8e73adf9e05b9b6fb5be2b2a9447ce72149f3
|
4
|
+
data.tar.gz: 66db535e3a79f188424cfd237381dbad0fe81e71
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a17b99842d2b900e2babd24fa8c5f0e80059935b4b627f0c7971f03ad36bd791833f35b243d454fe851509845bc3e1cb6a9421735436233267db7718250bbb7b
|
7
|
+
data.tar.gz: dfb73d76203ac990bbb3605783b83eb7c47333d02e64712813965fe335092d53ecef24aee35dbf2839060fca5b09bdd6d7f71c0c2eaa20556636be7ab98d5dfd
|
data/lib/netpgp.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
module NetPGP
|
4
|
+
|
5
|
+
class PublicKeyAlgorithm
|
6
|
+
NONE = 0
|
7
|
+
RSA = 1
|
8
|
+
RSA_ENCRYPT_ONLY = 2
|
9
|
+
RSA_SIGN_ONLY = 3
|
10
|
+
ELGAMAL = 16
|
11
|
+
DSA = 17
|
12
|
+
ECDH = 18
|
13
|
+
ECDSA = 19
|
14
|
+
FORMERLY_ELGAMAL = 20
|
15
|
+
|
16
|
+
def self.from_native(alg)
|
17
|
+
raise if alg.class != Symbol
|
18
|
+
LibNetPGP::PGP_PUBKEY_ALG_T[alg]
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.to_native(alg)
|
22
|
+
# avoid a warning on newer versions of ruby
|
23
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.4.0')
|
24
|
+
raise if alg.class != Integer
|
25
|
+
else
|
26
|
+
raise if alg.class != Fixnum
|
27
|
+
end
|
28
|
+
LibNetPGP::PGP_PUBKEY_ALG_T[alg]
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
class HashAlgorithm
|
34
|
+
MD5 = 1
|
35
|
+
SHA1 = 2
|
36
|
+
RIPEMD = 3
|
37
|
+
SHA256 = 8
|
38
|
+
SHA384 = 9
|
39
|
+
SHA512 = 10
|
40
|
+
SHA224 = 11
|
41
|
+
|
42
|
+
# see pgp_str_to_hash_alg
|
43
|
+
STRING_MAPPING = {
|
44
|
+
MD5 => 'md5',
|
45
|
+
SHA1 => 'sha1',
|
46
|
+
SHA256 => 'sha256',
|
47
|
+
SHA384 => 'sha384',
|
48
|
+
SHA512 => 'sha512'
|
49
|
+
}
|
50
|
+
|
51
|
+
def self.to_s(alg)
|
52
|
+
STRING_MAPPING[alg]
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
class SymmetricKeyAlgorithm
|
58
|
+
PLAINTEXT = 0
|
59
|
+
IDEA = 1
|
60
|
+
TRIPLEDES = 2
|
61
|
+
CAST5 = 3
|
62
|
+
BLOWFISH = 4
|
63
|
+
AES128 = 7
|
64
|
+
AES192 = 8
|
65
|
+
AES256 = 9
|
66
|
+
TWOFISH256 = 10
|
67
|
+
|
68
|
+
# see pgp_str_to_cipher
|
69
|
+
STRING_MAPPING = {
|
70
|
+
IDEA => 'idea',
|
71
|
+
TRIPLEDES => 'tripledes',
|
72
|
+
CAST5 => 'cast5',
|
73
|
+
AES128 => 'aes128',
|
74
|
+
AES256 => 'aes256'
|
75
|
+
}
|
76
|
+
|
77
|
+
def self.to_s(alg)
|
78
|
+
STRING_MAPPING[alg]
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
class StringToKeyUsage
|
84
|
+
NONE = 0
|
85
|
+
ENCRYPTED_AND_HASHED = 254
|
86
|
+
ENCRYPTED = 255
|
87
|
+
end
|
88
|
+
|
89
|
+
class StringToKeySpecifier
|
90
|
+
SIMPLE = 0
|
91
|
+
SALTED = 1
|
92
|
+
ITERATED_AND_SALTED = 3
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
@@ -0,0 +1,259 @@
|
|
1
|
+
require 'English'
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
module NetPGP
|
5
|
+
|
6
|
+
class Keyring
|
7
|
+
extend Forwardable
|
8
|
+
delegate [:size, :each, :select, :[], :push, :clear] => :@keys
|
9
|
+
|
10
|
+
attr_reader :keys
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@keys = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.load(data, armored=true, &passphrase_provider)
|
17
|
+
kr = Keyring.new
|
18
|
+
kr.add(data, armored, &passphrase_provider)
|
19
|
+
kr
|
20
|
+
end
|
21
|
+
|
22
|
+
def add(data, armored=true, &passphrase_provider)
|
23
|
+
keys = NetPGP::load_keys(data, armored, &passphrase_provider)
|
24
|
+
@keys.push(*keys)
|
25
|
+
keys.size
|
26
|
+
end
|
27
|
+
|
28
|
+
def verify(data, armored=true)
|
29
|
+
NetPGP::verify(@keys, data, armored)
|
30
|
+
end
|
31
|
+
|
32
|
+
def export(key, armored=true)
|
33
|
+
raise if key.parent
|
34
|
+
is_public = key.is_a?(PublicKey)
|
35
|
+
if is_public
|
36
|
+
seckey = secret_keys.find {|sk| sk.key_id == key.key_id}
|
37
|
+
else
|
38
|
+
seckey = key
|
39
|
+
end
|
40
|
+
return nil if not seckey
|
41
|
+
output_ptr = FFI::MemoryPointer.new(:pointer)
|
42
|
+
mem_ptr = FFI::MemoryPointer.new(:pointer)
|
43
|
+
output = nil
|
44
|
+
mem = nil
|
45
|
+
decrypted_seckey = nil
|
46
|
+
begin
|
47
|
+
LibNetPGP::pgp_setup_memory_write(output_ptr, mem_ptr, 4096)
|
48
|
+
output = LibNetPGP::PGPOutput.new(output_ptr.read_pointer)
|
49
|
+
mem = LibNetPGP::PGPMemory.new(mem_ptr.read_pointer)
|
50
|
+
native_ptr = LibC::calloc(1, LibNetPGP::PGPKey.size)
|
51
|
+
native = LibNetPGP::PGPKey.new(native_ptr)
|
52
|
+
native_auto = FFI::AutoPointer.new(native_ptr, LibNetPGP::PGPKey.method(:release))
|
53
|
+
key.to_native_key(native)
|
54
|
+
decrypted_seckey = seckey.decrypted_seckey
|
55
|
+
return nil if not decrypted_seckey
|
56
|
+
# this is necessary for signatures
|
57
|
+
seckey = SecretKey.from_native(decrypted_seckey)
|
58
|
+
seckey.to_native(native[:key][:seckey])
|
59
|
+
native[:type] = :PGP_PTAG_CT_SECRET_KEY
|
60
|
+
if is_public
|
61
|
+
LibNetPGP::dynarray_clear(native, 'uid', :string)
|
62
|
+
key.userids.each {|userid|
|
63
|
+
LibNetPGP::pgp_add_selfsigned_userid(native, userid)
|
64
|
+
}
|
65
|
+
end
|
66
|
+
# PGPKeyring is a ManagedStruct
|
67
|
+
subkeysring_ptr = LibC::calloc(1, LibNetPGP::PGPKeyring.size)
|
68
|
+
subkeysring = LibNetPGP::PGPKeyring.new(subkeysring_ptr)
|
69
|
+
NetPGP::keys_to_native_keyring(key.subkeys, subkeysring)
|
70
|
+
# add a binding signature to each subkey
|
71
|
+
(0..LibNetPGP::dynarray_count(subkeysring, 'key') - 1).each {|n|
|
72
|
+
subkey = LibNetPGP::dynarray_get_item(subkeysring, 'key', LibNetPGP::PGPKey, n)
|
73
|
+
LibNetPGP::dynarray_clear(subkey, 'packet', LibNetPGP::PGPSubPacket)
|
74
|
+
NetPGP::add_subkey_signature(native, subkey)
|
75
|
+
}
|
76
|
+
if is_public
|
77
|
+
ret = LibNetPGP::pgp_write_xfer_pubkey(output, native, subkeysring, armored ? 1 : 0)
|
78
|
+
else
|
79
|
+
decrypted_key_ptr = LibC::calloc(1, LibNetPGP::PGPKey.size)
|
80
|
+
decrypted_key = LibNetPGP::PGPKey.new(decrypted_key_ptr)
|
81
|
+
decrypted_key_auto = FFI::AutoPointer.new(decrypted_key_ptr, LibNetPGP::PGPKey.method(:release))
|
82
|
+
seckey.to_native_key(decrypted_key)
|
83
|
+
key.userids.each {|userid|
|
84
|
+
LibNetPGP::pgp_add_selfsigned_userid(decrypted_key, userid)
|
85
|
+
}
|
86
|
+
decrypted_key[:key][:seckey][:s2k_usage] = :PGP_S2KU_ENCRYPTED_AND_HASHED
|
87
|
+
decrypted_key[:key][:seckey][:alg] = :PGP_SA_CAST5
|
88
|
+
decrypted_key[:key][:seckey][:s2k_specifier] = :PGP_S2KS_SALTED
|
89
|
+
(0..LibNetPGP::dynarray_count(subkeysring, 'key') - 1).each {|n|
|
90
|
+
subkey = LibNetPGP::dynarray_get_item(subkeysring, 'key', LibNetPGP::PGPKey, n)
|
91
|
+
subkey[:key][:seckey][:s2k_usage] = :PGP_S2KU_ENCRYPTED_AND_HASHED
|
92
|
+
subkey[:key][:seckey][:alg] = :PGP_SA_CAST5
|
93
|
+
subkey[:key][:seckey][:s2k_specifier] = :PGP_S2KS_SALTED
|
94
|
+
}
|
95
|
+
ret = LibNetPGP::pgp_write_xfer_seckey(output, decrypted_key, key.passphrase, key.passphrase.size, subkeysring, armored ? 1 : 0)
|
96
|
+
end
|
97
|
+
return nil if ret != 1
|
98
|
+
data = mem[:buf].read_bytes(mem[:length])
|
99
|
+
data
|
100
|
+
ensure
|
101
|
+
LibNetPGP::pgp_teardown_memory_write(output, mem) if mem
|
102
|
+
LibNetPGP::pgp_seckey_free(decrypted_seckey) if decrypted_seckey
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def public_keys
|
107
|
+
self.select {|key|
|
108
|
+
key.is_a?(PublicKey)
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
112
|
+
def secret_keys
|
113
|
+
self.select {|key|
|
114
|
+
key.is_a?(SecretKey)
|
115
|
+
}
|
116
|
+
end
|
117
|
+
|
118
|
+
def to_native(native)
|
119
|
+
keys_to_native_keyring(@keys, native)
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
PARSE_KEYRING = Proc.new do |state, passphrase_provider, pkt, data|
|
125
|
+
next :PGP_RELEASE_MEMORY if state[:errors].any?
|
126
|
+
|
127
|
+
begin
|
128
|
+
lastkey = state[:keys].last
|
129
|
+
case pkt[:tag]
|
130
|
+
when :PGP_PTAG_CT_PUBLIC_KEY
|
131
|
+
key = PublicKey::from_native(pkt[:u][:pubkey])
|
132
|
+
state[:keys].push(key)
|
133
|
+
when :PGP_PTAG_CT_PUBLIC_SUBKEY
|
134
|
+
key = PublicKey::from_native(pkt[:u][:pubkey])
|
135
|
+
lastkey.add_subkey(key)
|
136
|
+
state[:keys].push(key)
|
137
|
+
when :PGP_PTAG_CT_ENCRYPTED_SECRET_KEY
|
138
|
+
key = SecretKey::from_native(pkt[:u][:seckey], true)
|
139
|
+
state[:keys].push(key)
|
140
|
+
when :PGP_PTAG_CT_ENCRYPTED_SECRET_SUBKEY
|
141
|
+
key = SecretKey::from_native(pkt[:u][:seckey], true)
|
142
|
+
lastkey.add_subkey(key)
|
143
|
+
state[:keys].push(key)
|
144
|
+
when :PGP_PTAG_CT_SECRET_KEY
|
145
|
+
key = SecretKey::from_native(pkt[:u][:seckey])
|
146
|
+
if state[:passphrase]
|
147
|
+
key.passphrase = state[:passphrase]
|
148
|
+
state[:passphrase] = nil
|
149
|
+
end
|
150
|
+
state[:keys].push(key)
|
151
|
+
when :PGP_PTAG_CT_SECRET_SUBKEY
|
152
|
+
key = SecretKey::from_native(pkt[:u][:seckey])
|
153
|
+
lastkey.add_subkey(key)
|
154
|
+
state[:keys].push(key)
|
155
|
+
when :PGP_GET_PASSPHRASE
|
156
|
+
seckey_ptr = pkt[:u][:skey_passphrase][:seckey]
|
157
|
+
seckey = LibNetPGP::PGPSecKey.new(seckey_ptr)
|
158
|
+
key = SecretKey::from_native(seckey)
|
159
|
+
passphrase = passphrase_provider.call(key)
|
160
|
+
if passphrase and passphrase != ''
|
161
|
+
passphrase_mem = LibC::calloc(1, passphrase.bytesize + 1)
|
162
|
+
passphrase_mem.write_bytes(passphrase)
|
163
|
+
pkt[:u][:skey_passphrase][:passphrase].write_pointer(passphrase_mem)
|
164
|
+
state[:passphrase] = passphrase
|
165
|
+
next :PGP_KEEP_MEMORY
|
166
|
+
end
|
167
|
+
when :PGP_PARSER_PACKET_END
|
168
|
+
if lastkey.is_a? NetPGP::SecretKey
|
169
|
+
raw_packet = pkt[:u][:packet]
|
170
|
+
bytes = raw_packet[:raw].read_bytes(raw_packet[:length])
|
171
|
+
lastkey.raw_subpackets.push(bytes)
|
172
|
+
end
|
173
|
+
when :PGP_PTAG_CT_USER_ID
|
174
|
+
lastkey.userids.push(pkt[:u][:userid].force_encoding('utf-8'))
|
175
|
+
when :PGP_PTAG_SS_KEY_EXPIRY
|
176
|
+
lastkey.expiration_time = lastkey.creation_time + pkt[:u][:ss_time]
|
177
|
+
else
|
178
|
+
# For debugging
|
179
|
+
#puts "Unhandled tag: #{pkt[:tag]}"
|
180
|
+
end # case
|
181
|
+
rescue
|
182
|
+
state[:errors].push($ERROR_INFO)
|
183
|
+
end
|
184
|
+
next :PGP_RELEASE_MEMORY
|
185
|
+
end
|
186
|
+
|
187
|
+
DEFAULT_PASSPHRASE_PROVIDER = Proc.new do |seckey|
|
188
|
+
nil
|
189
|
+
end
|
190
|
+
|
191
|
+
def self.load_keys(data, armored=true, &passphrase_provider)
|
192
|
+
# Just for readability
|
193
|
+
print_errors = 0
|
194
|
+
stream_mem = LibC::calloc(1, LibNetPGP::PGPStream.size)
|
195
|
+
# This will free the above memory (PGPStream is a ManagedStruct)
|
196
|
+
stream = LibNetPGP::PGPStream.new(stream_mem)
|
197
|
+
stream[:readinfo][:accumulate] = 1
|
198
|
+
LibNetPGP::pgp_parse_options(stream, :PGP_PTAG_SS_ALL, :PGP_PARSE_PARSED)
|
199
|
+
|
200
|
+
# This memory will be GC'd
|
201
|
+
mem = FFI::MemoryPointer.new(:uint8, data.bytesize)
|
202
|
+
mem.write_bytes(data)
|
203
|
+
|
204
|
+
LibNetPGP::pgp_reader_set_memory(stream, mem, mem.size)
|
205
|
+
state = {keys: [], errors: []}
|
206
|
+
provider = block_given? ? passphrase_provider : DEFAULT_PASSPHRASE_PROVIDER
|
207
|
+
callback = NetPGP::PARSE_KEYRING.curry[state][provider]
|
208
|
+
LibNetPGP::pgp_set_callback(stream, callback, nil)
|
209
|
+
LibNetPGP::pgp_reader_push_dearmour(stream) if armored
|
210
|
+
if LibNetPGP::pgp_parse(stream, print_errors) != 1
|
211
|
+
state[:errors].push('pgp_parse failed')
|
212
|
+
end
|
213
|
+
LibNetPGP::pgp_reader_pop_dearmour(stream) if armored
|
214
|
+
|
215
|
+
errors = stream_errors(stream)
|
216
|
+
state[:errors].push(errors) if errors.any?
|
217
|
+
|
218
|
+
raise state[:errors].join("\n") if state[:errors].any?
|
219
|
+
state[:keys]
|
220
|
+
end
|
221
|
+
|
222
|
+
def self.keys_to_native_keyring(keys, native)
|
223
|
+
raise if not native[:keys].null?
|
224
|
+
|
225
|
+
for key in keys
|
226
|
+
native_key = LibNetPGP::PGPKey.new
|
227
|
+
key.to_native_key(native_key)
|
228
|
+
LibNetPGP::dynarray_append_item(native, 'key', LibNetPGP::PGPKey, native_key)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def self.verify(keys, data, armored=true)
|
233
|
+
native_keyring_ptr = LibC::calloc(1, LibNetPGP::PGPKeyring.size)
|
234
|
+
native_keyring = LibNetPGP::PGPKeyring.new(native_keyring_ptr)
|
235
|
+
NetPGP::keys_to_native_keyring(keys, native_keyring)
|
236
|
+
|
237
|
+
pgpio = LibNetPGP::PGPIO.new
|
238
|
+
pgpio[:outs] = LibC::fdopen($stdout.to_i, 'w')
|
239
|
+
pgpio[:errs] = LibC::fdopen($stderr.to_i, 'w')
|
240
|
+
pgpio[:res] = pgpio[:errs]
|
241
|
+
|
242
|
+
data_buf = FFI::MemoryPointer.new(:uint8, data.bytesize)
|
243
|
+
data_buf.write_bytes(data)
|
244
|
+
|
245
|
+
# pgp_validate_mem frees this
|
246
|
+
mem_ptr = LibC::calloc(1, LibNetPGP::PGPMemory.size)
|
247
|
+
mem = LibNetPGP::PGPMemory.new(mem_ptr)
|
248
|
+
LibNetPGP::pgp_memory_add(mem, data_buf, data_buf.size)
|
249
|
+
|
250
|
+
# ManagedStruct, this frees itself
|
251
|
+
result_ptr = LibC::calloc(1, LibNetPGP::PGPValidation.size)
|
252
|
+
result = LibNetPGP::PGPValidation.new(result_ptr)
|
253
|
+
|
254
|
+
ret = LibNetPGP::pgp_validate_mem(pgpio, result, mem, nil, armored ? 1 : 0, native_keyring)
|
255
|
+
ret == 1
|
256
|
+
end
|
257
|
+
|
258
|
+
end # module NetPGP
|
259
|
+
|
@@ -0,0 +1,150 @@
|
|
1
|
+
module NetPGP
|
2
|
+
|
3
|
+
require_relative 'utils'
|
4
|
+
|
5
|
+
class PublicKey
|
6
|
+
attr_accessor :version,
|
7
|
+
:creation_time,
|
8
|
+
:expiration_time,
|
9
|
+
:public_key_algorithm,
|
10
|
+
:mpi,
|
11
|
+
:userids,
|
12
|
+
:parent,
|
13
|
+
:subkeys
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@version = nil
|
17
|
+
@creation_time = nil
|
18
|
+
@expiration_time = 0
|
19
|
+
@public_key_algorithm = nil
|
20
|
+
@mpi = {}
|
21
|
+
@userids = []
|
22
|
+
@parent = nil
|
23
|
+
@subkeys = []
|
24
|
+
end
|
25
|
+
|
26
|
+
def fingerprint
|
27
|
+
fp = LibNetPGP::PGPFingerprint.new
|
28
|
+
native_pubkey_ptr = LibC::calloc(1, LibNetPGP::PGPPubKey.size)
|
29
|
+
native_pubkey = LibNetPGP::PGPPubKey.new(native_pubkey_ptr)
|
30
|
+
native_pubkey_auto = FFI::AutoPointer.new(native_pubkey_ptr, LibNetPGP::PGPPubKey.method(:release))
|
31
|
+
to_native(native_pubkey)
|
32
|
+
hash = @version == 3 ? :PGP_HASH_MD5 : :PGP_HASH_SHA1
|
33
|
+
ret = LibNetPGP::pgp_fingerprint(fp, native_pubkey, hash)
|
34
|
+
raise 'pgp_fingerprint failed' if ret != 1
|
35
|
+
fp[:fingerprint].to_s[0, fp[:length]]
|
36
|
+
end
|
37
|
+
|
38
|
+
def fingerprint_hex
|
39
|
+
fingerprint.bytes.collect {|byte| '%02X' % byte}.join
|
40
|
+
end
|
41
|
+
|
42
|
+
def key_id
|
43
|
+
keyid_ptr = FFI::MemoryPointer.new(:uint8, LibNetPGP::PGP_KEY_ID_SIZE)
|
44
|
+
native_pubkey = LibNetPGP::PGPPubKey.new
|
45
|
+
to_native(native_pubkey)
|
46
|
+
ret = LibNetPGP::pgp_keyid(keyid_ptr, LibNetPGP::PGP_KEY_ID_SIZE, native_pubkey, :PGP_HASH_SHA1)
|
47
|
+
raise 'pgp_keyid failed' if ret != 1
|
48
|
+
keyid_ptr.read_bytes(LibNetPGP::PGP_KEY_ID_SIZE)
|
49
|
+
end
|
50
|
+
|
51
|
+
def key_id_hex
|
52
|
+
key_id.bytes.collect {|byte| '%02X' % byte}.join
|
53
|
+
end
|
54
|
+
|
55
|
+
def key_length
|
56
|
+
case @public_key_algorithm
|
57
|
+
when PublicKeyAlgorithm::RSA,
|
58
|
+
PublicKeyAlgorithm::RSA_ENCRYPT_ONLY,
|
59
|
+
PublicKeyAlgorithm::RSA_SIGN_ONLY
|
60
|
+
return NetPGP::bignum_byte_count(@mpi[:n]) * 8
|
61
|
+
when PublicKeyAlgorithm::DSA
|
62
|
+
case NetPGP::bignum_byte_count(@mpi[:q])
|
63
|
+
when 20
|
64
|
+
1024
|
65
|
+
when 28
|
66
|
+
2048
|
67
|
+
when 32
|
68
|
+
3072
|
69
|
+
end
|
70
|
+
when PublicKeyAlgorithm::ELGAMAL
|
71
|
+
NetPGP::bignum_byte_count(@mpi[:y]) * 8
|
72
|
+
end
|
73
|
+
0
|
74
|
+
end
|
75
|
+
|
76
|
+
def encrypt(data, armored=true, sk_algorithm=SymmetricKeyAlgorithm::CAST5)
|
77
|
+
cipher = SymmetricKeyAlgorithm::to_s(sk_algorithm)
|
78
|
+
memory = nil
|
79
|
+
|
80
|
+
begin
|
81
|
+
pubkey_ptr = LibC::calloc(1, LibNetPGP::PGPKey.size)
|
82
|
+
pubkey = LibNetPGP::PGPKey.new(pubkey_ptr)
|
83
|
+
pubkey_auto = FFI::AutoPointer.new(pubkey_ptr, LibNetPGP::PGPKey.method(:release))
|
84
|
+
|
85
|
+
to_native_key(pubkey)
|
86
|
+
data_buf = FFI::MemoryPointer.new(:uint8, data.bytesize)
|
87
|
+
data_buf.write_bytes(data)
|
88
|
+
pgpio = LibNetPGP::PGPIO.new
|
89
|
+
pgpio[:outs] = LibC::fdopen($stdout.to_i, 'w')
|
90
|
+
pgpio[:errs] = LibC::fdopen($stderr.to_i, 'w')
|
91
|
+
pgpio[:res] = pgpio[:errs]
|
92
|
+
memory_ptr = LibNetPGP::pgp_encrypt_buf(pgpio, data_buf, data_buf.size, pubkey, armored ? 1 : 0, cipher)
|
93
|
+
return nil if memory_ptr.null?
|
94
|
+
memory = LibNetPGP::PGPMemory.new(memory_ptr)
|
95
|
+
memory[:buf].read_bytes(memory[:length])
|
96
|
+
ensure
|
97
|
+
LibNetPGP::pgp_memory_free(memory) if memory
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def verify(data, armored=true)
|
102
|
+
NetPGP::verify([self], data, armored)
|
103
|
+
end
|
104
|
+
|
105
|
+
def add_subkey(subkey)
|
106
|
+
raise if subkey.subkeys.any?
|
107
|
+
subkey.parent = self
|
108
|
+
subkey.userids = @userids
|
109
|
+
@subkeys.push(subkey)
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.from_native(native)
|
113
|
+
pubkey = PublicKey.new
|
114
|
+
pubkey.version = LibNetPGP::enum_value(native[:version])
|
115
|
+
pubkey.creation_time = Time.at(native[:birthtime])
|
116
|
+
if pubkey.version == 3
|
117
|
+
pubkey.expiration_time = Time.at(native[:birthtime]) + (native[:days_valid] * 86400)
|
118
|
+
end
|
119
|
+
pubkey.public_key_algorithm = PublicKeyAlgorithm::from_native(native[:alg])
|
120
|
+
pubkey.mpi = NetPGP::mpis_from_native(native[:alg], native)
|
121
|
+
pubkey
|
122
|
+
end
|
123
|
+
|
124
|
+
def to_native(native)
|
125
|
+
native[:version] = @version
|
126
|
+
native[:birthtime] = @creation_time.to_i
|
127
|
+
if @version == 3 and @expiration_time
|
128
|
+
native[:days_valid] = ((@expiration_time.to_i - @creation_time.to_i) / 86400).to_i
|
129
|
+
else
|
130
|
+
native[:duration] = (@expiration_time.to_i - @creation_time.to_i).to_i
|
131
|
+
end
|
132
|
+
native[:alg] = @public_key_algorithm
|
133
|
+
NetPGP::mpis_to_native(native[:alg], @mpi, native)
|
134
|
+
end
|
135
|
+
|
136
|
+
def to_native_key(native_key)
|
137
|
+
native_key[:type] = :PGP_PTAG_CT_PUBLIC_KEY
|
138
|
+
native_key[:sigid] = key_id
|
139
|
+
to_native(native_key[:key][:pubkey])
|
140
|
+
if not @parent
|
141
|
+
@userids.each {|userid|
|
142
|
+
LibNetPGP::dynarray_append_item(native_key, 'uid', :string, userid)
|
143
|
+
}
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
end # module NetPGP
|
150
|
+
|