openpgp 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,31 @@
1
+ module OpenPGP
2
+ module Random
3
+ ##
4
+ # Generates a random number.
5
+ def self.number(bits = 32, options = {})
6
+ octets = bytes((bits / 8.0).ceil).unpack('C*')
7
+ number = octets.inject { |number, octet| number = (number << 8) | octet }
8
+ number & ((1 << bits) - 1)
9
+ end
10
+
11
+ ##
12
+ # Generates a pseudo-random prime number of the specified bit length.
13
+ #
14
+ # @see http://openssl.org/docs/crypto/BN_generate_prime.html
15
+ # @see http://openssl.org/docs/apps/genrsa.html
16
+ def self.prime(bits, options = {})
17
+ raise NotImplementedError # TODO
18
+ end
19
+
20
+ ##
21
+ # Generates a random byte.
22
+ def self.byte() bytes(1) end
23
+
24
+ ##
25
+ # Generates a string of random bytes.
26
+ def self.bytes(count, &block)
27
+ octets = File.open('/dev/urandom', 'r') {|f| f.read(count) } # FIXME
28
+ block_given? ? octets.each_byte(&block) : octets
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,186 @@
1
+ module OpenPGP
2
+ ##
3
+ # OpenPGP string-to-key (S2K) specifiers.
4
+ #
5
+ # @see http://tools.ietf.org/html/rfc4880#section-3.7
6
+ class S2K
7
+ attr_accessor :passphrase
8
+ attr_accessor :algorithm
9
+
10
+ def self.parse(input)
11
+ case mode = input.read_byte
12
+ when 0 then S2K::Simple.parse(input) # Simple S2K
13
+ when 1 then S2K::Salted.parse(input) # Salted S2K
14
+ when 3 then S2K::Iterated.parse(input) # Iterated and Salted S2K
15
+ when 100..110 then S2K.new(:data => input.read) # Private/Experimental S2K
16
+ else # TODO
17
+ end
18
+ end
19
+
20
+ def self.identifier
21
+ const_get(:IDENTIFIER)
22
+ end
23
+
24
+ def initialize(passphrase = nil, options = {}, &block)
25
+ @passphrase = passphrase.to_s
26
+ options.each { |k, v| instance_variable_set("@#{k}", v) }
27
+
28
+ block.call(self) if block_given?
29
+ end
30
+
31
+ def write(buffer)
32
+ buffer.write_byte(identifier)
33
+ buffer.write_byte(digest.to_i)
34
+ end
35
+
36
+ def identifier
37
+ @identifier || self.class.identifier
38
+ end
39
+
40
+ def to_hash
41
+ {:mode => identifier, :algorithm => digest.to_i}
42
+ end
43
+
44
+ def to_s
45
+ Buffer.write { |buffer| write(buffer) }
46
+ end
47
+
48
+ def to_key(key_size = 16)
49
+ key = if digest.size >= key_size
50
+ digest.digest(digest_input)
51
+ else
52
+ Buffer.write do |buffer|
53
+ (key_size / digest.size.to_f).ceil.times do |i|
54
+ buffer << digest.digest(digest_input_with_preload(i))
55
+ end
56
+ end
57
+ end
58
+ key[0, key_size]
59
+ end
60
+
61
+ def digest
62
+ @digest ||= case algorithm
63
+ when nil then Digest::DEFAULT
64
+ when Digest then algorithm
65
+ when Symbol then Digest.for(algorithm)
66
+ when String then Digest.for(algorithm)
67
+ else Digest.for(algorithm.to_i)
68
+ end
69
+ end
70
+
71
+ def digest_input_with_preload(length = 0)
72
+ ("\0" * length) << digest_input
73
+ end
74
+
75
+ def digest_input
76
+ raise NotImplementedError
77
+ end
78
+
79
+ ##
80
+ # @see http://tools.ietf.org/html/rfc4880#section-3.7.1.1
81
+ class Simple < S2K
82
+ IDENTIFIER = 0x00
83
+
84
+ def self.parse(input)
85
+ self.new(nil, :algorithm => input.read_byte)
86
+ end
87
+
88
+ def digest_input
89
+ passphrase
90
+ end
91
+ end
92
+
93
+ ##
94
+ # @see http://tools.ietf.org/html/rfc4880#section-3.7.1.2
95
+ class Salted < S2K
96
+ IDENTIFIER = 0x01
97
+
98
+ def self.parse(input)
99
+ self.new(nil, :algorithm => input.read_byte, :salt => input.read_bytes(8))
100
+ end
101
+
102
+ attr_accessor :salt
103
+
104
+ def initialize(passphrase = nil, options = {}, &block)
105
+ super(passphrase, options, &block)
106
+
107
+ @salt = Random.bytes(8) unless @salt
108
+ end
109
+
110
+ def write(buffer)
111
+ super(buffer)
112
+ buffer.write_bytes(salt)
113
+ end
114
+
115
+ def to_hash
116
+ super.merge({:salt => salt})
117
+ end
118
+
119
+ def digest_input
120
+ salt.to_s[0, 8] << passphrase
121
+ end
122
+ end
123
+
124
+ ##
125
+ # @see http://tools.ietf.org/html/rfc4880#section-3.7.1.3
126
+ class Iterated < Salted
127
+ IDENTIFIER = 0x03
128
+
129
+ def self.parse(input)
130
+ self.new(nil, :algorithm => input.read_byte, :salt => input.read_bytes(8)) do |s2k|
131
+ s2k.count = s2k.decode_count(input.read_byte)
132
+ end
133
+ end
134
+
135
+ attr_reader :count
136
+
137
+ def initialize(passphrase = nil, options = {}, &block)
138
+ super(passphrase, options, &block)
139
+
140
+ @count = 65536 unless @count
141
+ end
142
+
143
+ def write(buffer)
144
+ super(buffer)
145
+ buffer.write_byte(encode_count(count))
146
+ end
147
+
148
+ def to_hash
149
+ super.merge(:count => count)
150
+ end
151
+
152
+ def digest_input
153
+ buffer = Buffer.write do |buffer|
154
+ iterations = count
155
+ while iterations > 0
156
+ buffer << (digest_input = super())
157
+ iterations -= digest_input.size
158
+ end
159
+ end
160
+ end
161
+
162
+ protected
163
+
164
+ EXPBIAS = 6
165
+
166
+ def decode_count(count)
167
+ (16 + (count & 15)) << ((count >> 4) + EXPBIAS)
168
+ end
169
+
170
+ def encode_count(iterations)
171
+ case iterations
172
+ when 0..1024 then 0
173
+ when 65011712..(1.0/0) then 255
174
+ else
175
+ count1 = iterations >> 6
176
+ count2 = (count2 || 0) + 1 while count1 >= 32 && count1 >>= 1
177
+ result = (count2 << 4) | (count1 - 16)
178
+ result += 1 if decode_count(result) < iterations
179
+ result
180
+ end
181
+ end
182
+ end
183
+
184
+ DEFAULT = Iterated
185
+ end
186
+ end
@@ -0,0 +1,65 @@
1
+ module OpenPGP
2
+ ##
3
+ # Alias for OpenPGP::Armor.encode().
4
+ def self.enarmor(data, marker = :message, options = {})
5
+ Armor.encode(data, marker, options)
6
+ end
7
+
8
+ ##
9
+ # Alias for OpenPGP::Armor.decode().
10
+ def self.dearmor(text, marker = nil, options = {})
11
+ Armor.decode(text, marker, options)
12
+ end
13
+
14
+ ##
15
+ # Alias for OpenPGP::Message.encrypt().
16
+ def self.encrypt(data, options = {})
17
+ (msg = Message.encrypt(data, options)) ? msg.to_s : nil
18
+ end
19
+
20
+ ##
21
+ # Alias for OpenPGP::Message.decrypt().
22
+ def self.decrypt(data, options = {})
23
+ raise NotImplementedError # TODO
24
+ end
25
+
26
+ ##
27
+ # Alias for OpenPGP::Message.sign().
28
+ def self.sign
29
+ raise NotImplementedError # TODO
30
+ end
31
+
32
+ ##
33
+ # Alias for OpenPGP::Message.verify().
34
+ def self.verify
35
+ raise NotImplementedError # TODO
36
+ end
37
+
38
+ ##
39
+ # @see http://tools.ietf.org/html/rfc4880#section-6.1
40
+ CRC24_INIT = 0x00b704ce
41
+ CRC24_POLY = 0x01864cfb
42
+
43
+ ##
44
+ # @see http://tools.ietf.org/html/rfc4880#section-6
45
+ # @see http://tools.ietf.org/html/rfc4880#section-6.1
46
+ def self.crc24(data)
47
+ crc = CRC24_INIT
48
+ data.each_byte do |octet|
49
+ crc ^= octet << 16
50
+ 8.times do
51
+ crc <<= 1
52
+ crc ^= CRC24_POLY if (crc & 0x01000000).nonzero?
53
+ end
54
+ end
55
+ crc &= 0x00ffffff
56
+ end
57
+
58
+ ##
59
+ # Returns the bit length of a multiprecision integer (MPI).
60
+ #
61
+ # @see http://tools.ietf.org/html/rfc4880#section-3.2
62
+ def self.bitlength(data)
63
+ data.empty? ? 0 : (data.size - 1) * 8 + (Math.log(data[0]) / Math.log(2)).floor + 1
64
+ end
65
+ end
@@ -1,11 +1,14 @@
1
1
  module OpenPGP
2
- module Version
2
+ module VERSION
3
3
  MAJOR = 0
4
4
  MINOR = 0
5
- TINY = 1
5
+ TINY = 2
6
6
  EXTRA = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY].join('.')
9
9
  STRING << "-#{EXTRA}" if EXTRA
10
+
11
+ def self.to_s() STRING end
12
+ def self.to_str() STRING end
10
13
  end
11
14
  end
metadata CHANGED
@@ -1,19 +1,30 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openpgp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arto Bendiken
8
+ - "K\xC3\xA9vin Lacointe"
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
12
 
12
- date: 2009-04-18 00:00:00 +02:00
13
+ date: 2009-12-20 00:00:00 +01:00
13
14
  default_executable: openpgp
14
15
  dependencies:
15
16
  - !ruby/object:Gem::Dependency
16
- name: rakefile
17
+ name: open4
18
+ type: :runtime
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ version:
26
+ - !ruby/object:Gem::Dependency
27
+ name: bendiken-rakefile
17
28
  type: :development
18
29
  version_requirement:
19
30
  version_requirements: !ruby/object:Gem::Requirement
@@ -22,7 +33,7 @@ dependencies:
22
33
  - !ruby/object:Gem::Version
23
34
  version: "0"
24
35
  version:
25
- description: " OpenPGP.rb is a pure-Ruby implementation of the OpenPGP Message Format (RFC 4880).\n"
36
+ description: " OpenPGP.rb is a pure-Ruby implementation of the OpenPGP Message Format\n (RFC 4880), the most widely-used e-mail encryption standard in the world.\n"
26
37
  email: arto.bendiken@gmail.com
27
38
  executables:
28
39
  - openpgp
@@ -31,22 +42,42 @@ extensions: []
31
42
  extra_rdoc_files: []
32
43
 
33
44
  files:
34
- - LICENSE
45
+ - AUTHORS
35
46
  - README
36
47
  - Rakefile
48
+ - UNLICENSE
37
49
  - VERSION
38
50
  - bin/openpgp
39
- - lib/openpgp.rb
40
51
  - lib/openpgp/algorithm.rb
41
52
  - lib/openpgp/armor.rb
42
- - lib/openpgp/gnupg.rb
53
+ - lib/openpgp/buffer.rb
54
+ - lib/openpgp/cipher/3des.rb
55
+ - lib/openpgp/cipher/aes.rb
56
+ - lib/openpgp/cipher/blowfish.rb
57
+ - lib/openpgp/cipher/cast5.rb
58
+ - lib/openpgp/cipher/idea.rb
59
+ - lib/openpgp/cipher/twofish.rb
60
+ - lib/openpgp/cipher.rb
61
+ - lib/openpgp/client/gnupg.rb
62
+ - lib/openpgp/digest/md5.rb
63
+ - lib/openpgp/digest/rmd160.rb
64
+ - lib/openpgp/digest/sha1.rb
65
+ - lib/openpgp/digest/sha2.rb
66
+ - lib/openpgp/digest.rb
67
+ - lib/openpgp/engine/gnupg.rb
68
+ - lib/openpgp/engine/openssl.rb
69
+ - lib/openpgp/engine.rb
43
70
  - lib/openpgp/message.rb
44
71
  - lib/openpgp/packet.rb
72
+ - lib/openpgp/random.rb
73
+ - lib/openpgp/s2k.rb
74
+ - lib/openpgp/util.rb
45
75
  - lib/openpgp/version.rb
76
+ - lib/openpgp.rb
46
77
  has_rdoc: false
47
78
  homepage: http://github.com/bendiken/openpgp
48
79
  licenses:
49
- - MIT
80
+ - Public Domain
50
81
  post_install_message:
51
82
  rdoc_options: []
52
83
 
@@ -67,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
98
  requirements:
68
99
  - GnuPG >= 1.4.7 (not required, but enables extra functionality)
69
100
  rubyforge_project: openpgp
70
- rubygems_version: 1.3.2
101
+ rubygems_version: 1.3.5
71
102
  signing_key:
72
103
  specification_version: 3
73
104
  summary: A pure-Ruby implementation of the OpenPGP Message Format (RFC 4880).
data/LICENSE DELETED
@@ -1,19 +0,0 @@
1
- Copyright (c) 2009 Arto Bendiken <http://ar.to/>
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining a copy
4
- of this software and associated documentation files (the "Software"), to
5
- deal in the Software without restriction, including without limitation the
6
- rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
- sell copies of the Software, and to permit persons to whom the Software is
8
- furnished to do so, subject to the following conditions:
9
-
10
- The above copyright notice and this permission notice shall be included in
11
- all copies or substantial portions of the Software.
12
-
13
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
- IN THE SOFTWARE.