akero 1.0.3 → 1.0.4
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/README.md +10 -3
- data/Rakefile +4 -0
- data/benchmark/bm_rate.png +0 -0
- data/benchmark/bm_size.png +0 -0
- data/lib/akero.rb +18 -11
- data/lib/akero/benchmark.rb +25 -25
- data/lib/akero/version.rb +1 -1
- data/spec/akero_spec.rb +134 -129
- metadata +1 -7
data/README.md
CHANGED
|
@@ -4,13 +4,13 @@ Akero ([ἄγγελος](http://en.wiktionary.org/wiki/%F0%90%80%80%F0%90%80%90%
|
|
|
4
4
|
|
|
5
5
|
Under the hood Akero uses standard OpenSSL primitives. Each instance wraps a [RSA](http://en.wikipedia.org/wiki/RSA)-keypair, a corresponding [X.509 certificate](http://en.wikipedia.org/wiki/X.509) and exchanges self-signed messages ([PKCS#7](https://tools.ietf.org/html/rfc2315)) with other instances.
|
|
6
6
|
|
|
7
|
-
Akero does not try to be a substitute for a fully featured [PKI](http://en.wikipedia.org/wiki/Public_key_infrastructure). It is meant to be used as a building block in scenarios where trust-relationships and keyrings can be externally managed, and where the complexity of traditional solutions (X.509 PKI, OpenPGP,
|
|
7
|
+
Akero does not try to be a substitute for a fully featured [PKI](http://en.wikipedia.org/wiki/Public_key_infrastructure). It is meant to be used as a building block in scenarios where trust-relationships and keyrings can be externally managed, and where the complexity of traditional solutions (X.509 PKI, OpenPGP, custom RSA) yields no tangible benefits.
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
11
|
* Secure 1-to-n messaging (sign-only -or- sign->encrypt->sign)
|
|
12
|
-
* Low complexity; easy to use, understand and review (only
|
|
13
|
-
* Transport agnostic; messages and certificates are self-contained
|
|
12
|
+
* Low complexity; easy to use, understand and review (only 192 lines of code)
|
|
13
|
+
* Transport agnostic; messages and certificates are self-contained and optionally ascii-armored (base64)
|
|
14
14
|
* Built on standard OpenSSL primitives, no homegrown algorithms
|
|
15
15
|
* [100%](https://busyloop.net/oss/akero/coverage/) test coverage
|
|
16
16
|
|
|
@@ -64,6 +64,13 @@ File.open('/tmp/alice.akr', 'w') { |f| f.write(alice.private_key) }
|
|
|
64
64
|
# And load her again
|
|
65
65
|
new_alice = Akero.load(File.read('/tmp/alice.akr'))
|
|
66
66
|
|
|
67
|
+
# By default all messages are ascii armored.
|
|
68
|
+
# In production Alice disables the armoring
|
|
69
|
+
# for better performance.
|
|
70
|
+
signed_msg = alice.sign("Hello world!", false)
|
|
71
|
+
msg = alice.encrypt(alice.public_key, "Hello!", false)
|
|
72
|
+
puts alice.receive(msg).body # => "Hello!"
|
|
73
|
+
|
|
67
74
|
```
|
|
68
75
|
|
|
69
76
|
## Documentation
|
data/Rakefile
CHANGED
data/benchmark/bm_rate.png
CHANGED
|
Binary file
|
data/benchmark/bm_size.png
CHANGED
|
Binary file
|
data/lib/akero.rb
CHANGED
|
@@ -81,6 +81,7 @@ class Akero
|
|
|
81
81
|
PLATE_CRYPTED = ['PKCS7', 'AKERO SECRET MESSAGE'] # @private
|
|
82
82
|
|
|
83
83
|
DEFAULT_RSA_BITS = 2048
|
|
84
|
+
DEFAULT_DIGEST = OpenSSL::Digest::SHA512
|
|
84
85
|
|
|
85
86
|
# Unique fingerprint of this Akero keypair.
|
|
86
87
|
#
|
|
@@ -101,10 +102,10 @@ class Akero
|
|
|
101
102
|
# Akero.new(4096, OpenSSL::Digest::SHA512)
|
|
102
103
|
#
|
|
103
104
|
# @param [Integer] rsa_bits RSA key length
|
|
104
|
-
# @param [OpenSSL::Digest]
|
|
105
|
+
# @param [OpenSSL::Digest] digest Signature digest
|
|
105
106
|
# @return [Akero] New Akero instance
|
|
106
|
-
def initialize(rsa_bits=DEFAULT_RSA_BITS,
|
|
107
|
-
@key, @cert = generate_keypair(rsa_bits,
|
|
107
|
+
def initialize(rsa_bits=DEFAULT_RSA_BITS, digest=DEFAULT_DIGEST)
|
|
108
|
+
@key, @cert = generate_keypair(rsa_bits, digest) unless rsa_bits.nil?
|
|
108
109
|
end
|
|
109
110
|
|
|
110
111
|
# Load an Akero identity.
|
|
@@ -161,9 +162,11 @@ class Akero
|
|
|
161
162
|
# Sign a message.
|
|
162
163
|
#
|
|
163
164
|
# @param [String] plaintext The message to sign (binary safe)
|
|
165
|
+
# @param [Boolean] ascii_armor Convert the output in base64?
|
|
164
166
|
# @return [String] Akero signed message
|
|
165
|
-
def sign(plaintext)
|
|
166
|
-
|
|
167
|
+
def sign(plaintext, ascii_armor=true)
|
|
168
|
+
out = _sign(plaintext)
|
|
169
|
+
ascii_armor ? Akero.replate(out.to_s, Akero::PLATE_SIGNED) : out.to_der
|
|
167
170
|
end
|
|
168
171
|
|
|
169
172
|
# Sign->encrypt->sign a message for 1 or more recipients.
|
|
@@ -184,8 +187,9 @@ class Akero
|
|
|
184
187
|
#
|
|
185
188
|
# @param [Array] to Akero public keys of recipients
|
|
186
189
|
# @param [String] plaintext The message to encrypt (binary safe)
|
|
190
|
+
# @param [Boolean] ascii_armor Convert the output to base64?
|
|
187
191
|
# @return [String] Akero secret message
|
|
188
|
-
def encrypt(to, plaintext)
|
|
192
|
+
def encrypt(to, plaintext, ascii_armor=true)
|
|
189
193
|
to = [to] unless to.is_a? Array
|
|
190
194
|
to = to.map { |e|
|
|
191
195
|
case e
|
|
@@ -199,7 +203,8 @@ class Akero
|
|
|
199
203
|
raise RuntimeError, ERR_INVALID_RECIPIENT
|
|
200
204
|
end
|
|
201
205
|
}
|
|
202
|
-
|
|
206
|
+
out = _sign(_encrypt(to, _sign(plaintext, false)))
|
|
207
|
+
ascii_armor ? Akero.replate(out.to_s, PLATE_CRYPTED) : out.to_der
|
|
203
208
|
end
|
|
204
209
|
|
|
205
210
|
# Receive an Akero message.
|
|
@@ -207,7 +212,9 @@ class Akero
|
|
|
207
212
|
# @param [String] ciphertext Akero Message
|
|
208
213
|
# @return [Akero::Message] Message_body, signer_certificate, body_type
|
|
209
214
|
def receive(ciphertext)
|
|
210
|
-
ciphertext
|
|
215
|
+
if ciphertext.start_with? '-----BEGIN '
|
|
216
|
+
ciphertext = Akero.replate(ciphertext, Akero::PLATE_CRYPTED, true)
|
|
217
|
+
end
|
|
211
218
|
begin
|
|
212
219
|
body, signer_cert, body_type = verify(ciphertext, nil)
|
|
213
220
|
rescue ArgumentError
|
|
@@ -316,9 +323,9 @@ class Akero
|
|
|
316
323
|
# Generate new RSA keypair and certificate.
|
|
317
324
|
#
|
|
318
325
|
# @param [Integer] rsa_bits RSA key length
|
|
319
|
-
# @param [OpenSSL::Digest]
|
|
326
|
+
# @param [OpenSSL::Digest] digest Signature digest
|
|
320
327
|
# @return [Array] rsa_keypair, certificate
|
|
321
|
-
def generate_keypair(rsa_bits=DEFAULT_RSA_BITS,
|
|
328
|
+
def generate_keypair(rsa_bits=DEFAULT_RSA_BITS, digest=DEFAULT_DIGEST)
|
|
322
329
|
cn = "Akero #{Akero::VERSION}"
|
|
323
330
|
rsa = OpenSSL::PKey::RSA.new(rsa_bits)
|
|
324
331
|
|
|
@@ -342,7 +349,7 @@ class Akero
|
|
|
342
349
|
aki = ef.create_extension("authorityKeyIdentifier",
|
|
343
350
|
"keyid:always,issuer:always")
|
|
344
351
|
cert.add_extension(aki)
|
|
345
|
-
cert.sign(rsa,
|
|
352
|
+
cert.sign(rsa, digest.new)
|
|
346
353
|
[rsa, cert]
|
|
347
354
|
end
|
|
348
355
|
end
|
data/lib/akero/benchmark.rb
CHANGED
|
@@ -15,16 +15,16 @@ class Akero
|
|
|
15
15
|
puts "Running size benchmark..."
|
|
16
16
|
|
|
17
17
|
rnd = Random.new
|
|
18
|
-
msg_sizes = (8..
|
|
19
|
-
|
|
18
|
+
msg_sizes = (8..14).map{|x| 2**x}
|
|
19
|
+
modes = [[2048, false], [2048, true]]
|
|
20
20
|
results = {}
|
|
21
|
-
|
|
22
|
-
alice = Akero.new(
|
|
23
|
-
bob = Akero.new(
|
|
21
|
+
modes.each do |mode|
|
|
22
|
+
alice = Akero.new(mode[0])
|
|
23
|
+
bob = Akero.new(mode[0])
|
|
24
24
|
msg_sizes.each do |msize|
|
|
25
25
|
msg = rnd.bytes(msize)
|
|
26
|
-
ciphertext = alice.encrypt(bob.public_key, msg)
|
|
27
|
-
(results["ENCRYPT #{
|
|
26
|
+
ciphertext = alice.encrypt(bob.public_key, msg, mode[1])
|
|
27
|
+
(results["ENCRYPT #{mode[0]} bits #{mode[1] ? 'ascii_armor=1' : 'ascii_armor=0'}"] ||= []) << [msize, ciphertext.length / msg.length.to_f]
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
|
|
@@ -34,48 +34,48 @@ class Akero
|
|
|
34
34
|
def b_timing
|
|
35
35
|
puts "Running timing benchmark..."
|
|
36
36
|
|
|
37
|
-
msg_sizes = (
|
|
38
|
-
|
|
37
|
+
msg_sizes = (8..18).map{|x| 2**x}
|
|
38
|
+
modes = [[2048, false], [2048, true]]
|
|
39
39
|
|
|
40
40
|
rnd = Random.new
|
|
41
41
|
|
|
42
42
|
rounds = 50
|
|
43
43
|
results = []
|
|
44
|
-
|
|
45
|
-
results << B.enchmark("ENCRYPT #{
|
|
46
|
-
alice = Akero.new(
|
|
47
|
-
bob = Akero.new(
|
|
44
|
+
modes.each do |mode|
|
|
45
|
+
results << B.enchmark("ENCRYPT #{mode[0]} bits, ascii_armor=#{mode[1]?1:0}", :rounds => rounds, :compare => :mean) do
|
|
46
|
+
alice = Akero.new(mode[0])
|
|
47
|
+
bob = Akero.new(mode[0])
|
|
48
48
|
msg_sizes.each_with_index do |msize, i|
|
|
49
49
|
msg = rnd.bytes(msize)
|
|
50
50
|
job "msg_size #{msize}" do
|
|
51
|
-
alice.encrypt(bob.public_key, msg)
|
|
51
|
+
alice.encrypt(bob.public_key, msg, mode[1])
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
results << B.enchmark("
|
|
59
|
-
alice = Akero.new(
|
|
60
|
-
bob = Akero.new(
|
|
57
|
+
modes.each do |mode|
|
|
58
|
+
results << B.enchmark("DECRYPT #{mode[0]} bits, ascii_armor=#{mode[1]?1:0}", :rounds => rounds, :compare => :mean) do
|
|
59
|
+
alice = Akero.new(mode[0])
|
|
60
|
+
bob = Akero.new(mode[0])
|
|
61
61
|
msg_sizes.each_with_index do |msize, i|
|
|
62
62
|
msg = rnd.bytes(msize)
|
|
63
|
+
msg = alice.encrypt(bob.public_key, msg, mode[1])
|
|
63
64
|
job "msg_size #{msize}" do
|
|
64
|
-
|
|
65
|
+
bob.receive(msg)
|
|
65
66
|
end
|
|
66
67
|
end
|
|
67
68
|
end
|
|
68
69
|
end
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
results << B.enchmark("
|
|
72
|
-
alice = Akero.new(
|
|
73
|
-
bob = Akero.new(
|
|
71
|
+
modes.each do |mode|
|
|
72
|
+
results << B.enchmark("SIGN #{mode[0]} bits, ascii_armor=#{mode[1]?1:0}", :rounds => rounds, :compare => :mean) do
|
|
73
|
+
alice = Akero.new(mode[0])
|
|
74
|
+
bob = Akero.new(mode[0])
|
|
74
75
|
msg_sizes.each_with_index do |msize, i|
|
|
75
76
|
msg = rnd.bytes(msize)
|
|
76
|
-
msg = alice.encrypt(bob.public_key, msg)
|
|
77
77
|
job "msg_size #{msize}" do
|
|
78
|
-
|
|
78
|
+
alice.sign(msg, mode[1])
|
|
79
79
|
end
|
|
80
80
|
end
|
|
81
81
|
end
|
data/lib/akero/version.rb
CHANGED
data/spec/akero_spec.rb
CHANGED
|
@@ -56,145 +56,150 @@ describe Akero do
|
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
describe '#sign' do
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
59
|
+
([true, false]).each do |ascii_armor|
|
|
60
|
+
describe "ascii_armor=#{ascii_armor}" do
|
|
61
|
+
describe 'return value' do
|
|
62
|
+
if ascii_armor
|
|
63
|
+
it "is a String that looks like an Akero signed message" do
|
|
64
|
+
plaintext = "Hello world!"
|
|
65
|
+
signed_msg = subject.sign(plaintext, ascii_armor)
|
|
66
|
+
signed_msg.should be_a String
|
|
67
|
+
signed_msg.should match /^-----BEGIN #{Akero::PLATE_SIGNED[1]}-----\n/
|
|
68
|
+
signed_msg.should match /\n-----END #{Akero::PLATE_SIGNED[1]}-----\n$/
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "contains valid signature" do
|
|
73
|
+
plaintext = "Hello world!"
|
|
74
|
+
signed_msg = subject.sign(plaintext, ascii_armor)
|
|
75
|
+
bob = Akero.new
|
|
76
|
+
msg = bob.receive(signed_msg)
|
|
77
|
+
msg.from.should == subject.id
|
|
78
|
+
msg.from_pk.should == subject.public_key
|
|
79
|
+
msg.body.should == plaintext
|
|
80
|
+
msg.type.should == :signed
|
|
81
|
+
end
|
|
82
|
+
end
|
|
77
83
|
end
|
|
78
84
|
end
|
|
79
85
|
end
|
|
80
86
|
|
|
81
87
|
describe '#encrypt' do
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
it "raises RuntimeError when message is not String" do
|
|
117
|
-
lambda {
|
|
118
|
-
msg = "Hello world!"
|
|
119
|
-
ciphertext = subject.encrypt(subject.public_key, 42)
|
|
120
|
-
}.should raise_error RuntimeError, Akero::ERR_MSG_NOT_STRING_NOR_PKCS7
|
|
88
|
+
([true, false]).each do |ascii_armor|
|
|
89
|
+
describe "ascii_armor=#{ascii_armor}" do
|
|
90
|
+
describe 'return value' do
|
|
91
|
+
if ascii_armor
|
|
92
|
+
it "is a String that looks like an Akero secret message" do
|
|
93
|
+
plaintext = "Hello world!"
|
|
94
|
+
ciphertext = subject.encrypt(subject.public_key, plaintext, ascii_armor)
|
|
95
|
+
ciphertext.should be_a String
|
|
96
|
+
ciphertext.should match /^-----BEGIN #{Akero::PLATE_CRYPTED[1]}-----\n/
|
|
97
|
+
ciphertext.should match /\n-----END #{Akero::PLATE_CRYPTED[1]}-----\n$/
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "raises RuntimeError on invalid recipient (invalid public key)" do
|
|
102
|
+
lambda {
|
|
103
|
+
msg = "Hello world!"
|
|
104
|
+
ciphertext = subject.encrypt([subject.public_key, 'foo'], msg)
|
|
105
|
+
}.should raise_error RuntimeError, Akero::ERR_INVALID_RECIPIENT_CERT
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "raises RuntimeError on invalid recipient (wrong type)" do
|
|
109
|
+
lambda {
|
|
110
|
+
msg = "Hello world!"
|
|
111
|
+
ciphertext = subject.encrypt([subject.public_key, 42], msg)
|
|
112
|
+
}.should raise_error RuntimeError, Akero::ERR_INVALID_RECIPIENT
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "raises RuntimeError when message is not String" do
|
|
116
|
+
lambda {
|
|
117
|
+
msg = "Hello world!"
|
|
118
|
+
ciphertext = subject.encrypt(subject.public_key, 42)
|
|
119
|
+
}.should raise_error RuntimeError, Akero::ERR_MSG_NOT_STRING_NOR_PKCS7
|
|
120
|
+
end
|
|
121
|
+
end
|
|
121
122
|
end
|
|
122
123
|
end
|
|
123
124
|
end
|
|
124
125
|
|
|
125
126
|
describe '#receive' do
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
127
|
+
([true, false]).each do |ascii_armor|
|
|
128
|
+
describe "ascii_armor=#{ascii_armor}" do
|
|
129
|
+
it "decrypts message that was encrypted for self" do
|
|
130
|
+
plaintext = "Hello world!"
|
|
131
|
+
ciphertext = subject.encrypt(subject.public_key, plaintext, ascii_armor)
|
|
132
|
+
msg = subject.receive(ciphertext)
|
|
133
|
+
msg.body.should == plaintext
|
|
134
|
+
msg.type.should == :encrypted
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it "decrypts message that was encrypted for self and other recipients" do
|
|
138
|
+
plaintext = "Hello world!"
|
|
139
|
+
alice = Akero.new
|
|
140
|
+
bob = Akero.new
|
|
141
|
+
ciphertext = subject.encrypt([alice.public_key, subject.public_key, bob.public_key], plaintext, ascii_armor)
|
|
142
|
+
msg = subject.receive(ciphertext)
|
|
143
|
+
msg.body.should == plaintext
|
|
144
|
+
msg.type.should == :encrypted
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it "fails to decrypt message that was encrypted only for other recipients" do
|
|
148
|
+
lambda {
|
|
149
|
+
plaintext = "Hello world!"
|
|
150
|
+
alice = Akero.new
|
|
151
|
+
bob = Akero.new
|
|
152
|
+
ciphertext = subject.encrypt([alice.public_key, bob.public_key], plaintext, ascii_armor)
|
|
153
|
+
msg = subject.receive(ciphertext)
|
|
154
|
+
msg.body.should == plaintext
|
|
155
|
+
msg.type.should == :encrypted
|
|
156
|
+
}.should raise_error RuntimeError, Akero::ERR_DECRYPT
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it "extracts signature from signed message" do
|
|
160
|
+
plaintext = "Hello world!"
|
|
161
|
+
alice = Akero.new
|
|
162
|
+
signed_msg = subject.sign(plaintext, ascii_armor)
|
|
163
|
+
msg = alice.receive(signed_msg)
|
|
164
|
+
msg.body.should == plaintext
|
|
165
|
+
msg.type.should == :signed
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it "raises RuntimeError on invalid message" do
|
|
169
|
+
lambda {
|
|
170
|
+
subject.receive("foobar")
|
|
171
|
+
}.should raise_error RuntimeError #, Akero::ERR_MSG_MALFORMED_ENV
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it "raises RuntimeError when payload does not match envelope signature" do
|
|
175
|
+
lambda {
|
|
176
|
+
oscar = Akero.new
|
|
177
|
+
raw_key = subject.send(:instance_variable_get, '@cert')
|
|
178
|
+
a = subject.send(:_encrypt, [raw_key], subject.send(:_sign, 'foobar'))
|
|
179
|
+
b = oscar.send(:_sign, a)
|
|
180
|
+
c = ascii_armor ? Akero.replate(b.to_s, Akero::PLATE_CRYPTED) : b.to_der
|
|
181
|
+
subject.receive(c)
|
|
182
|
+
}.should raise_error RuntimeError, Akero::ERR_MSG_CORRUPT_CERT
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
it "raises RuntimeError on malformed inner message" do
|
|
186
|
+
lambda {
|
|
187
|
+
key, cert = subject.send(:generate_keypair, 1024)
|
|
188
|
+
env = OpenSSL::PKCS7::sign(cert, key, 0xff.chr, [], OpenSSL::PKCS7::BINARY)
|
|
189
|
+
broken_msg = Akero.replate(env.to_s, Akero::PLATE_CRYPTED)
|
|
190
|
+
subject.receive(broken_msg)
|
|
191
|
+
}.should raise_error RuntimeError, Akero::ERR_MSG_MALFORMED_BODY
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
it "raises RuntimeError on unsigned message" do
|
|
195
|
+
lambda {
|
|
196
|
+
raw_key = subject.send(:instance_variable_get, '@cert')
|
|
197
|
+
env = OpenSSL::PKCS7::encrypt([raw_key], 'foobar', OpenSSL::Cipher::new("AES-256-CFB"), OpenSSL::PKCS7::BINARY)
|
|
198
|
+
broken_msg = Akero.replate(env.to_s, Akero::PLATE_CRYPTED)
|
|
199
|
+
subject.receive(broken_msg)
|
|
200
|
+
}.should raise_error RuntimeError, Akero::ERR_MSG_TOO_MANY_SIGNERS
|
|
201
|
+
end
|
|
202
|
+
end
|
|
198
203
|
end
|
|
199
204
|
end
|
|
200
205
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: akero
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.4
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -190,18 +190,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
190
190
|
- - ! '>='
|
|
191
191
|
- !ruby/object:Gem::Version
|
|
192
192
|
version: '0'
|
|
193
|
-
segments:
|
|
194
|
-
- 0
|
|
195
|
-
hash: 1654579781693310372
|
|
196
193
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
197
194
|
none: false
|
|
198
195
|
requirements:
|
|
199
196
|
- - ! '>='
|
|
200
197
|
- !ruby/object:Gem::Version
|
|
201
198
|
version: '0'
|
|
202
|
-
segments:
|
|
203
|
-
- 0
|
|
204
|
-
hash: 1654579781693310372
|
|
205
199
|
requirements: []
|
|
206
200
|
rubyforge_project:
|
|
207
201
|
rubygems_version: 1.8.23
|