sandal 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,37 @@
1
+ require 'helper'
2
+ require 'securerandom'
3
+
4
+ shared_examples 'algorithm compatibility' do |enc_class|
5
+
6
+ it 'can encrypt and decrypt tokens with the "dir" algorithm' do
7
+ payload = 'Some text to encrypt'
8
+ content_master_key = SecureRandom.random_bytes(32)
9
+ encrypter = enc_class.new(Sandal::Enc::Alg::Direct.new(content_master_key))
10
+ token = Sandal.encrypt_token(payload, encrypter)
11
+ output = Sandal.decrypt_token(token) { encrypter }
12
+ output.should == payload
13
+ end
14
+
15
+ it 'can encrypt and decrypt tokens with the RSA1_5 algorithm' do
16
+ payload = 'Some other text to encrypt'
17
+ rsa = OpenSSL::PKey::RSA.new(2048)
18
+ encrypter = enc_class.new(Sandal::Enc::Alg::RSA1_5.new(rsa.public_key))
19
+ token = Sandal.encrypt_token(payload, encrypter)
20
+ output = Sandal.decrypt_token(token) do
21
+ enc_class.new(Sandal::Enc::Alg::RSA1_5.new(rsa))
22
+ end
23
+ output.should == payload
24
+ end
25
+
26
+ it 'can encrypt and decrypt tokens with the RSA-OAEP algorithm' do
27
+ payload = 'Some more text to encrypt'
28
+ rsa = OpenSSL::PKey::RSA.new(2048)
29
+ encrypter = enc_class.new(Sandal::Enc::Alg::RSA_OAEP.new(rsa.public_key))
30
+ token = Sandal.encrypt_token(payload, encrypter)
31
+ output = Sandal.decrypt_token(token) do
32
+ enc_class.new(Sandal::Enc::Alg::RSA_OAEP.new(rsa))
33
+ end
34
+ output.should == payload
35
+ end
36
+
37
+ end
@@ -1,6 +1,8 @@
1
1
  require 'helper'
2
2
  require 'openssl'
3
3
 
4
+ include Sandal::Util
5
+
4
6
  # EC isn't implemented in jruby-openssl at the moment
5
7
  if defined? Sandal::Sig::ES
6
8
 
@@ -26,7 +28,7 @@ describe Sandal::Sig::ES do
26
28
  r = make_bn([14, 209, 33, 83, 121, 99, 108, 72, 60, 47, 127, 21, 88, 7, 212, 2, 163, 178, 40, 3, 58, 249, 124, 126, 23, 129, 154, 195, 22, 158, 166, 101] )
27
29
  s = make_bn([197, 10, 7, 211, 140, 60, 112, 229, 216, 241, 45, 175, 8, 74, 84, 128, 166, 101, 144, 197, 242, 147, 80, 154, 143, 63, 127, 138, 131, 163, 84, 213])
28
30
  signature = Sandal::Sig::ES.encode_jws_signature(r, s, 256)
29
- base64_signature = Sandal::Util.base64_encode(signature)
31
+ base64_signature = jwt_base64_encode(signature)
30
32
  base64_signature.should == 'DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q'
31
33
  end
32
34
 
@@ -34,7 +36,7 @@ describe Sandal::Sig::ES do
34
36
  r = make_bn([1, 220, 12, 129, 231, 171, 194, 209, 232, 135, 233, 117, 247, 105, 122, 210, 26, 125, 192, 1, 217, 21, 82, 91, 45, 240, 255, 83, 19, 34, 239, 71, 48, 157, 147, 152, 105, 18, 53, 108, 163, 214, 68, 231, 62, 153, 150, 106, 194, 164, 246, 72, 143, 138, 24, 50, 129, 223, 133, 206, 209, 172, 63, 237, 119, 109] )
35
37
  s = make_bn([0, 111, 6, 105, 44, 5, 41, 208, 128, 61, 152, 40, 92, 61, 152, 4, 150, 66, 60, 69, 247, 196, 170, 81, 193, 199, 78, 59, 194, 169, 16, 124, 9, 143, 42, 142, 131, 48, 206, 238, 34, 175, 83, 203, 220, 159, 3, 107, 155, 22, 27, 73, 111, 68, 68, 21, 238, 144, 229, 232, 148, 188, 222, 59, 242, 103] )
36
38
  signature = Sandal::Sig::ES.encode_jws_signature(r, s, 521)
37
- base64_signature = Sandal::Util.base64_encode(signature)
39
+ base64_signature = jwt_base64_encode(signature)
38
40
  base64_signature.should == 'AdwMgeerwtHoh-l192l60hp9wAHZFVJbLfD_UxMi70cwnZOYaRI1bKPWROc-mZZqwqT2SI-KGDKB34XO0aw_7XdtAG8GaSwFKdCAPZgoXD2YBJZCPEX3xKpRwcdOO8KpEHwJjyqOgzDO7iKvU8vcnwNrmxYbSW9ERBXukOXolLzeO_Jn'
39
41
  end
40
42
 
@@ -54,12 +56,36 @@ describe Sandal::Sig::ES256 do
54
56
  validator.valid?(signature, data).should == true
55
57
  end
56
58
 
59
+ it 'can use string keys to sign data and verify signatures' do
60
+ private_key = <<KEY_END
61
+ -----BEGIN EC PARAMETERS-----
62
+ BggqhkjOPQMBBw==
63
+ -----END EC PARAMETERS-----
64
+ -----BEGIN EC PRIVATE KEY-----
65
+ MHcCAQEEII1Ar4w2EVK6wNL84EpVTVY7XXXVmVqyvjZ4EW9kBGhSoAoGCCqGSM49
66
+ AwEHoUQDQgAEVnYRY+AEiU+UNdYzl+KtuWvdAfKBoAmEekv4icfZQCbLew/eXIlv
67
+ 32E8+j0bFYwYi3XjxCJXRE3S2iWPEEygcA==
68
+ -----END EC PRIVATE KEY-----
69
+ KEY_END
70
+ public_key = <<KEY_END
71
+ -----BEGIN PUBLIC KEY-----
72
+ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVnYRY+AEiU+UNdYzl+KtuWvdAfKB
73
+ oAmEekv4icfZQCbLew/eXIlv32E8+j0bFYwYi3XjxCJXRE3S2iWPEEygcA==
74
+ -----END PUBLIC KEY-----
75
+ KEY_END
76
+ data = 'Hello ES256'
77
+ signer = Sandal::Sig::ES256.new(private_key)
78
+ signature = signer.sign(data)
79
+ validator = Sandal::Sig::ES256.new(public_key)
80
+ validator.valid?(signature, data).should == true
81
+ end
82
+
57
83
  it 'can verify the signature in JWS section A3.1' do
58
84
  x = make_bn([127, 205, 206, 39, 112, 246, 196, 93, 65, 131, 203, 238, 111, 219, 75, 123, 88, 7, 51, 53, 123, 233, 239, 19, 186, 207, 110, 60, 123, 209, 84, 69])
59
85
  y = make_bn([199, 241, 68, 205, 27, 189, 155, 126, 135, 44, 223, 237, 185, 238, 185, 244, 179, 105, 93, 110, 169, 11, 36, 173, 138, 70, 35, 40, 133, 136, 229, 173])
60
86
  d = make_bn([142, 155, 16, 158, 113, 144, 152, 191, 152, 4, 135, 223, 31, 93, 119, 233, 203, 41, 96, 110, 190, 210, 38, 59, 95, 87, 194, 19, 223, 132, 244, 178])
61
87
  data = 'eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ'
62
- signature = Sandal::Util.base64_decode('DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q')
88
+ signature = jwt_base64_decode('DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q')
63
89
 
64
90
  group = OpenSSL::PKey::EC::Group.new('prime256v1')
65
91
  public_key = OpenSSL::PKey::EC.new(group)
@@ -73,7 +99,7 @@ describe Sandal::Sig::ES256 do
73
99
  y = make_bn([199, 241, 68, 205, 27, 189, 155, 126, 135, 44, 223, 237, 185, 238, 185, 244, 179, 105, 93, 110, 169, 11, 36, 173, 138, 70, 35, 40, 133, 136, 229, 173])
74
100
  d = make_bn([142, 155, 16, 158, 113, 144, 152, 191, 152, 4, 135, 223, 31, 93, 119, 233, 203, 41, 96, 110, 190, 210, 38, 59, 95, 87, 194, 19, 223, 132, 244, 178])
75
101
  data = 'not the data that was signed'
76
- signature = Sandal::Util.base64_decode('DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q')
102
+ signature = jwt_base64_decode('DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q')
77
103
 
78
104
  group = OpenSSL::PKey::EC::Group.new('prime256v1')
79
105
  public_key = OpenSSL::PKey::EC.new(group)
@@ -104,6 +130,32 @@ describe Sandal::Sig::ES384 do
104
130
  validator.valid?(signature, data).should == true
105
131
  end
106
132
 
133
+ it 'can use string keys to sign data and verify signatures' do
134
+ private_key = <<KEY_END
135
+ -----BEGIN EC PARAMETERS-----
136
+ BgUrgQQAIg==
137
+ -----END EC PARAMETERS-----
138
+ -----BEGIN EC PRIVATE KEY-----
139
+ MIGkAgEBBDDHWNCqR7V8EQS1aeCWXJ6arxaj31tvfBozSVDhbgzvFsFM9tbgbhTb
140
+ 1PGWXJEP91SgBwYFK4EEACKhZANiAASSjX9LH/BrmGp6WoHN/gBYN3Su/nIAApwM
141
+ iuFPbUFcWamxo8hUUTxLpdwvrrEHIVV2urXaVc0KHdSo93bVEHMOvLYjpXFXu+8f
142
+ 6Fu17ofcECDNIaI9A+uydWY3E/cJUDM=
143
+ -----END EC PRIVATE KEY-----
144
+ KEY_END
145
+ public_key = <<KEY_END
146
+ -----BEGIN PUBLIC KEY-----
147
+ MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEko1/Sx/wa5hqelqBzf4AWDd0rv5yAAKc
148
+ DIrhT21BXFmpsaPIVFE8S6XcL66xByFVdrq12lXNCh3UqPd21RBzDry2I6VxV7vv
149
+ H+hbte6H3BAgzSGiPQPrsnVmNxP3CVAz
150
+ -----END PUBLIC KEY-----
151
+ KEY_END
152
+ data = 'Hello ES384'
153
+ signer = Sandal::Sig::ES384.new(private_key)
154
+ signature = signer.sign(data)
155
+ validator = Sandal::Sig::ES384.new(public_key)
156
+ validator.valid?(signature, data).should == true
157
+ end
158
+
107
159
  it 'raises an argument error if the key has the wrong curve' do
108
160
  group = OpenSSL::PKey::EC::Group.new('secp521r1')
109
161
  private_key = OpenSSL::PKey::EC.new(group).generate_key
@@ -126,12 +178,40 @@ describe Sandal::Sig::ES512 do
126
178
  validator.valid?(signature, data).should == true
127
179
  end
128
180
 
181
+ it 'can use string keys to sign data and verify signatures' do
182
+ private_key = <<KEY_END
183
+ -----BEGIN EC PARAMETERS-----
184
+ BgUrgQQAIw==
185
+ -----END EC PARAMETERS-----
186
+ -----BEGIN EC PRIVATE KEY-----
187
+ MIHcAgEBBEIBQokOnEjac/cnqtuEPrS+ekzObqwN4wcsh4MgW1M9D/lC+cfHcgso
188
+ QhdmC1fZEYV9G3eiVYRO818XBrgzX8sOqQGgBwYFK4EEACOhgYkDgYYABADWDbxx
189
+ FZHDy5nzP+tL1AcDgbVtZbin6jOz3E0EPzjDJS8267XROdSLxh/FdM54HaZ5ak2D
190
+ q0VThSOquJdkiy6jyAEOlXLeznDrV9ZP9ddFFFA8OMM2aImU+HdGq6rlWrAs7qMU
191
+ tu6lP9k3+WHD7Z1+YkCafox+lpraE4NrnlkVqO2RVg==
192
+ -----END EC PRIVATE KEY-----
193
+ KEY_END
194
+ public_key = <<KEY_END
195
+ -----BEGIN PUBLIC KEY-----
196
+ MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQA1g28cRWRw8uZ8z/rS9QHA4G1bWW4
197
+ p+ozs9xNBD84wyUvNuu10TnUi8YfxXTOeB2meWpNg6tFU4UjqriXZIsuo8gBDpVy
198
+ 3s5w61fWT/XXRRRQPDjDNmiJlPh3Rquq5VqwLO6jFLbupT/ZN/lhw+2dfmJAmn6M
199
+ fpaa2hODa55ZFajtkVY=
200
+ -----END PUBLIC KEY-----
201
+ KEY_END
202
+ data = 'Hello ES512'
203
+ signer = Sandal::Sig::ES512.new(private_key)
204
+ signature = signer.sign(data)
205
+ validator = Sandal::Sig::ES512.new(public_key)
206
+ validator.valid?(signature, data).should == true
207
+ end
208
+
129
209
  it 'can verify the signature in JWS section A4.1' do
130
210
  x = make_bn([1, 233, 41, 5, 15, 18, 79, 198, 188, 85, 199, 213, 57, 51, 101, 223, 157, 239, 74, 176, 194, 44, 178, 87, 152, 249, 52, 235, 4, 227, 198, 186, 227, 112, 26, 87, 167, 145, 14, 157, 129, 191, 54, 49, 89, 232, 235, 203, 21, 93, 99, 73, 244, 189, 182, 204, 248, 169, 76, 92, 89, 199, 170, 193, 1, 164])
131
211
  y = make_bn([0, 52, 166, 68, 14, 55, 103, 80, 210, 55, 31, 209, 189, 194, 200, 243, 183, 29, 47, 78, 229, 234, 52, 50, 200, 21, 204, 163, 21, 96, 254, 93, 147, 135, 236, 119, 75, 85, 131, 134, 48, 229, 203, 191, 90, 140, 190, 10, 145, 221, 0, 100, 198, 153, 154, 31, 110, 110, 103, 250, 221, 237, 228, 200, 200, 246])
132
212
  d = make_bn([1, 142, 105, 111, 176, 52, 80, 88, 129, 221, 17, 11, 72, 62, 184, 125, 50, 206, 73, 95, 227, 107, 55, 69, 237, 242, 216, 202, 228, 240, 242, 83, 159, 70, 21, 160, 233, 142, 171, 82, 179, 192, 197, 234, 196, 206, 7, 81, 133, 168, 231, 187, 71, 222, 172, 29, 29, 231, 123, 204, 246, 97, 53, 230, 61, 130] )
133
213
  data = 'eyJhbGciOiJFUzUxMiJ9.UGF5bG9hZA'
134
- signature = Sandal::Util.base64_decode('AdwMgeerwtHoh-l192l60hp9wAHZFVJbLfD_UxMi70cwnZOYaRI1bKPWROc-mZZqwqT2SI-KGDKB34XO0aw_7XdtAG8GaSwFKdCAPZgoXD2YBJZCPEX3xKpRwcdOO8KpEHwJjyqOgzDO7iKvU8vcnwNrmxYbSW9ERBXukOXolLzeO_Jn')
214
+ signature = jwt_base64_decode('AdwMgeerwtHoh-l192l60hp9wAHZFVJbLfD_UxMi70cwnZOYaRI1bKPWROc-mZZqwqT2SI-KGDKB34XO0aw_7XdtAG8GaSwFKdCAPZgoXD2YBJZCPEX3xKpRwcdOO8KpEHwJjyqOgzDO7iKvU8vcnwNrmxYbSW9ERBXukOXolLzeO_Jn')
135
215
 
136
216
  group = OpenSSL::PKey::EC::Group.new('secp521r1')
137
217
  public_key = OpenSSL::PKey::EC.new(group)
@@ -145,7 +225,7 @@ describe Sandal::Sig::ES512 do
145
225
  y = make_bn([0, 52, 166, 68, 14, 55, 103, 80, 210, 55, 31, 209, 189, 194, 200, 243, 183, 29, 47, 78, 229, 234, 52, 50, 200, 21, 204, 163, 21, 96, 254, 93, 147, 135, 236, 119, 75, 85, 131, 134, 48, 229, 203, 191, 90, 140, 190, 10, 145, 221, 0, 100, 198, 153, 154, 31, 110, 110, 103, 250, 221, 237, 228, 200, 200, 246])
146
226
  d = make_bn([1, 142, 105, 111, 176, 52, 80, 88, 129, 221, 17, 11, 72, 62, 184, 125, 50, 206, 73, 95, 227, 107, 55, 69, 237, 242, 216, 202, 228, 240, 242, 83, 159, 70, 21, 160, 233, 142, 171, 82, 179, 192, 197, 234, 196, 206, 7, 81, 133, 168, 231, 187, 71, 222, 172, 29, 29, 231, 123, 204, 246, 97, 53, 230, 61, 130] )
147
227
  data = 'not the data that was signed'
148
- signature = Sandal::Util.base64_decode('AdwMgeerwtHoh-l192l60hp9wAHZFVJbLfD_UxMi70cwnZOYaRI1bKPWROc-mZZqwqT2SI-KGDKB34XO0aw_7XdtAG8GaSwFKdCAPZgoXD2YBJZCPEX3xKpRwcdOO8KpEHwJjyqOgzDO7iKvU8vcnwNrmxYbSW9ERBXukOXolLzeO_Jn')
228
+ signature = jwt_base64_decode('AdwMgeerwtHoh-l192l60hp9wAHZFVJbLfD_UxMi70cwnZOYaRI1bKPWROc-mZZqwqT2SI-KGDKB34XO0aw_7XdtAG8GaSwFKdCAPZgoXD2YBJZCPEX3xKpRwcdOO8KpEHwJjyqOgzDO7iKvU8vcnwNrmxYbSW9ERBXukOXolLzeO_Jn')
149
229
 
150
230
  group = OpenSSL::PKey::EC::Group.new('secp521r1')
151
231
  public_key = OpenSSL::PKey::EC.new(group)
@@ -1,7 +1,49 @@
1
1
  require 'helper'
2
2
  require 'openssl'
3
3
 
4
+ rsa_private_key = <<KEY_END
5
+ -----BEGIN RSA PRIVATE KEY-----
6
+ MIIEowIBAAKCAQEA4lt7zb5RlxwLVvw2mOKW06AGrBW3kfUVIkV6lImwqRps6jpZ
7
+ UNBOUkLjqIipXBkKeG6TbL46z4Rw2oEcUTTpOgm/9XEiJP/7nfkK/Sr6cChVLDr5
8
+ sohKnxkADrltdNwUUF0gPlK0REa2wiEvpd00D46Sfxfa5kpe/oYajCyRtesmGyrD
9
+ iD4BKJIaHTal4613l1k8HWhzza4qztbufZ4BMPfHkjyjOBWLsYSU0axI86b5WnxJ
10
+ KZUyghxeL51jYqV5eSeMBC3rr+HHuwdF3ulhvDo0jUxGjFJBG/6ZUheVNAGrAvD8
11
+ 5RV3tp8ukcc02t2l0Z97PWDcZHpiiul+DvvmeQIDAQABAoIBADy56lbiDiWKAojN
12
+ lSAi+e/AaMnV8a+YnpjZJu+emORlEH8uNDP4DmsHQug98aGhnit9DtQHnON7VoNo
13
+ S96FYWSOpQ8F0PE4M5rH62jMFO/uAhuhnseExPA11swcdv745AJDWZkeuvnuNq2S
14
+ FaRb2dGqoCa0kadioGWMOKcOdfDlqcBApTI5IWy67wLJwF7+qTS+BT7BVAreQnQf
15
+ 2qlYXSPWBxpL8iGobBGXQlsWTdiYDalrfyV0mvJaXxwHml3PMxyVrJyIvbc0HgMn
16
+ YqrBgnWrCz7FIU+8OXd4XFGqD09QpHn7SkdLvgXNlSy5fi3SeLN+ClyP1XvrFQYk
17
+ KhfCbwECgYEA/CpsxJEZzwCtvBeHlhNvEV5H2O0HI7Wb+pN5J3QyhMjdOc8KZozx
18
+ 8D3hj6+I2NJM/Uj0V27LH0R92H29fKLjXUjtRwHtrV33PXWQAMzSS8gHOdeQe8iP
19
+ GgdAVDdDJsCR3W5oXEQGj7q8QgLAVdV0X9jZ6BG2MGIbdMi6SUE7DlECgYEA5cyY
20
+ /diePvEcXsEX8AgraOGwH+E4w+d21uJPjh4UpBhiJdrqEdZ2bjKtpl6czKmqu4tx
21
+ R7WNHqRd8LyUpdGHNvQU+kg1Uc1y1hy8HR1x1lZQYMBi4qkB1P6G08RHEL/oilxO
22
+ F1EIxYpwHbW/ZVXzGAyIr4Z9xGMLE5j9jVTsg6kCgYB4JdaxSdmcMdyVtDhcH2Ja
23
+ Siu9hiJSt2NcXwvo6opvji0qMCXqetmD+FgS2DZB6OHaBPq29gk+GqpDjpXMXugq
24
+ OGcl4BtY8V6uH+e/GdhRVztqKfWjpQnaAv55oeMTAcn+UW7UF21w6i5s3Va7Dvtl
25
+ 97LLyjSelQA0ArgP007KIQKBgQDDzDAPGiK7PnUNxzi+LDfQhXurrhrP0MhRD0L5
26
+ tGeh6aS23G/UAwelnUiYGMVBHM98PLOohehX03S3Sfbd0kmDaTT2i8/ig0r1ZEZk
27
+ CFKWbbTOux2GQrps4PHAPdzPSLS6LyvachEnP22H4vPRRAp80zEjXVSLoFgvuotP
28
+ gKyFAQKBgBuMvB9XVILcn8IcZ3ax9B8agU4jeBLScoBV25GvSq7hUaFaNC4WMHzf
29
+ 8av7nDTzlZlLLDMB8rvpz66gMWIWGeU5JWYJaiLMM/JeS9UJOo/6Wn10MvtNSBXH
30
+ 30+kWAHpOSjtxL7tzmMrb46krFS/0iYDFKiLtIPNiacjxlEzBTZL
31
+ -----END RSA PRIVATE KEY-----
32
+ KEY_END
33
+ rsa_public_key = <<KEY_END
34
+ -----BEGIN PUBLIC KEY-----
35
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4lt7zb5RlxwLVvw2mOKW
36
+ 06AGrBW3kfUVIkV6lImwqRps6jpZUNBOUkLjqIipXBkKeG6TbL46z4Rw2oEcUTTp
37
+ Ogm/9XEiJP/7nfkK/Sr6cChVLDr5sohKnxkADrltdNwUUF0gPlK0REa2wiEvpd00
38
+ D46Sfxfa5kpe/oYajCyRtesmGyrDiD4BKJIaHTal4613l1k8HWhzza4qztbufZ4B
39
+ MPfHkjyjOBWLsYSU0axI86b5WnxJKZUyghxeL51jYqV5eSeMBC3rr+HHuwdF3ulh
40
+ vDo0jUxGjFJBG/6ZUheVNAGrAvD85RV3tp8ukcc02t2l0Z97PWDcZHpiiul+Dvvm
41
+ eQIDAQAB
42
+ -----END PUBLIC KEY-----
43
+ KEY_END
44
+
4
45
  describe Sandal::Sig::RS256 do
46
+
5
47
  it 'can sign data and verify signatures' do
6
48
  data = 'Hello RS256'
7
49
  private_key = OpenSSL::PKey::RSA.generate(2048)
@@ -10,9 +52,19 @@ describe Sandal::Sig::RS256 do
10
52
  validator = Sandal::Sig::RS256.new(private_key.public_key)
11
53
  validator.valid?(signature, data).should == true
12
54
  end
55
+
56
+ it 'can use string keys to sign data and verify signatures' do
57
+ data = 'Hello RS256'
58
+ signer = Sandal::Sig::RS256.new(rsa_private_key)
59
+ signature = signer.sign(data)
60
+ validator = Sandal::Sig::RS256.new(rsa_public_key)
61
+ validator.valid?(signature, data).should == true
62
+ end
63
+
13
64
  end
14
65
 
15
66
  describe Sandal::Sig::RS384 do
67
+
16
68
  it 'can sign data and verify signatures' do
17
69
  data = 'Hello RS384'
18
70
  private_key = OpenSSL::PKey::RSA.generate(2048)
@@ -21,9 +73,19 @@ describe Sandal::Sig::RS384 do
21
73
  validator = Sandal::Sig::RS384.new(private_key.public_key)
22
74
  validator.valid?(signature, data).should == true
23
75
  end
76
+
77
+ it 'can use string keys to sign data and verify signatures' do
78
+ data = 'Hello RS384'
79
+ signer = Sandal::Sig::RS384.new(rsa_private_key)
80
+ signature = signer.sign(data)
81
+ validator = Sandal::Sig::RS384.new(rsa_public_key)
82
+ validator.valid?(signature, data).should == true
83
+ end
84
+
24
85
  end
25
86
 
26
87
  describe Sandal::Sig::RS512 do
88
+
27
89
  it 'can sign data and verify signatures' do
28
90
  data = 'Hello RS512'
29
91
  private_key = OpenSSL::PKey::RSA.generate(2048)
@@ -32,4 +94,13 @@ describe Sandal::Sig::RS512 do
32
94
  validator = Sandal::Sig::RS512.new(private_key.public_key)
33
95
  validator.valid?(signature, data).should == true
34
96
  end
97
+
98
+ it 'can use string keys to sign data and verify signatures' do
99
+ data = 'Hello RS512'
100
+ signer = Sandal::Sig::RS512.new(rsa_private_key)
101
+ signature = signer.sign(data)
102
+ validator = Sandal::Sig::RS512.new(rsa_public_key)
103
+ validator.valid?(signature, data).should == true
104
+ end
105
+
35
106
  end
@@ -1,37 +1,77 @@
1
1
  require 'helper'
2
2
  require 'openssl'
3
+ require 'benchmark'
4
+
5
+ include Sandal::Util
3
6
 
4
7
  describe Sandal::Util do
5
8
 
6
- it 'encodes and decodes base64 as per JWT example 6.1' do
7
- src = "{\"iss\":\"joe\",\r\n \"exp\":1300819380,\r\n \"http://example.com/is_root\":true}"
8
- encoded = Sandal::Util.base64_encode(src)
9
- encoded.should == 'eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ'
10
- val = Sandal::Util.base64_decode(encoded)
11
- val.should == src
12
- end
9
+ context '#jwt_base64_decode' do
13
10
 
14
- it 'raises a token error if base64 strings contain padding' do
15
- expect { Sandal::Util.base64_decode('eyJpc3MiOiJq=') }.to raise_error Sandal::TokenError
16
- end
11
+ it 'decodes base64 as per JWT example 6.1' do
12
+ encoded = 'eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ'
13
+ val = jwt_base64_decode(encoded)
14
+ val.should == %!{"iss":"joe",\r\n "exp":1300819380,\r\n "http://example.com/is_root":true}!
15
+ end
17
16
 
18
- it 'compares nil strings as equal' do
19
- Sandal::Util.secure_equals(nil, nil).should == true
20
- end
17
+ it 'raises an ArgumentError if base64 strings contain padding' do
18
+ expect { jwt_base64_decode('eyJpc3MiOiJq=') }.to raise_error ArgumentError
19
+ end
20
+
21
+ it 'raises an ArgumentError if base64 strings are invalid' do
22
+ expect { jwt_base64_decode('not valid base64') }.to raise_error ArgumentError
23
+ end
21
24
 
22
- it 'compares nil strings as unequal to empty strings' do
23
- Sandal::Util.secure_equals(nil, '').should == false
24
- Sandal::Util.secure_equals('', nil).should == false
25
25
  end
26
26
 
27
- it 'compares equal strings as equal' do
28
- Sandal::Util.secure_equals('hello', 'hello').should == true
29
- Sandal::Util.secure_equals('a longer string', 'a longer string').should == true
27
+ context '#jwt_base64_encode' do
28
+
29
+ it 'encodes base64 as per JWT example 6.1' do
30
+ src = %!{"iss":"joe",\r\n "exp":1300819380,\r\n "http://example.com/is_root":true}!
31
+ encoded = jwt_base64_encode(src)
32
+ encoded.should == 'eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ'
33
+ end
34
+
30
35
  end
31
36
 
32
- it 'compares unequal strings as unequal' do
33
- Sandal::Util.secure_equals('hello', 'world').should == false
34
- Sandal::Util.secure_equals('a longer string', 'a different longer string').should == false
37
+ context '#jwt_strings_equal?' do
38
+
39
+ it 'compares nil strings as equal' do
40
+ jwt_strings_equal?(nil, nil).should == true
41
+ end
42
+
43
+ it 'compares empty strings as equal' do
44
+ jwt_strings_equal?('', '').should == true
45
+ end
46
+
47
+ it 'compares nil strings as unequal to empty strings' do
48
+ jwt_strings_equal?(nil, '').should == false
49
+ jwt_strings_equal?('', nil).should == false
50
+ end
51
+
52
+ it 'compares equal strings as equal' do
53
+ jwt_strings_equal?('hello', 'hello').should == true
54
+ jwt_strings_equal?('a longer string', 'a longer string').should == true
55
+ end
56
+
57
+ it 'compares unequal strings as unequal' do
58
+ jwt_strings_equal?('hello', 'world').should == false
59
+ jwt_strings_equal?('a longer string', 'a different longer string').should == false
60
+ end
61
+
62
+ it 'compares strings without short-circuiting', :timing_dependent do
63
+ measure_equals = -> a, b do
64
+ Benchmark.realtime { 100.times { jwt_strings_equal?(a, b) } }
65
+ end
66
+ ref = 'a' * 10000
67
+ cmp1 = ('a' * 9999) + 'b'
68
+ cmp2 = 'a' + ('b' * 9999)
69
+ t1 = measure_equals.(ref, cmp1)
70
+ t2 = measure_equals.(ref, cmp2)
71
+ range = (t1 - t1/20.0)..(t1 + t1/20.0)
72
+ range.should === t2
73
+ end
74
+
35
75
  end
36
76
 
37
77
  end
data/spec/sandal_spec.rb CHANGED
@@ -45,14 +45,20 @@ describe Sandal do
45
45
  expect { Sandal.decode_token(token) }.to raise_error Sandal::ClaimError
46
46
  end
47
47
 
48
- it 'does not raise an error when the expiry date is far in the past but validation is disabled' do
48
+ it 'does not raise an error when the expiry date is in the past but validation is disabled' do
49
49
  token = Sandal.encode_token({ 'exp' => (Time.now - 600).to_i }, nil)
50
- Sandal.decode_token(token) { |header, options| options[:validate_exp] = false }
50
+ Sandal.decode_token(token) do |header, options|
51
+ options[:ignore_exp] = true
52
+ nil
53
+ end
51
54
  end
52
55
 
53
56
  it 'does not raise an error when the expiry date is in the past but within the clock skew' do
54
57
  token = Sandal.encode_token({ 'exp' => (Time.now - 60).to_i }, nil)
55
- Sandal.decode_token(token)
58
+ Sandal.decode_token(token) do |header, options|
59
+ options[:max_clock_skew] = 300
60
+ nil
61
+ end
56
62
  end
57
63
 
58
64
  it 'does not raise an error when the expiry date is valid' do
@@ -70,14 +76,20 @@ describe Sandal do
70
76
  expect { Sandal.decode_token(token) }.to raise_error Sandal::ClaimError
71
77
  end
72
78
 
73
- it 'does not raise an error when the not-before date is far in the future but validation is disabled' do
79
+ it 'does not raise an error when the not-before date is in the future but validation is disabled' do
74
80
  token = Sandal.encode_token({ 'nbf' => (Time.now + 600).to_i }, nil)
75
- Sandal.decode_token(token) { |header, options| options[:validate_nbf] = false }
81
+ Sandal.decode_token(token) do |header, options|
82
+ options[:ignore_nbf] = true
83
+ nil
84
+ end
76
85
  end
77
86
 
78
87
  it 'does not raise an error when the not-before date is in the future but within the clock skew' do
79
88
  token = Sandal.encode_token({ 'nbf' => (Time.now + 60).to_i }, nil)
80
- Sandal.decode_token(token)
89
+ Sandal.decode_token(token) do |header, options|
90
+ options[:max_clock_skew] = 300
91
+ nil
92
+ end
81
93
  end
82
94
 
83
95
  it 'does not raise an error when the not-before is valid' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sandal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Beech
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-05 00:00:00.000000000 Z
11
+ date: 2013-04-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '2.13'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0.7'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0.7'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: coveralls
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -144,8 +158,13 @@ files:
144
158
  - lib/sandal/version.rb
145
159
  - sandal.gemspec
146
160
  - spec/helper.rb
161
+ - spec/sandal/claims_spec.rb
147
162
  - spec/sandal/enc/a128cbc_hs256_spec.rb
148
163
  - spec/sandal/enc/a128gcm_spec.rb
164
+ - spec/sandal/enc/a256cbc_hs512_spec.rb
165
+ - spec/sandal/enc/a256gcm_spec.rb
166
+ - spec/sandal/enc/alg/direct_spec.rb
167
+ - spec/sandal/enc/shared_examples.rb
149
168
  - spec/sandal/sig/es_spec.rb
150
169
  - spec/sandal/sig/hs_spec.rb
151
170
  - spec/sandal/sig/rs_spec.rb
@@ -178,8 +197,13 @@ specification_version: 4
178
197
  summary: A JSON Web Token (JWT) library.
179
198
  test_files:
180
199
  - spec/helper.rb
200
+ - spec/sandal/claims_spec.rb
181
201
  - spec/sandal/enc/a128cbc_hs256_spec.rb
182
202
  - spec/sandal/enc/a128gcm_spec.rb
203
+ - spec/sandal/enc/a256cbc_hs512_spec.rb
204
+ - spec/sandal/enc/a256gcm_spec.rb
205
+ - spec/sandal/enc/alg/direct_spec.rb
206
+ - spec/sandal/enc/shared_examples.rb
183
207
  - spec/sandal/sig/es_spec.rb
184
208
  - spec/sandal/sig/hs_spec.rb
185
209
  - spec/sandal/sig/rs_spec.rb