pkcs11 0.2.3-x86-mingw32 → 0.2.4-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ �.c΅q�©-S���DW�X��|���˶�������<��R��sUS���c0zY���ŦCY��]t䰖�-O�����&�j����'=�X����EE�u����0�r�A��0��)d�=�W�^YX �ʎ�����B �
2
+ ԛ�3�@�U�y;�1��ѓ�,�1+ ����\����P�3ѓ�71K�u�Y<Pv�{V�ūt?cۡ����B��[_==�"��<�� �&G����$E'����%$� �9u�!
@@ -1,3 +1,8 @@
1
+ === 0.2.4 / 2013-04-05
2
+
3
+ * Build and package binary x64 version for Windows in addition to x86.
4
+ * Allow to use big positive numbers (>0x80000000) in 32bit mode (Anton Fedorov)
5
+
1
6
  === 0.2.3 / 2012-01-25
2
7
 
3
8
  * fix C_WaitForSlotEvent to be a Library- instead of a Slot-method
@@ -1,7 +1,9 @@
1
+ {<img src="https://travis-ci.org/larskanis/pkcs11.png?branch=master" alt="Build Status" />}[https://travis-ci.org/larskanis/pkcs11]
2
+
1
3
  = PKCS #11/Ruby Interface
2
4
 
3
5
  * Homepage: http://github.com/larskanis/pkcs11
4
- * API documentation: http://pkcs11.rubyforge.org/pkcs11/
6
+ * API documentation: http://pkcs11.rubyforge.org/pkcs11/frames.html
5
7
 
6
8
  This module allows Ruby programs to interface with "RSA Security Inc.
7
9
  PKCS #11 Cryptographic Token Interface (Cryptoki)".
@@ -33,7 +35,7 @@ While this seems to be true for C, it shouldn't for Ruby.
33
35
  * {PKCS11::Object} represents a key, data or certificate object.
34
36
  * all constants defined in PKCS#11 v2.20 are available in the module {PKCS11}
35
37
  and contain the associated Integer value (CKA_KEY_TYPE, CKK_AES, CKM_SHA_1 etc.)
36
- * also all structs are available in the module {PKCS11} as proper ruby classes
38
+ * also all PKCS#11 v2.20 structs are available in the module {PKCS11} as proper ruby classes
37
39
  ({PKCS11::CK_VERSION}, {PKCS11::CK_OTP_PARAMS} etc.)
38
40
 
39
41
  === Example
@@ -42,19 +44,19 @@ While this seems to be true for C, it shouldn't for Ruby.
42
44
  include PKCS11
43
45
 
44
46
  pkcs11 = PKCS11.open("/path/to/pkcs11.so")
45
- p pkcs11.info
46
- session = pkcs11.active_slots.first.open
47
- session.login(:USER, "1234")
48
- secret_key = session.generate_key(:DES2_KEY_GEN,
49
- :ENCRYPT=>true, :DECRYPT=>true, :SENSITIVE=>true, :TOKEN=>true, :LABEL=>'my key')
50
- cryptogram = session.encrypt( {:DES3_CBC_PAD=>"\0"*8}, secret_key, "some plaintext")
51
- session.logout
52
- session.close
53
-
54
- This opens a PKCS#11 library and prints it's information block.
55
- Then a {PKCS11::Session} to the first active slot of the device is opened and
56
- a login is done on the user account. Now, a 112 bit DES3 key is generated and
57
- some plaintext is encrypted with it. A 8-byte zero IV is used. In many cases method parameters
47
+ p pkcs11.info # => #<PKCS11::CK_INFO cryptokiVersion=...>
48
+ pkcs11.active_slots.first.open do |session|
49
+ session.login(:USER, "1234")
50
+ secret_key = session.generate_key(:DES2_KEY_GEN,
51
+ :ENCRYPT=>true, :DECRYPT=>true, :SENSITIVE=>true, :TOKEN=>true, :LABEL=>'my key')
52
+ cryptogram = session.encrypt( {:DES3_CBC_PAD=>"\0"*8}, secret_key, "some plaintext")
53
+ session.logout
54
+ end
55
+
56
+ This opens a {PKCS11::Library PKCS#11 library} and prints it's {PKCS11::CK_INFO information block}.
57
+ Then a {PKCS11::Session} to the first {PKCS11::Library#active_slots active slot} of the device is opened and
58
+ a {PKCS11::Session#login login} is done on the user account. Now, a 112 bit DES3 {PKCS11::Object key object} is generated and
59
+ some plaintext is {PKCS11::Session#encrypt encrypted} with it. A 8-byte zero IV is used. In many cases method parameters
58
60
  can be Integer (like PKCS11::CKA_LABEL) or, as in the sample, Symbol (:LABEL) which is internally
59
61
  converted.
60
62
 
@@ -76,7 +78,7 @@ The pkcs11 binding fully supports native, background Ruby threads.
76
78
  This of course only applies to Rubinius and Ruby 1.9.x or higher since
77
79
  earlier versions of Ruby do not support native threads.
78
80
 
79
- Calling the Cryptoki library from multiple threads simultaneously,
81
+ According to the standard, calling the Cryptoki library from multiple threads simultaneously,
80
82
  requires to open it with flag PKCS11::CKF_OS_LOCKING_OK.
81
83
  Application-supplied synchronization primitives
82
84
  (CreateMutex, DestroyMutex, LockMutex, UnlockMutex) are not supported.
data/Rakefile CHANGED
@@ -26,7 +26,7 @@ hoe = Hoe.spec 'pkcs11' do
26
26
  extra_dev_deps << ['yard', '>= 0.6']
27
27
  extra_dev_deps << ['rake-compiler', '>= 0.7']
28
28
 
29
- self.url = 'http://github.com/larskanis/pkcs11'
29
+ self.urls = ['http://github.com/larskanis/pkcs11']
30
30
  self.summary = 'PKCS#11 binding for Ruby'
31
31
  self.description = 'This module allows Ruby programs to interface with "RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki)".'
32
32
 
@@ -39,12 +39,12 @@ hoe = Hoe.spec 'pkcs11' do
39
39
  self.rdoc_locations << "larskanis@rack.rubyforge.org:/var/www/gforge-projects/pkcs11/pkcs11/"
40
40
  end
41
41
 
42
- ENV['RUBY_CC_VERSION'] ||= '1.8.7:1.9.2'
42
+ ENV['RUBY_CC_VERSION'] ||= '1.8.7:1.9.3:2.0.0'
43
43
 
44
44
  Rake::ExtensionTask.new('pkcs11_ext', hoe.spec) do |ext|
45
45
  ext.ext_dir = 'ext'
46
46
  ext.cross_compile = true # enable cross compilation (requires cross compile toolchain)
47
- ext.cross_platform = ['i386-mingw32'] # forces the Windows platform instead of the default one
47
+ ext.cross_platform = ['i386-mingw32', 'x64-mingw32'] # forces the Windows platform instead of the default one
48
48
  end
49
49
 
50
50
  file 'ext/extconf.rb' => ['ext/pk11_struct_def.inc', 'ext/pk11_thread_funcs.c']
@@ -66,6 +66,17 @@ end
66
66
  file 'ext/pk11_thread_funcs.c' => 'ext/pk11_thread_funcs.h'
67
67
  file 'ext/pk11.h' => 'ext/pk11_thread_funcs.h'
68
68
 
69
+ task 'copy:pkcs11_ext:i386-mingw32:1.9.3' do |t|
70
+ sh "i686-w64-mingw32-strip -S tmp/i386-mingw32/stage/lib/1.9/pkcs11_ext.so"
71
+ end
72
+ task 'copy:pkcs11_ext:i386-mingw32:2.0.0' do |t|
73
+ sh "i686-w64-mingw32-strip -S tmp/i386-mingw32/stage/lib/2.0/pkcs11_ext.so"
74
+ end
75
+ task 'copy:pkcs11_ext:x64-mingw32:2.0.0' do |t|
76
+ sh "x86_64-w64-mingw32-strip -S tmp/x64-mingw32/stage/lib/2.0/pkcs11_ext.so"
77
+ end
78
+
79
+
69
80
  task :docs_of_vendor_extensions do
70
81
  Dir['pkcs11_*'].each do |dir|
71
82
  chdir(dir) do
data/ext/pk11.c CHANGED
@@ -1376,6 +1376,7 @@ ck_attr_initialize(int argc, VALUE *argv, VALUE self)
1376
1376
  attr->ulValueLen = 0;
1377
1377
  break;
1378
1378
  case T_FIXNUM:
1379
+ case T_BIGNUM:
1379
1380
  attr->pValue = (CK_BYTE_PTR)malloc(sizeof(CK_OBJECT_CLASS));
1380
1381
  *((CK_OBJECT_CLASS*)attr->pValue) = NUM2ULONG(value);
1381
1382
  attr->ulValueLen = sizeof(CK_OBJECT_CLASS);
@@ -1531,6 +1532,7 @@ cCK_MECHANISM_set_pParameter(VALUE self, VALUE value)
1531
1532
  m->ulParameterLen = RSTRING_LEN(value);
1532
1533
  break;
1533
1534
  case T_FIXNUM:
1535
+ case T_BIGNUM:
1534
1536
  ulong_val = NUM2ULONG(value);
1535
1537
  value = rb_obj_freeze(rb_str_new((char*)&ulong_val, sizeof(ulong_val)));
1536
1538
  m->pParameter = RSTRING_PTR(value);
@@ -1,6 +1,6 @@
1
1
  #ifndef RUBY_PK11_VERSION_H
2
2
  #define RUBY_PK11_VERSION_H
3
3
 
4
- static const char *VERSION = "0.2.3";
4
+ static const char *VERSION = "0.2.4";
5
5
 
6
6
  #endif
Binary file
Binary file
Binary file
@@ -134,6 +134,8 @@ module PKCS11
134
134
  PKCS11::CK_MECHANISM.new(mech, param)
135
135
  when Fixnum
136
136
  PKCS11::CK_MECHANISM.new(mechanism)
137
+ when Bignum
138
+ PKCS11::CK_MECHANISM.new(mechanism)
137
139
  else
138
140
  mechanism
139
141
  end
@@ -39,6 +39,9 @@ module PKCS11
39
39
  end
40
40
 
41
41
  alias unwrapped_C_Initialize C_Initialize
42
+ # Initialize a pkcs11 dynamic library.
43
+ #
44
+ # @param [Hash, CK_C_INITIALIZE_ARGS] args A Hash or CK_C_INITIALIZE_ARGS instance with load params.
42
45
  def C_Initialize(args=nil)
43
46
  case args
44
47
  when Hash
@@ -0,0 +1,89 @@
1
+ = PKCS #11/Ruby Interface for Safenet Protect Server HSM
2
+
3
+ * Homepage: http://github.com/larskanis/pkcs11
4
+ * API documentation: http://pkcs11.rubyforge.org/pkcs11/
5
+ * Safenet[http://www.safenet-inc.com] - Protect Server HSM
6
+
7
+ This ruby gem is an add-on to ruby-pkcs11[http://github.com/larskanis/pkcs11] .
8
+ It allowes to use Protect Server specific extensions, which are beyond the PKCS#11 standard.
9
+ That means CKA_EXPORT, CKM_DES3_DERIVE_CBC, structs like CK_DES3_CBC_PARAMS, special functions and so on.
10
+ The module works on the Unix like operating systems and win32.
11
+
12
+ == Requirements
13
+
14
+ * ProtectServer PTKC-SDK to compile the module
15
+ * pkcs11 gem installed (use: <tt>gem install pkcs11</tt> )
16
+
17
+ == Installation
18
+
19
+ gem install pkcs11_protect_server -- --with-protect-server-sdk-dir=/path/to/ETcpsdk
20
+
21
+ This installs the ProtectServer-PKCS#11 extension along with pkcs11-gem either by compiling (Unix)
22
+ or by using the precompiled gem for Win32.
23
+
24
+ git clone git://github.com/larskanis/pkcs11.git
25
+ cd pkcs11_protect_server
26
+ rake gem PROTECT_SERVER_SDK_DIR=/path/to/ETcpsdk
27
+ gem install -l pkg/pkcs11_protect_server -- --with-protect-server-sdk-dir=/path/to/ETcpsdk
28
+
29
+ Downloads and installs the gem from git source.
30
+
31
+ == Usage
32
+
33
+ Open the software emulation library and login to a session:
34
+
35
+ require "rubygems"
36
+ require "pkcs11_protect_server"
37
+
38
+ pkcs11 = PKCS11::ProtectServer::Library.new(:sw)
39
+ p pkcs11.info
40
+ session = pkcs11.active_slots.last.open
41
+ session.login(:USER, "1234")
42
+ # ... crypto operations
43
+ session.logout
44
+ session.close
45
+
46
+ {PKCS11::ProtectServer::Library#initialize} tries to find the library file in
47
+ the standard installation directory on Windows or Linux.
48
+
49
+ == Cross compiling for mswin32
50
+
51
+ Using rake-compiler a cross compiled pkcs11_protect_server.gem can be build on a linux host for
52
+ the win32 platform. There are no runtime dependencies to any but the standard Windows DLLs.
53
+
54
+ Install mingw32. On a debian based system this should work:
55
+
56
+ apt-get install mingw32
57
+
58
+ On MacOS X, if you have MacPorts installed:
59
+
60
+ port install i386-mingw32-gcc
61
+
62
+ Install the rake-compiler:
63
+
64
+ gem install rake-compiler
65
+
66
+ Download and cross compile ruby for win32:
67
+
68
+ rake-compiler cross-ruby VERSION=1.8.7-p352
69
+ rake-compiler cross-ruby VERSION=1.9.2-p290
70
+
71
+ Download and cross compile pkcs11_protect_server for win32:
72
+
73
+ rake cross native gem PROTECT_SERVER_SDK_DIR=/path/to/ETcpsdk
74
+
75
+ If everything works, there should be pkcs11_protect_server-VERSION-x86-mswin32.gem in the pkg
76
+ directory.
77
+
78
+
79
+ == ToDo
80
+
81
+ * implement ProtectServer specific function calls
82
+ * implement possibility to use callbacks
83
+ * add all structs and constants
84
+
85
+ == Authors
86
+ * Lars Kanis <kanis@comcard.de>
87
+
88
+ == Copying
89
+ See MIT-LICENSE included in the package.
@@ -188,7 +188,8 @@ class TestPkcs11Crypt < Test::Unit::TestCase
188
188
  new_key2 = session.derive_key( {:DH_PKCS_DERIVE=>key1.pub_key.to_s(2)}, priv_key2,
189
189
  :CLASS=>CKO_SECRET_KEY, :KEY_TYPE=>CKK_AES, :VALUE_LEN=>16, :ENCRYPT=>true, :DECRYPT=>true, :SENSITIVE=>false )
190
190
 
191
- assert_equal new_key1[0,16], new_key2[:VALUE], 'Exchanged session key should be equal'
191
+ # Some versions of softokn3 use left- and some use rightmost bits of exchanged key
192
+ assert_operator [new_key1[0,16], new_key1[-16..-1]], :include?, new_key2[:VALUE], 'Exchanged session key should be equal'
192
193
  end
193
194
 
194
195
  def test_derive_key2
@@ -150,4 +150,17 @@ class TestPkcs11Structs < Test::Unit::TestCase
150
150
  assert_equal ["2010", "12", "31"], s.values, 'values of CK_DATE'
151
151
  assert_equal( {:day=>"31", :month=>"12", :year=>"2010"}, s.to_hash, 'CK_DATE as hash' )
152
152
  end
153
+
154
+ def test_bignum_attribute
155
+ bignum = [-1].pack("l_").unpack("L_")[0]
156
+ attr = CK_ATTRIBUTE.new(CKA_KEY_TYPE, bignum)
157
+ assert_equal bignum, attr.value, "The bignum value should set"
158
+ end
159
+
160
+ def test_bignum_mechanism
161
+ bignum = [-1].pack("l_").unpack("L_")[0]
162
+ mech = CK_MECHANISM.new(bignum-1, bignum)
163
+ assert_equal bignum-1, mech.mechanism, "The bignum mechanism should set"
164
+ assert_equal [-1].pack("l_"), mech.pParameter, "The bignum parameter is retrieved as String"
165
+ end
153
166
  end
@@ -35,7 +35,7 @@ class TestPkcs11Thread < Test::Unit::TestCase
35
35
  }
36
36
  # This should take some seconds:
37
37
  pub_key, priv_key = session.generate_key_pair(:RSA_PKCS_KEY_PAIR_GEN,
38
- {:MODULUS_BITS=>1408, :PUBLIC_EXPONENT=>[3].pack("N"), :TOKEN=>false},
38
+ {:MODULUS_BITS=>2048, :PUBLIC_EXPONENT=>[3].pack("N"), :TOKEN=>false},
39
39
  {})
40
40
  th.kill
41
41
  assert_operator count, :>, 10, "The second thread should count further concurrent to the key generation"
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pkcs11
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 3
10
- version: 0.2.3
9
+ - 4
10
+ version: 0.2.4
11
11
  platform: x86-mingw32
12
12
  authors:
13
13
  - Ryosuke Kutsuna
@@ -15,53 +15,74 @@ authors:
15
15
  - Lars Kanis
16
16
  autorequire:
17
17
  bindir: bin
18
- cert_chain: []
18
+ cert_chain:
19
+ - |
20
+ -----BEGIN CERTIFICATE-----
21
+ MIIDPDCCAiSgAwIBAgIBADANBgkqhkiG9w0BAQUFADBEMQ0wCwYDVQQDDARsYXJz
22
+ MR8wHQYKCZImiZPyLGQBGRYPZ3JlaXotcmVpbnNkb3JmMRIwEAYKCZImiZPyLGQB
23
+ GRYCZGUwHhcNMTMwMzExMjAyMjIyWhcNMTQwMzExMjAyMjIyWjBEMQ0wCwYDVQQD
24
+ DARsYXJzMR8wHQYKCZImiZPyLGQBGRYPZ3JlaXotcmVpbnNkb3JmMRIwEAYKCZIm
25
+ iZPyLGQBGRYCZGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZb4Uv
26
+ RFJfRu/VEWiy3psh2jinETjiuBrL0NeRFGf8H7iU9+gx/DI/FFhfHGLrDeIskrJx
27
+ YIWDMmEjVO10UUdj7wu4ZhmU++0Cd7Kq9/TyP/shIP3IjqHjVLCnJ3P6f1cl5rxZ
28
+ gqo+d3BAoDrmPk0rtaf6QopwUw9RBiF8V4HqvpiY+ruJotP5UQDP4/lVOKvA8PI9
29
+ P0GmVbFBrbc7Zt5h78N3UyOK0u+nvOC23BvyHXzCtcFsXCoEkt+Wwh0RFqVZdnjM
30
+ LMO2vULHKKHDdX54K/sbVCj9pN9h1aotNzrEyo55zxn0G9PHg/G3P8nMvAXPkUTe
31
+ brhXrfCwWRvOXA4TAgMBAAGjOTA3MAsGA1UdDwQEAwIEsDAJBgNVHRMEAjAAMB0G
32
+ A1UdDgQWBBRAHK81igrXodaDj8a8/BIKsaZrETANBgkqhkiG9w0BAQUFAAOCAQEA
33
+ Iswhcol3ytXthaUH3k5LopZ09viZrZHzAw0QleI3Opl/9QEGJ2BPV9+93iC0OrNL
34
+ hmnxig6vKK1EeJ5PHXJ8hOI3nTZBrOmQcEXNBqyToP1FHMWZqwZ8wiBPXtiCqDBR
35
+ ePQ25J9xFNzQ1ItgzNSpx5cs67QNKrx5woocoBHD6kStFbshZPJx4axl3GbUFQd5
36
+ H//3YdPQOH3jaVeUXhS+pz/gfbx8fhFAtsQ+855A3HO7g2ZRIg/atAp/0MFyn5s5
37
+ 0rq+VHOIPyvxF5khT0mYAcNmZTC8z1yPsqdgwfYNDjsSWwiIRSPUSmJRvfjM8hsW
38
+ mMFp4kPUHbWOqCp2mz9gCA==
39
+ -----END CERTIFICATE-----
19
40
 
20
- date: 2012-01-25 00:00:00 Z
41
+ date: 2013-04-05 00:00:00 Z
21
42
  dependencies:
22
43
  - !ruby/object:Gem::Dependency
23
- name: yard
44
+ name: rdoc
24
45
  prerelease: false
25
46
  requirement: &id001 !ruby/object:Gem::Requirement
26
47
  none: false
27
48
  requirements:
28
- - - ">="
49
+ - - ~>
29
50
  - !ruby/object:Gem::Version
30
- hash: 7
51
+ hash: 19
31
52
  segments:
32
- - 0
33
- - 6
34
- version: "0.6"
53
+ - 3
54
+ - 10
55
+ version: "3.10"
35
56
  type: :development
36
57
  version_requirements: *id001
37
58
  - !ruby/object:Gem::Dependency
38
- name: rake-compiler
59
+ name: yard
39
60
  prerelease: false
40
61
  requirement: &id002 !ruby/object:Gem::Requirement
41
62
  none: false
42
63
  requirements:
43
64
  - - ">="
44
65
  - !ruby/object:Gem::Version
45
- hash: 5
66
+ hash: 7
46
67
  segments:
47
68
  - 0
48
- - 7
49
- version: "0.7"
69
+ - 6
70
+ version: "0.6"
50
71
  type: :development
51
72
  version_requirements: *id002
52
73
  - !ruby/object:Gem::Dependency
53
- name: rdoc
74
+ name: rake-compiler
54
75
  prerelease: false
55
76
  requirement: &id003 !ruby/object:Gem::Requirement
56
77
  none: false
57
78
  requirements:
58
- - - ~>
79
+ - - ">="
59
80
  - !ruby/object:Gem::Version
60
- hash: 19
81
+ hash: 5
61
82
  segments:
62
- - 3
63
- - 10
64
- version: "3.10"
83
+ - 0
84
+ - 7
85
+ version: "0.7"
65
86
  type: :development
66
87
  version_requirements: *id003
67
88
  - !ruby/object:Gem::Dependency
@@ -72,11 +93,11 @@ dependencies:
72
93
  requirements:
73
94
  - - ~>
74
95
  - !ruby/object:Gem::Version
75
- hash: 27
96
+ hash: 7
76
97
  segments:
77
- - 2
78
- - 12
79
- version: "2.12"
98
+ - 3
99
+ - 0
100
+ version: "3.0"
80
101
  type: :development
81
102
  version_requirements: *id004
82
103
  description: "This module allows Ruby programs to interface with \"RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki)\"."
@@ -91,8 +112,9 @@ extensions: []
91
112
  extra_rdoc_files:
92
113
  - History.txt
93
114
  - Manifest.txt
94
- - pkcs11_protect_server/Manifest.txt
95
115
  - README.rdoc
116
+ - pkcs11_protect_server/Manifest.txt
117
+ - pkcs11_protect_server/README_PROTECT_SERVER.rdoc
96
118
  - ext/pk11.c
97
119
  files:
98
120
  - .autotest
@@ -145,8 +167,10 @@ files:
145
167
  - ext/pk11_thread_funcs.h
146
168
  - ext/pk11_thread_funcs.c
147
169
  - pkcs11_protect_server/Manifest.txt
170
+ - pkcs11_protect_server/README_PROTECT_SERVER.rdoc
148
171
  - lib/1.8/pkcs11_ext.so
149
172
  - lib/1.9/pkcs11_ext.so
173
+ - lib/2.0/pkcs11_ext.so
150
174
  homepage: http://github.com/larskanis/pkcs11
151
175
  licenses: []
152
176
 
@@ -177,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
177
201
  requirements: []
178
202
 
179
203
  rubyforge_project: pkcs11
180
- rubygems_version: 1.8.6
204
+ rubygems_version: 1.8.17
181
205
  signing_key:
182
206
  specification_version: 3
183
207
  summary: PKCS#11 binding for Ruby
@@ -0,0 +1,4 @@
1
+ �2p��d�����H��E��`8f�u��d8n�OG
2
+ ��,(ػM�N��90�F"k�u�B�-Z����I��˯8\g��T��b�p�A�e�-���v��0X�kI�o�<[��bǶ|��b����o`^ʽ*
3
+ E17��{*U���+Ŗ�on�+E��]��V@7-S6T5̪�^�Q�������GJR���C���$�ʞ��ЎӢ�{��N��5U�S�jE`L��
4
+ B��%��/h��א^G5c�J�