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.
@@ -9,12 +9,17 @@ module OpenPGP
9
9
 
10
10
  ##
11
11
  # Returns the implementation class for a packet tag.
12
+ #
13
+ # @param [Integer, #to_i] tag
14
+ # @return [Class]
12
15
  def self.for(tag)
13
16
  @@tags[tag.to_i] || self
14
17
  end
15
18
 
16
19
  ##
17
20
  # Returns the packet tag for this class.
21
+ #
22
+ # @return [Integer]
18
23
  def self.tag
19
24
  @@tags.index(self)
20
25
  end
@@ -22,13 +27,15 @@ module OpenPGP
22
27
  ##
23
28
  # Parses an OpenPGP packet.
24
29
  #
25
- # @see http://tools.ietf.org/html/rfc4880#section-4.2
30
+ # @param [Buffer, #to_str] data
31
+ # @return [Packet]
32
+ # @see http://tools.ietf.org/html/rfc4880#section-4.2
26
33
  def self.parse(data)
27
34
  data = Buffer.new(data.to_str) if data.respond_to?(:to_str)
28
35
 
29
36
  unless data.eof?
30
- new = ((tag = data.getc) & 64).nonzero? # bit 6 indicates new packet format if set
31
- data.ungetc(tag)
37
+ new = ((tag = data.getbyte) & 64).nonzero? # bit 6 indicates new packet format if set
38
+ data.ungetbyte(tag) rescue data.ungetc(tag.ord) # FIXME in backports/1.8.7
32
39
  send(new ? :parse_new_format : :parse_old_format, data)
33
40
  end
34
41
  end
@@ -36,20 +43,22 @@ module OpenPGP
36
43
  ##
37
44
  # Parses a new-format (RFC 4880) OpenPGP packet.
38
45
  #
39
- # @see http://tools.ietf.org/html/rfc4880#section-4.2.2
46
+ # @param [Buffer, #to_str] data
47
+ # @return [Packet]
48
+ # @see http://tools.ietf.org/html/rfc4880#section-4.2.2
40
49
  def self.parse_new_format(data)
41
- tag = data.getc & 63
42
- len = data.getc
50
+ tag = data.getbyte & 63
51
+ len = data.getbyte
43
52
 
44
53
  case len
45
54
  when 0..191 # 4.2.2.1. One-Octet Lengths
46
55
  data_length = len
47
56
  when 192..223 # 4.2.2.2. Two-Octet Lengths
48
- data_length = ((len - 192) << 8) + data.getc + 192
57
+ data_length = ((len - 192) << 8) + data.getbyte + 192
49
58
  when 224..254 # 4.2.2.4. Partial Body Lengths
50
59
  data_length = 1 << (len & 0x1f)
51
60
  when 255 # 4.2.2.3. Five-Octet Lengths
52
- data_length = (data.getc << 24) | (data.getc << 16) | (data.getc << 8) | data.getc
61
+ data_length = (data.getbyte << 24) | (data.getbyte << 16) | (data.getbyte << 8) | data.getbyte
53
62
  end
54
63
 
55
64
  Packet.for(tag).parse_body(Buffer.new(data.read(data_length)), :tag => tag)
@@ -58,14 +67,16 @@ module OpenPGP
58
67
  ##
59
68
  # Parses an old-format (PGP 2.6.x) OpenPGP packet.
60
69
  #
61
- # @see http://tools.ietf.org/html/rfc4880#section-4.2.1
70
+ # @param [Buffer, #to_str] data
71
+ # @return [Packet]
72
+ # @see http://tools.ietf.org/html/rfc4880#section-4.2.1
62
73
  def self.parse_old_format(data)
63
- len = (tag = data.getc) & 3
74
+ len = (tag = data.getbyte) & 3
64
75
  tag = (tag >> 2) & 15
65
76
 
66
77
  case len
67
78
  when 0 # The packet has a one-octet length. The header is 2 octets long.
68
- data_length = data.getc
79
+ data_length = data.getbyte
69
80
  when 1 # The packet has a two-octet length. The header is 3 octets long.
70
81
  data_length = data.read(2).unpack('n').first
71
82
  when 2 # The packet has a four-octet length. The header is 5 octets long.
@@ -80,10 +91,15 @@ module OpenPGP
80
91
  end
81
92
 
82
93
  ##
94
+ # @param [Buffer] body
95
+ # @param [Hash{Symbol => Object}] options
96
+ # @return [Packet]
83
97
  def self.parse_body(body, options = {})
84
98
  self.new(options)
85
99
  end
86
100
 
101
+ ##
102
+ # @param [Hash{Symbol => Object}] options
87
103
  def initialize(options = {}, &block)
88
104
  options.each { |k, v| send("#{k}=", v) }
89
105
  block.call(self) if block_given?
@@ -91,8 +107,12 @@ module OpenPGP
91
107
 
92
108
  #def to_s() body end
93
109
 
110
+ ##
111
+ # @return [Integer]
94
112
  def size() body.size end
95
113
 
114
+ ##
115
+ # @return [String]
96
116
  def body
97
117
  respond_to?(:write_body) ? Buffer.write { |buffer| write_body(buffer) } : ""
98
118
  end
@@ -2,6 +2,10 @@ module OpenPGP
2
2
  module Random
3
3
  ##
4
4
  # Generates a random number.
5
+ #
6
+ # @param [Integer] bits
7
+ # @param [Hash{Symbol => Object}] options
8
+ # @return [Integer]
5
9
  def self.number(bits = 32, options = {})
6
10
  octets = bytes((bits / 8.0).ceil).unpack('C*')
7
11
  number = octets.inject { |number, octet| number = (number << 8) | octet }
@@ -11,18 +15,26 @@ module OpenPGP
11
15
  ##
12
16
  # Generates a pseudo-random prime number of the specified bit length.
13
17
  #
14
- # @see http://openssl.org/docs/crypto/BN_generate_prime.html
15
- # @see http://openssl.org/docs/apps/genrsa.html
18
+ # @param [Integer] bits
19
+ # @param [Hash{Symbol => Object}] options
20
+ # @return [Integer]
21
+ # @see http://openssl.org/docs/crypto/BN_generate_prime.html
22
+ # @see http://openssl.org/docs/apps/genrsa.html
16
23
  def self.prime(bits, options = {})
17
24
  raise NotImplementedError # TODO
18
25
  end
19
26
 
20
27
  ##
21
28
  # Generates a random byte.
29
+ #
30
+ # @return [String]
22
31
  def self.byte() bytes(1) end
23
32
 
24
33
  ##
25
34
  # Generates a string of random bytes.
35
+ #
36
+ # @param [Integer] count
37
+ # @return [String]
26
38
  def self.bytes(count, &block)
27
39
  octets = File.open('/dev/urandom', 'r') {|f| f.read(count) } # FIXME
28
40
  block_given? ? octets.each_byte(&block) : octets
@@ -4,9 +4,15 @@ module OpenPGP
4
4
  #
5
5
  # @see http://tools.ietf.org/html/rfc4880#section-3.7
6
6
  class S2K
7
+ # @return [String]
7
8
  attr_accessor :passphrase
9
+
10
+ # @return [Integer]
8
11
  attr_accessor :algorithm
9
12
 
13
+ ##
14
+ # @param [Buffer] input
15
+ # @return [S2K]
10
16
  def self.parse(input)
11
17
  case mode = input.read_byte
12
18
  when 0 then S2K::Simple.parse(input) # Simple S2K
@@ -17,10 +23,15 @@ module OpenPGP
17
23
  end
18
24
  end
19
25
 
26
+ ##
27
+ # @return [Integer]
20
28
  def self.identifier
21
29
  const_get(:IDENTIFIER)
22
30
  end
23
31
 
32
+ ##
33
+ # @param [String, #to_s] passphrase
34
+ # @param [Hash{Symbol => Object}] options
24
35
  def initialize(passphrase = nil, options = {}, &block)
25
36
  @passphrase = passphrase.to_s
26
37
  options.each { |k, v| instance_variable_set("@#{k}", v) }
@@ -28,23 +39,34 @@ module OpenPGP
28
39
  block.call(self) if block_given?
29
40
  end
30
41
 
42
+ ##
43
+ # @param [Buffer] buffer
44
+ # @return [void]
31
45
  def write(buffer)
32
46
  buffer.write_byte(identifier)
33
47
  buffer.write_byte(digest.to_i)
34
48
  end
35
49
 
50
+ ##
51
+ # @return [Integer]
36
52
  def identifier
37
53
  @identifier || self.class.identifier
38
54
  end
39
55
 
56
+ ##
57
+ # @return [Hash]
40
58
  def to_hash
41
59
  {:mode => identifier, :algorithm => digest.to_i}
42
60
  end
43
61
 
62
+ ##
63
+ # @return [String]
44
64
  def to_s
45
65
  Buffer.write { |buffer| write(buffer) }
46
66
  end
47
67
 
68
+ ##
69
+ # @return [Object]
48
70
  def to_key(key_size = 16)
49
71
  key = if digest.size >= key_size
50
72
  digest.digest(digest_input)
@@ -58,6 +80,8 @@ module OpenPGP
58
80
  key[0, key_size]
59
81
  end
60
82
 
83
+ ##
84
+ # @return [Class]
61
85
  def digest
62
86
  @digest ||= case algorithm
63
87
  when nil then Digest::DEFAULT
@@ -68,10 +92,17 @@ module OpenPGP
68
92
  end
69
93
  end
70
94
 
95
+ ##
96
+ # @param [Integer] length
97
+ # @return [String]
71
98
  def digest_input_with_preload(length = 0)
72
99
  ("\0" * length) << digest_input
73
100
  end
74
101
 
102
+ ##
103
+ # @return [String]
104
+ # @raise [NotImplementedError] unless implemented in subclass
105
+ # @abstract
75
106
  def digest_input
76
107
  raise NotImplementedError
77
108
  end
@@ -81,10 +112,15 @@ module OpenPGP
81
112
  class Simple < S2K
82
113
  IDENTIFIER = 0x00
83
114
 
115
+ ##
116
+ # @param [Buffer] input
117
+ # @return [S2K]
84
118
  def self.parse(input)
85
119
  self.new(nil, :algorithm => input.read_byte)
86
120
  end
87
121
 
122
+ ##
123
+ # @return [String]
88
124
  def digest_input
89
125
  passphrase
90
126
  end
@@ -95,27 +131,40 @@ module OpenPGP
95
131
  class Salted < S2K
96
132
  IDENTIFIER = 0x01
97
133
 
134
+ ##
135
+ # @param [Buffer] input
136
+ # @return [S2K]
98
137
  def self.parse(input)
99
138
  self.new(nil, :algorithm => input.read_byte, :salt => input.read_bytes(8))
100
139
  end
101
140
 
141
+ # @return [String]
102
142
  attr_accessor :salt
103
143
 
144
+ ##
145
+ # @param [String, #to_s] passphrase
146
+ # @param [Hash{Symbol => Object}] options
104
147
  def initialize(passphrase = nil, options = {}, &block)
105
148
  super(passphrase, options, &block)
106
-
107
149
  @salt = Random.bytes(8) unless @salt
108
150
  end
109
151
 
152
+ ##
153
+ # @param [Buffer] buffer
154
+ # @return [void]
110
155
  def write(buffer)
111
156
  super(buffer)
112
157
  buffer.write_bytes(salt)
113
158
  end
114
159
 
160
+ ##
161
+ # @return [Hash]
115
162
  def to_hash
116
163
  super.merge({:salt => salt})
117
164
  end
118
165
 
166
+ ##
167
+ # @return [String]
119
168
  def digest_input
120
169
  salt.to_s[0, 8] << passphrase
121
170
  end
@@ -126,29 +175,42 @@ module OpenPGP
126
175
  class Iterated < Salted
127
176
  IDENTIFIER = 0x03
128
177
 
178
+ ##
179
+ # @param [Buffer] input
180
+ # @return [S2K]
129
181
  def self.parse(input)
130
182
  self.new(nil, :algorithm => input.read_byte, :salt => input.read_bytes(8)) do |s2k|
131
183
  s2k.count = s2k.decode_count(input.read_byte)
132
184
  end
133
185
  end
134
186
 
187
+ # @return [Integer]
135
188
  attr_reader :count
136
189
 
190
+ ##
191
+ # @param [String, #to_s] passphrase
192
+ # @param [Hash{Symbol => Object}] options
137
193
  def initialize(passphrase = nil, options = {}, &block)
138
194
  super(passphrase, options, &block)
139
-
140
195
  @count = 65536 unless @count
141
196
  end
142
197
 
198
+ ##
199
+ # @param [Buffer] buffer
200
+ # @return [void]
143
201
  def write(buffer)
144
202
  super(buffer)
145
203
  buffer.write_byte(encode_count(count))
146
204
  end
147
205
 
206
+ ##
207
+ # @return [Hash]
148
208
  def to_hash
149
209
  super.merge(:count => count)
150
210
  end
151
211
 
212
+ ##
213
+ # @return [String]
152
214
  def digest_input
153
215
  buffer = Buffer.write do |buffer|
154
216
  iterations = count
@@ -163,10 +225,16 @@ module OpenPGP
163
225
 
164
226
  EXPBIAS = 6
165
227
 
228
+ ##
229
+ # @param [Integer] count
230
+ # @return [Integer]
166
231
  def decode_count(count)
167
232
  (16 + (count & 15)) << ((count >> 4) + EXPBIAS)
168
233
  end
169
234
 
235
+ ##
236
+ # @param [Integer] iterations
237
+ # @return [Integer]
170
238
  def encode_count(iterations)
171
239
  case iterations
172
240
  when 0..1024 then 0
@@ -1,36 +1,36 @@
1
1
  module OpenPGP
2
2
  ##
3
- # Alias for OpenPGP::Armor.encode().
3
+ # Alias for {OpenPGP::Armor.encode}.
4
4
  def self.enarmor(data, marker = :message, options = {})
5
5
  Armor.encode(data, marker, options)
6
6
  end
7
7
 
8
8
  ##
9
- # Alias for OpenPGP::Armor.decode().
9
+ # Alias for {OpenPGP::Armor.decode}.
10
10
  def self.dearmor(text, marker = nil, options = {})
11
11
  Armor.decode(text, marker, options)
12
12
  end
13
13
 
14
14
  ##
15
- # Alias for OpenPGP::Message.encrypt().
15
+ # Alias for {OpenPGP::Message.encrypt}.
16
16
  def self.encrypt(data, options = {})
17
17
  (msg = Message.encrypt(data, options)) ? msg.to_s : nil
18
18
  end
19
19
 
20
20
  ##
21
- # Alias for OpenPGP::Message.decrypt().
21
+ # Alias for {OpenPGP::Message.decrypt}.
22
22
  def self.decrypt(data, options = {})
23
23
  raise NotImplementedError # TODO
24
24
  end
25
25
 
26
26
  ##
27
- # Alias for OpenPGP::Message.sign().
27
+ # Alias for {OpenPGP::Message.sign}.
28
28
  def self.sign
29
29
  raise NotImplementedError # TODO
30
30
  end
31
31
 
32
32
  ##
33
- # Alias for OpenPGP::Message.verify().
33
+ # Alias for {OpenPGP::Message.verify}.
34
34
  def self.verify
35
35
  raise NotImplementedError # TODO
36
36
  end
@@ -41,8 +41,10 @@ module OpenPGP
41
41
  CRC24_POLY = 0x01864cfb
42
42
 
43
43
  ##
44
- # @see http://tools.ietf.org/html/rfc4880#section-6
45
- # @see http://tools.ietf.org/html/rfc4880#section-6.1
44
+ # @param [String] data
45
+ # @return [Integer]
46
+ # @see http://tools.ietf.org/html/rfc4880#section-6
47
+ # @see http://tools.ietf.org/html/rfc4880#section-6.1
46
48
  def self.crc24(data)
47
49
  crc = CRC24_INIT
48
50
  data.each_byte do |octet|
@@ -58,8 +60,10 @@ module OpenPGP
58
60
  ##
59
61
  # Returns the bit length of a multiprecision integer (MPI).
60
62
  #
61
- # @see http://tools.ietf.org/html/rfc4880#section-3.2
63
+ # @param [String] data
64
+ # @return [Integer]
65
+ # @see http://tools.ietf.org/html/rfc4880#section-3.2
62
66
  def self.bitlength(data)
63
- data.empty? ? 0 : (data.size - 1) * 8 + (Math.log(data[0]) / Math.log(2)).floor + 1
67
+ data.empty? ? 0 : (data.size - 1) * 8 + (Math.log(data[0].ord) / Math.log(2)).floor + 1
64
68
  end
65
69
  end
@@ -2,13 +2,21 @@ module OpenPGP
2
2
  module VERSION
3
3
  MAJOR = 0
4
4
  MINOR = 0
5
- TINY = 2
5
+ TINY = 3
6
6
  EXTRA = nil
7
7
 
8
- STRING = [MAJOR, MINOR, TINY].join('.')
9
- STRING << "-#{EXTRA}" if EXTRA
8
+ STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
10
9
 
11
- def self.to_s() STRING end
10
+ ##
11
+ # @return [String]
12
+ def self.to_s() STRING end
13
+
14
+ ##
15
+ # @return [String]
12
16
  def self.to_str() STRING end
17
+
18
+ ##
19
+ # @return [Array(Integer, Integer, Integer)]
20
+ def self.to_a() [MAJOR, MINOR, TINY] end
13
21
  end
14
22
  end