openpgp 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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