openpgp 0.0.2 → 0.0.3
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.
- data/AUTHORS +1 -2
- data/CONTRIBUTORS +1 -0
- data/README +45 -13
- data/VERSION +1 -1
- data/lib/openpgp.rb +17 -3
- data/lib/openpgp/algorithm.rb +1 -0
- data/lib/openpgp/armor.rb +37 -9
- data/lib/openpgp/buffer.rb +57 -8
- data/lib/openpgp/cipher.rb +34 -3
- data/lib/openpgp/client/gnupg.rb +230 -20
- data/lib/openpgp/digest.rb +19 -0
- data/lib/openpgp/digest/md5.rb +1 -0
- data/lib/openpgp/digest/rmd160.rb +1 -0
- data/lib/openpgp/digest/sha1.rb +1 -0
- data/lib/openpgp/digest/sha2.rb +4 -0
- data/lib/openpgp/engine.rb +17 -0
- data/lib/openpgp/engine/gnupg.rb +58 -1
- data/lib/openpgp/engine/openssl.rb +13 -1
- data/lib/openpgp/message.rb +32 -2
- data/lib/openpgp/packet.rb +31 -11
- data/lib/openpgp/random.rb +14 -2
- data/lib/openpgp/s2k.rb +70 -2
- data/lib/openpgp/util.rb +14 -10
- data/lib/openpgp/version.rb +12 -4
- metadata +50 -20
- data/Rakefile +0 -5
data/AUTHORS
CHANGED
@@ -1,2 +1 @@
|
|
1
|
-
* Arto Bendiken <arto.bendiken@gmail.com>
|
2
|
-
* Kévin Lacointe <kevinlacointe@gmail.com> (Some GnuPG patches)
|
1
|
+
* Arto Bendiken <arto.bendiken@gmail.com>
|
data/CONTRIBUTORS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* Kévin Lacointe <kevinlacointe@gmail.com> (Some GnuPG patches)
|
data/README
CHANGED
@@ -3,7 +3,6 @@ OpenPGP.rb: OpenPGP for Ruby
|
|
3
3
|
|
4
4
|
This is a pure-Ruby implementation of the OpenPGP Message Format (RFC 4880).
|
5
5
|
|
6
|
-
* <http://openpgp.rubyforge.org/>
|
7
6
|
* <http://github.com/bendiken/openpgp>
|
8
7
|
|
9
8
|
### About OpenPGP
|
@@ -28,12 +27,13 @@ Features
|
|
28
27
|
Examples
|
29
28
|
--------
|
30
29
|
|
30
|
+
require 'rubygems'
|
31
31
|
require 'openpgp'
|
32
32
|
|
33
33
|
### Decoding an ASCII-armored message
|
34
34
|
|
35
35
|
require 'open-uri'
|
36
|
-
text = open('http://
|
36
|
+
text = open('http://openpgp.rubyforge.org/pgp.txt').read
|
37
37
|
|
38
38
|
msg = OpenPGP::Message.parse(OpenPGP.dearmor(text))
|
39
39
|
|
@@ -56,6 +56,21 @@ Documentation
|
|
56
56
|
|
57
57
|
* <http://openpgp.rubyforge.org/>
|
58
58
|
|
59
|
+
Dependencies
|
60
|
+
------------
|
61
|
+
|
62
|
+
* [Ruby](http://ruby-lang.org/) (>= 1.8.7) or (>= 1.8.1 with [Backports][])
|
63
|
+
* [Open4](http://rubygems.org/gems/open4) (>= 1.0.1)
|
64
|
+
|
65
|
+
Installation
|
66
|
+
------------
|
67
|
+
|
68
|
+
The recommended installation method is via [RubyGems](http://rubygems.org/).
|
69
|
+
To install the latest official release of OpenPGP.rb, do:
|
70
|
+
|
71
|
+
% [sudo] gem install openpgp # Ruby 1.8.7+ or 1.9.x
|
72
|
+
% [sudo] gem install backports openpgp # Ruby 1.8.1+
|
73
|
+
|
59
74
|
Download
|
60
75
|
--------
|
61
76
|
|
@@ -68,21 +83,13 @@ as follows:
|
|
68
83
|
|
69
84
|
% wget http://github.com/bendiken/openpgp/tarball/master
|
70
85
|
|
71
|
-
Installation
|
72
|
-
------------
|
73
|
-
|
74
|
-
The recommended installation method is via RubyGems. To install the latest
|
75
|
-
official release from Gemcutter, do:
|
76
|
-
|
77
|
-
% [sudo] gem install openpgp
|
78
|
-
|
79
86
|
Resources
|
80
87
|
---------
|
81
88
|
|
82
89
|
* <http://openpgp.rubyforge.org/>
|
83
90
|
* <http://github.com/bendiken/openpgp>
|
84
|
-
* <http://
|
85
|
-
* <http://rubyforge.org/projects/openpgp
|
91
|
+
* <http://rubygems.org/gems/openpgp>
|
92
|
+
* <http://rubyforge.org/projects/openpgp/>
|
86
93
|
* <http://raa.ruby-lang.org/project/openpgp/>
|
87
94
|
* <http://www.ohloh.net/p/openpgp>
|
88
95
|
|
@@ -90,10 +97,35 @@ Authors
|
|
90
97
|
-------
|
91
98
|
|
92
99
|
* [Arto Bendiken](mailto:arto.bendiken@gmail.com) - <http://ar.to/>
|
93
|
-
|
100
|
+
|
101
|
+
Contributors
|
102
|
+
------------
|
103
|
+
|
104
|
+
* [Kévin Lacointe](mailto:kevinlacointe@gmail.com) - <http://github.com/klacointe>
|
105
|
+
|
106
|
+
Contributing
|
107
|
+
------------
|
108
|
+
|
109
|
+
* Do your best to adhere to the existing coding conventions and idioms.
|
110
|
+
* Don't use hard tabs, and don't leave trailing whitespace on any line.
|
111
|
+
* Do document every method you add using [YARD][] annotations. Read the
|
112
|
+
[tutorial][YARD-GS] or just look at the existing code for examples.
|
113
|
+
* Don't touch the `.gemspec` or `VERSION` files. If you need to change them,
|
114
|
+
do so on your private branch only.
|
115
|
+
* Do feel free to add yourself to the `CONTRIBUTORS` file and the
|
116
|
+
corresponding list in the the `README`. Alphabetical order applies.
|
117
|
+
* Don't touch the `AUTHORS` file. If your contributions are significant
|
118
|
+
enough, be assured we will eventually add you in there.
|
119
|
+
* Do note that in order for us to merge any non-trivial changes (as a rule
|
120
|
+
of thumb, additions larger than about 15 lines of code), we need an
|
121
|
+
explicit [public domain dedication][PDD] on record from you.
|
94
122
|
|
95
123
|
License
|
96
124
|
-------
|
97
125
|
|
98
126
|
OpenPGP.rb is free and unencumbered public domain software. For more
|
99
127
|
information, see <http://unlicense.org/> or the accompanying UNLICENSE file.
|
128
|
+
|
129
|
+
[YARD]: http://yardoc.org/
|
130
|
+
[YARD-GS]: http://yardoc.org/docs/yard/file:docs/GettingStarted.md
|
131
|
+
[PDD]: http://unlicense.org/#unlicensing-contributions
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.3
|
data/lib/openpgp.rb
CHANGED
@@ -1,17 +1,31 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
if RUBY_VERSION < '1.8.7'
|
2
|
+
# @see http://rubygems.org/gems/backports
|
3
|
+
begin
|
4
|
+
require 'backports/1.8.7'
|
5
|
+
rescue LoadError
|
6
|
+
begin
|
7
|
+
require 'rubygems'
|
8
|
+
require 'backports/1.8.7'
|
9
|
+
rescue LoadError
|
10
|
+
abort "OpenPGP.rb requires Ruby 1.8.7 or the Backports gem (hint: `gem install backports')."
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
3
14
|
|
4
15
|
module OpenPGP
|
16
|
+
require 'openpgp/util'
|
17
|
+
|
5
18
|
autoload :Algorithm, 'openpgp/algorithm'
|
6
19
|
autoload :Armor, 'openpgp/armor'
|
7
20
|
autoload :Buffer, 'openpgp/buffer'
|
8
21
|
autoload :Cipher, 'openpgp/cipher'
|
9
|
-
autoload :Engine, 'openpgp/engine'
|
10
22
|
autoload :Digest, 'openpgp/digest'
|
23
|
+
autoload :Engine, 'openpgp/engine'
|
11
24
|
autoload :Message, 'openpgp/message'
|
12
25
|
autoload :Packet, 'openpgp/packet'
|
13
26
|
autoload :Random, 'openpgp/random'
|
14
27
|
autoload :S2K, 'openpgp/s2k'
|
28
|
+
autoload :VERSION, 'openpgp/version'
|
15
29
|
end
|
16
30
|
|
17
31
|
OpenPGP::Engine::OpenSSL.install!
|
data/lib/openpgp/algorithm.rb
CHANGED
data/lib/openpgp/armor.rb
CHANGED
@@ -14,27 +14,42 @@ module OpenPGP
|
|
14
14
|
ARMORED_FILE = 'ARMORED FILE' # a GnuPG extension
|
15
15
|
end
|
16
16
|
|
17
|
+
##
|
18
|
+
# @param [String, #to_s] marker
|
19
|
+
# @return [String]
|
17
20
|
def self.marker(marker)
|
18
21
|
marker = Markers.const_get(marker.to_s.upcase.to_sym) if marker.is_a?(Symbol)
|
19
22
|
marker.to_s.upcase
|
20
23
|
end
|
21
24
|
|
22
25
|
##
|
23
|
-
# @
|
26
|
+
# @param [String, #to_s] marker
|
27
|
+
# @return [String]
|
28
|
+
# @see http://tools.ietf.org/html/rfc4880#section-6.2
|
24
29
|
def self.header(marker)
|
25
30
|
"-----BEGIN PGP #{marker(marker)}-----"
|
26
31
|
end
|
27
32
|
|
28
33
|
##
|
29
|
-
# @
|
34
|
+
# @param [String, #to_s] marker
|
35
|
+
# @return [String]
|
36
|
+
# @see http://tools.ietf.org/html/rfc4880#section-6.2
|
30
37
|
def self.footer(marker)
|
31
38
|
"-----END PGP #{marker(marker)}-----"
|
32
39
|
end
|
33
40
|
|
34
41
|
##
|
35
|
-
# @
|
36
|
-
# @
|
37
|
-
# @
|
42
|
+
# @param [String] data
|
43
|
+
# @param [String, #to_s] marker
|
44
|
+
# @param [Hash{Symbol => Object}] options
|
45
|
+
# @option options [String, #to_s] :version (nil)
|
46
|
+
# @option options [String, #to_s] :comment (nil)
|
47
|
+
# @option options [Hash] :headers (nil)
|
48
|
+
# @option options [Integer] :line_length (nil)
|
49
|
+
# @return [String]
|
50
|
+
# @see http://tools.ietf.org/html/rfc4880#section-6
|
51
|
+
# @see http://tools.ietf.org/html/rfc4880#section-6.2
|
52
|
+
# @see http://tools.ietf.org/html/rfc2045
|
38
53
|
def self.encode(data, marker = :message, options = {})
|
39
54
|
Buffer.write do |text|
|
40
55
|
text << self.header(marker) << "\n"
|
@@ -50,8 +65,13 @@ module OpenPGP
|
|
50
65
|
end
|
51
66
|
|
52
67
|
##
|
53
|
-
# @
|
54
|
-
# @
|
68
|
+
# @param [String] text
|
69
|
+
# @param [String, #to_s] marker
|
70
|
+
# @param [Hash{Symbol => Object}] options
|
71
|
+
# @option options [Boolean] :crc (false)
|
72
|
+
# @return [String]
|
73
|
+
# @see http://tools.ietf.org/html/rfc4880#section-6
|
74
|
+
# @see http://tools.ietf.org/html/rfc2045
|
55
75
|
def self.decode(text, marker = nil, options = {})
|
56
76
|
data, crc, state = Buffer.new, nil, :begin
|
57
77
|
|
@@ -87,13 +107,18 @@ module OpenPGP
|
|
87
107
|
data
|
88
108
|
end
|
89
109
|
|
110
|
+
##
|
90
111
|
class CRCError < IOError; end
|
91
112
|
|
92
113
|
protected
|
93
114
|
|
94
115
|
##
|
95
|
-
# Returns the Base64-encoded version of
|
116
|
+
# Returns the Base64-encoded version of `input`, with a configurable
|
96
117
|
# output line length.
|
118
|
+
#
|
119
|
+
# @param [String] input
|
120
|
+
# @param [Integer] line_length
|
121
|
+
# @return [String]
|
97
122
|
def self.encode64(input, line_length = nil)
|
98
123
|
if line_length.nil?
|
99
124
|
[input].pack('m')
|
@@ -110,7 +135,10 @@ module OpenPGP
|
|
110
135
|
end
|
111
136
|
|
112
137
|
##
|
113
|
-
# Returns the Base64-decoded version of
|
138
|
+
# Returns the Base64-decoded version of `input`.
|
139
|
+
#
|
140
|
+
# @param [String] input
|
141
|
+
# @return [String]
|
114
142
|
def self.decode64(input)
|
115
143
|
input.unpack('m').first
|
116
144
|
end
|
data/lib/openpgp/buffer.rb
CHANGED
@@ -3,22 +3,30 @@ require 'stringio'
|
|
3
3
|
module OpenPGP
|
4
4
|
##
|
5
5
|
class Buffer < StringIO
|
6
|
+
##
|
7
|
+
# @return [String]
|
6
8
|
def self.write(*args, &block)
|
7
9
|
buffer = self.new(*args, &block)
|
8
10
|
buffer.string
|
9
11
|
end
|
10
12
|
|
13
|
+
##
|
14
|
+
# @yield [buffer]
|
15
|
+
# @yieldparam [Buffer] buffer
|
11
16
|
def initialize(*args, &block)
|
12
17
|
super
|
13
18
|
block.call(self) if block_given?
|
14
19
|
end
|
15
20
|
|
16
21
|
##
|
22
|
+
# @return [String]
|
17
23
|
def read_string
|
18
24
|
read_bytes(length = read_byte)
|
19
25
|
end
|
20
26
|
|
21
27
|
##
|
28
|
+
# @param [String, #to_s] value
|
29
|
+
# @return [Buffer]
|
22
30
|
def write_string(value)
|
23
31
|
value = value.to_s
|
24
32
|
self << [value.size].pack('C')
|
@@ -26,19 +34,25 @@ module OpenPGP
|
|
26
34
|
end
|
27
35
|
|
28
36
|
##
|
29
|
-
# @
|
37
|
+
# @return [Integer]
|
38
|
+
# @see http://tools.ietf.org/html/rfc4880#section-3.5
|
30
39
|
def read_timestamp
|
31
40
|
read_unpacked(4, 'N')
|
32
41
|
end
|
33
42
|
|
34
43
|
##
|
35
|
-
# @
|
44
|
+
# @param [Integer, #to_i] value
|
45
|
+
# @return [Buffer]
|
46
|
+
# @see http://tools.ietf.org/html/rfc4880#section-3.5
|
36
47
|
def write_timestamp(value)
|
37
48
|
self << [value.to_i].pack('N')
|
38
49
|
end
|
39
50
|
|
40
51
|
##
|
41
|
-
# @
|
52
|
+
# @param [Integer] count
|
53
|
+
# @param [Integer] base
|
54
|
+
# @return [Integer]
|
55
|
+
# @see http://tools.ietf.org/html/rfc4880#section-3.1
|
42
56
|
def read_number(count, base = nil)
|
43
57
|
number, shift = 0, count * 8
|
44
58
|
read_bytes(count).each_byte do |octet|
|
@@ -48,13 +62,16 @@ module OpenPGP
|
|
48
62
|
end
|
49
63
|
|
50
64
|
##
|
51
|
-
# @
|
65
|
+
# @param [Integer] value
|
66
|
+
# @return [Buffer]
|
67
|
+
# @see http://tools.ietf.org/html/rfc4880#section-3.1
|
52
68
|
def write_number
|
53
69
|
# TODO
|
54
70
|
end
|
55
71
|
|
56
72
|
##
|
57
|
-
# @
|
73
|
+
# @return [String]
|
74
|
+
# @see http://tools.ietf.org/html/rfc4880#section-3.2
|
58
75
|
def read_mpi
|
59
76
|
length = read_unpacked(2, 'n') # length in bits
|
60
77
|
length = ((length + 7) / 8.0).floor # length in bytes
|
@@ -62,39 +79,71 @@ module OpenPGP
|
|
62
79
|
end
|
63
80
|
|
64
81
|
##
|
65
|
-
# @
|
82
|
+
# @param [String] value
|
83
|
+
# @return [Buffer]
|
84
|
+
# @see http://tools.ietf.org/html/rfc4880#section-3.2
|
66
85
|
def write_mpi
|
67
86
|
# TODO
|
68
87
|
end
|
69
88
|
|
70
89
|
##
|
71
|
-
# @
|
90
|
+
# @return [S2K]
|
91
|
+
# @see http://tools.ietf.org/html/rfc4880#section-3.7
|
72
92
|
def read_s2k() S2K.parse(self) end
|
73
93
|
|
94
|
+
##
|
95
|
+
# @param [S2K] s2k
|
96
|
+
# @return [Buffer]
|
74
97
|
def write_s2k(s2k) s2k.write(self) end
|
75
98
|
|
99
|
+
##
|
100
|
+
# @param [Integer] count
|
101
|
+
# @param [String] format
|
102
|
+
# @return [Integer]
|
76
103
|
def read_unpacked(count, format)
|
77
104
|
read_bytes(count).unpack(format).first
|
78
105
|
end
|
79
106
|
|
107
|
+
##
|
108
|
+
# @param [Integer] value
|
109
|
+
# @return [Buffer]
|
80
110
|
def write_unpacked
|
81
111
|
# TODO
|
82
112
|
end
|
83
113
|
|
114
|
+
##
|
115
|
+
# @param [Integer] count
|
116
|
+
# @return [String]
|
84
117
|
def read_bytes(count)
|
85
118
|
read(count)
|
86
119
|
end
|
87
120
|
|
121
|
+
##
|
122
|
+
# @param [String] value
|
123
|
+
# @return [Buffer]
|
88
124
|
def write_bytes(value)
|
89
125
|
self << value
|
90
126
|
end
|
91
127
|
|
128
|
+
##
|
129
|
+
# @return [String]
|
92
130
|
def read_byte
|
93
|
-
|
131
|
+
getbyte
|
94
132
|
end
|
95
133
|
|
134
|
+
##
|
135
|
+
# @param [#chr, #to_s] value
|
136
|
+
# @return [Buffer]
|
96
137
|
def write_byte(value)
|
97
138
|
self << (value.respond_to?(:chr) ? value : value.to_s[0]).chr
|
98
139
|
end
|
140
|
+
|
141
|
+
##
|
142
|
+
# @return [String]
|
143
|
+
def string
|
144
|
+
string = super
|
145
|
+
string.force_encoding(Encoding::ASCII_8BIT) if string.respond_to?(:force_encoding)
|
146
|
+
string
|
147
|
+
end
|
99
148
|
end
|
100
149
|
end
|
data/lib/openpgp/cipher.rb
CHANGED
@@ -16,7 +16,9 @@ module OpenPGP
|
|
16
16
|
DEFAULT = AES128
|
17
17
|
|
18
18
|
##
|
19
|
-
# @
|
19
|
+
# @param [Symbol, String, Integer] identifier
|
20
|
+
# @return [Class]
|
21
|
+
# @see http://tools.ietf.org/html/rfc4880#section-9.2
|
20
22
|
def self.for(identifier)
|
21
23
|
case identifier
|
22
24
|
when Symbol then const_get(identifier.to_s.upcase)
|
@@ -32,9 +34,18 @@ module OpenPGP
|
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
35
|
-
|
37
|
+
# @return [S2K]
|
38
|
+
attr_accessor :key
|
39
|
+
|
40
|
+
# @return [Hash]
|
41
|
+
attr_accessor :options
|
42
|
+
|
43
|
+
# @return [String]
|
36
44
|
attr_accessor :engine
|
37
45
|
|
46
|
+
##
|
47
|
+
# @param [S2K] key
|
48
|
+
# @param [Hash{Symbol => Object}] options
|
38
49
|
def initialize(key, options = {})
|
39
50
|
@key = case key
|
40
51
|
when S2K then key.to_key(key_size)
|
@@ -43,24 +54,36 @@ module OpenPGP
|
|
43
54
|
@options = options
|
44
55
|
end
|
45
56
|
|
57
|
+
##
|
58
|
+
# @return [Integer]
|
46
59
|
def self.to_i() identifier end
|
47
60
|
|
61
|
+
##
|
62
|
+
# @return [Integer]
|
48
63
|
def self.identifier
|
49
64
|
const_get(:IDENTIFIER)
|
50
65
|
end
|
51
66
|
|
67
|
+
##
|
68
|
+
# @return [Integer]
|
52
69
|
def identifier()
|
53
70
|
self.class.identifier
|
54
71
|
end
|
55
72
|
|
73
|
+
##
|
74
|
+
# @return [Integer]
|
56
75
|
def key_size
|
57
76
|
@key_size ||= engine.key_len
|
58
77
|
end
|
59
78
|
|
79
|
+
##
|
80
|
+
# @return [Integer]
|
60
81
|
def block_size
|
61
82
|
@block_size ||= engine.block_size
|
62
83
|
end
|
63
84
|
|
85
|
+
##
|
86
|
+
# @return [String]
|
64
87
|
def engine
|
65
88
|
@engine ||= Engine::OpenSSL.use do
|
66
89
|
OpenSSL::Cipher.new(self.class.const_get(:ENGINE))
|
@@ -68,7 +91,9 @@ module OpenPGP
|
|
68
91
|
end
|
69
92
|
|
70
93
|
##
|
71
|
-
# @
|
94
|
+
# @param [String] plaintext
|
95
|
+
# @return [String]
|
96
|
+
# @see http://tools.ietf.org/html/rfc4880#section-13.9
|
72
97
|
def encrypt(plaintext)
|
73
98
|
ciphertext = String.new
|
74
99
|
|
@@ -101,12 +126,18 @@ module OpenPGP
|
|
101
126
|
ciphertext
|
102
127
|
end
|
103
128
|
|
129
|
+
##
|
130
|
+
# @param [String] ciphertext
|
131
|
+
# @return [String]
|
104
132
|
def decrypt(ciphertext)
|
105
133
|
# TODO
|
106
134
|
engine.reset
|
107
135
|
engine.decrypt
|
108
136
|
end
|
109
137
|
|
138
|
+
##
|
139
|
+
# @param [String] block
|
140
|
+
# @return [String]
|
110
141
|
def encrypt_block(block)
|
111
142
|
engine.encrypt
|
112
143
|
engine.key = @key
|