pkcs11 0.1.0-x86-mswin32
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +23 -0
- data/History.txt +3 -0
- data/MIT-LICENSE +22 -0
- data/Manifest.txt +34 -0
- data/README.rdoc +156 -0
- data/Rakefile +36 -0
- data/ext/extconf.rb +6 -0
- data/ext/include/cryptoki.h +66 -0
- data/ext/include/ct-kip.h +50 -0
- data/ext/include/otp-pkcs11.h +125 -0
- data/ext/include/pkcs-11v2-20a3.h +124 -0
- data/ext/include/pkcs11.h +299 -0
- data/ext/include/pkcs11f.h +912 -0
- data/ext/include/pkcs11t.h +1885 -0
- data/ext/pk11.c +1737 -0
- data/ext/pk11.h +78 -0
- data/ext/pk11_const.c +680 -0
- data/lib/1.8/pkcs11_ext.so +0 -0
- data/lib/1.9/pkcs11_ext.so +0 -0
- data/lib/pkcs11.rb +12 -0
- data/lib/pkcs11/extensions.rb +160 -0
- data/lib/pkcs11/library.rb +63 -0
- data/lib/pkcs11/object.rb +104 -0
- data/lib/pkcs11/session.rb +568 -0
- data/lib/pkcs11/slot.rb +90 -0
- data/sample/firefox_certs.rb +90 -0
- data/sample/nssckbi.rb +51 -0
- data/test/fixtures/softokn/cert8.db +0 -0
- data/test/fixtures/softokn/key3.db +0 -0
- data/test/fixtures/softokn/secmod.db +0 -0
- data/test/helper.rb +43 -0
- data/test/test_pkcs11.rb +36 -0
- data/test/test_pkcs11_crypt.rb +167 -0
- data/test/test_pkcs11_object.rb +94 -0
- data/test/test_pkcs11_session.rb +97 -0
- data/test/test_pkcs11_slot.rb +66 -0
- metadata +122 -0
data/lib/pkcs11/slot.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
module PKCS11
|
2
|
+
# Each slot corresponds to a physical reader or other device interface.
|
3
|
+
# It may contain a token.
|
4
|
+
class Slot
|
5
|
+
def initialize(pkcs11, slot) # :nodoc:
|
6
|
+
@pk, @slot = pkcs11, slot
|
7
|
+
end
|
8
|
+
|
9
|
+
# The slot handle.
|
10
|
+
def to_int
|
11
|
+
@slot
|
12
|
+
end
|
13
|
+
alias to_i to_int
|
14
|
+
|
15
|
+
def inspect # :nodoc:
|
16
|
+
"#<#{self.class} #{@slot.inspect}>"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Obtains information about a particular slot in the system.
|
20
|
+
def C_GetSlotInfo
|
21
|
+
@pk.C_GetSlotInfo(@slot)
|
22
|
+
end
|
23
|
+
alias info C_GetSlotInfo
|
24
|
+
|
25
|
+
# Obtains information about a particular token in the system.
|
26
|
+
def C_GetTokenInfo
|
27
|
+
@pk.C_GetTokenInfo(@slot)
|
28
|
+
end
|
29
|
+
alias token_info C_GetTokenInfo
|
30
|
+
|
31
|
+
# Waits for a slot event, such as token insertion or token removal, to
|
32
|
+
# occur. flags determines whether or not the C_WaitForSlotEvent call blocks (i.e., waits
|
33
|
+
# for a slot event to occur);
|
34
|
+
def C_WaitForSlotEvent(flags)
|
35
|
+
@pk.C_WaitForSlotEvent(@slot, flags)
|
36
|
+
end
|
37
|
+
alias wait_for_event C_WaitForSlotEvent
|
38
|
+
|
39
|
+
# C_GetMechanismList is used to obtain a list of mechanism types supported by a token.
|
40
|
+
def C_GetMechanismList
|
41
|
+
@pk.C_GetMechanismList(@slot).map{|mech|
|
42
|
+
Mechanism.new MECHANISMS, mech
|
43
|
+
}
|
44
|
+
end
|
45
|
+
alias mechanisms C_GetMechanismList
|
46
|
+
|
47
|
+
# Obtains information about a particular mechanism possibly
|
48
|
+
# supported by a token.
|
49
|
+
def C_GetMechanismInfo(mechanism)
|
50
|
+
@pk.C_GetMechanismInfo(@slot, Session.hash_to_mechanism(mechanism))
|
51
|
+
end
|
52
|
+
alias mechanism_info C_GetMechanismInfo
|
53
|
+
|
54
|
+
# Initializes a token. pin is the SO’s initial PIN; label is the label of the token (max 32-byte). This standard allows PIN
|
55
|
+
# values to contain any valid UTF8 character, but the token may impose subset restrictions.
|
56
|
+
def C_InitToken(pin, label)
|
57
|
+
@pk.C_InitToken(@slot, pin, label.ljust(32, " "))
|
58
|
+
end
|
59
|
+
alias init_token C_InitToken
|
60
|
+
|
61
|
+
# Opens a Session between an application and a token in a particular slot.
|
62
|
+
#
|
63
|
+
# flags:: indicates the type of session. Default is read-only,
|
64
|
+
# use <tt>CKF_SERIAL_SESSION | CKF_RW_SESSION</tt> for read-write session.
|
65
|
+
#
|
66
|
+
# * If called with block, yields the block with the session and closes the session
|
67
|
+
# when the is finished.
|
68
|
+
# * If called without block, returns the session object.
|
69
|
+
def C_OpenSession(flags=CKF_SERIAL_SESSION)
|
70
|
+
nr = @pk.C_OpenSession(@slot, flags)
|
71
|
+
sess = Session.new @pk, nr
|
72
|
+
if block_given?
|
73
|
+
begin
|
74
|
+
yield sess
|
75
|
+
ensure
|
76
|
+
sess.close
|
77
|
+
end
|
78
|
+
else
|
79
|
+
sess
|
80
|
+
end
|
81
|
+
end
|
82
|
+
alias open C_OpenSession
|
83
|
+
|
84
|
+
# Closes all sessions an application has with a token.
|
85
|
+
def C_CloseAllSessions
|
86
|
+
@pk.C_CloseAllSessions(@slot)
|
87
|
+
end
|
88
|
+
alias close_all_sessions C_CloseAllSessions
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require "pkcs11"
|
2
|
+
require "openssl"
|
3
|
+
|
4
|
+
LIBSOFTOKEN3_SO = "libsoftokn3.so"
|
5
|
+
LIBNSS_PATHS = %w(
|
6
|
+
/usr/lib64 /usr/lib/ /usr/lib64/nss /usr/lib/nss
|
7
|
+
)
|
8
|
+
unless so_path = ARGV.shift
|
9
|
+
paths = LIBNSS_PATHS.collect{|path| File.join(path, LIBSOFTOKEN3_SO) }
|
10
|
+
so_path = paths.find{|path| File.exist?(path) }
|
11
|
+
end
|
12
|
+
|
13
|
+
dir = Dir.glob(File.expand_path("~/.mozilla/firefox/*.default")).first
|
14
|
+
NSS_INIT_ARGS = [
|
15
|
+
"configDir='#{dir}'",
|
16
|
+
"secmod='secmod.db'",
|
17
|
+
"flags='readOnly'",
|
18
|
+
]
|
19
|
+
|
20
|
+
args = PKCS11::CK_C_INITIALIZE_ARGS.new
|
21
|
+
args.flags = 0
|
22
|
+
args.pReserved = NSS_INIT_ARGS.join(" ")
|
23
|
+
|
24
|
+
pk11 = PKCS11.new(so_path, args)
|
25
|
+
info = pk11.C_GetInfo
|
26
|
+
p [
|
27
|
+
info.cryptokiVersion, info.manufacturerID, info.flags,
|
28
|
+
info.libraryDescription, info.libraryVersion
|
29
|
+
]
|
30
|
+
|
31
|
+
slots = pk11.C_GetSlotList(false)
|
32
|
+
p slots
|
33
|
+
|
34
|
+
slot = 2
|
35
|
+
sinfo = pk11.C_GetSlotInfo(slot)
|
36
|
+
p [
|
37
|
+
sinfo.slotDescription, sinfo.manufacturerID, sinfo.flags,
|
38
|
+
sinfo.hardwareVersion, sinfo.firmwareVersion
|
39
|
+
]
|
40
|
+
mechanisms = pk11.C_GetMechanismList(slot)
|
41
|
+
mechanisms.each do |m|
|
42
|
+
p PKCS11::MECHANISMS[m] || m
|
43
|
+
end
|
44
|
+
|
45
|
+
flags = PKCS11::CKF_SERIAL_SESSION | PKCS11::CKF_RW_SESSION
|
46
|
+
session = pk11.C_OpenSession(slot, flags)
|
47
|
+
p [:session, session]
|
48
|
+
pk11.C_Login(session, PKCS11::CKU_USER, "")
|
49
|
+
|
50
|
+
find_template = [
|
51
|
+
PKCS11::CK_ATTRIBUTE.new(PKCS11::CKA_CLASS, PKCS11::CKO_CERTIFICATE),
|
52
|
+
]
|
53
|
+
p pk11.C_FindObjectsInit(session, find_template)
|
54
|
+
objs = pk11.C_FindObjects(session, 128)
|
55
|
+
objs.each do |handle|
|
56
|
+
template = [
|
57
|
+
PKCS11::CK_ATTRIBUTE.new(PKCS11::CKA_SUBJECT, nil),
|
58
|
+
]
|
59
|
+
attrs = pk11.C_GetAttributeValue(session, handle, template)
|
60
|
+
attrs.each do |attr|
|
61
|
+
p OpenSSL::X509::Name.new(attr.value)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
objs = pk11.C_FindObjectsFinal(session)
|
65
|
+
|
66
|
+
find_template = [
|
67
|
+
PKCS11::CK_ATTRIBUTE.new(PKCS11::CKA_CLASS, PKCS11::CKO_PRIVATE_KEY),
|
68
|
+
PKCS11::CK_ATTRIBUTE.new(PKCS11::CKA_KEY_TYPE, PKCS11::CKK_RSA),
|
69
|
+
]
|
70
|
+
p pk11.C_FindObjectsInit(session, find_template)
|
71
|
+
objs = pk11.C_FindObjects(session, 128)
|
72
|
+
objs.each do |handle|
|
73
|
+
template = [
|
74
|
+
PKCS11::CK_ATTRIBUTE.new(PKCS11::CKA_CLASS, nil),
|
75
|
+
PKCS11::CK_ATTRIBUTE.new(PKCS11::CKA_KEY_TYPE, nil),
|
76
|
+
PKCS11::CK_ATTRIBUTE.new(PKCS11::CKA_ID, nil),
|
77
|
+
PKCS11::CK_ATTRIBUTE.new(PKCS11::CKA_SIGN, nil),
|
78
|
+
PKCS11::CK_ATTRIBUTE.new(PKCS11::CKA_SIGN_RECOVER, nil),
|
79
|
+
PKCS11::CK_ATTRIBUTE.new(PKCS11::CKA_DECRYPT, nil),
|
80
|
+
PKCS11::CK_ATTRIBUTE.new(PKCS11::CKA_EXTRACTABLE, nil),
|
81
|
+
]
|
82
|
+
attrs = pk11.C_GetAttributeValue(session, handle, template)
|
83
|
+
attrs.each do |attr|
|
84
|
+
p [PKCS11::ATTRIBUTES[attr.type], attr.value]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
objs = pk11.C_FindObjectsFinal(session)
|
88
|
+
|
89
|
+
pk11.C_Logout(session)
|
90
|
+
pk11.C_CloseSession(session)
|
data/sample/nssckbi.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require "pkcs11"
|
2
|
+
require "openssl"
|
3
|
+
|
4
|
+
LIBNSSCKBI_SO = "libnssckbi.so"
|
5
|
+
LIBNSS_PATHS = %w(
|
6
|
+
/usr/lib64 /usr/lib /usr/lib64/nss /usr/lib/nss
|
7
|
+
/usr/lib64/xulrunner /usr/lib/xulrunner
|
8
|
+
/usr/local/lib64/xulrunner /usr/local/lib/xulrunner
|
9
|
+
)
|
10
|
+
unless so_name = ARGV[0]
|
11
|
+
paths = LIBNSS_PATHS.collect{|path| File.join(path, LIBNSSCKBI_SO) }
|
12
|
+
so_name = paths.find{|path| File.exist?(path) }
|
13
|
+
end
|
14
|
+
|
15
|
+
pkcs11 = PKCS11.new(so_name)
|
16
|
+
slot = pkcs11.C_GetSlotList(true).first
|
17
|
+
session = pkcs11.C_OpenSession(slot, PKCS11::CKF_SERIAL_SESSION)
|
18
|
+
|
19
|
+
pkcs11.C_FindObjectsInit(session, [
|
20
|
+
PKCS11::CK_ATTRIBUTE.new(PKCS11::CKA_CLASS, PKCS11::CKO_CERTIFICATE)
|
21
|
+
])
|
22
|
+
handles = pkcs11.C_FindObjects(session, 1000)
|
23
|
+
pkcs11.C_FindObjectsFinal(session)
|
24
|
+
|
25
|
+
attribute_types = [
|
26
|
+
PKCS11::CKA_CLASS,
|
27
|
+
PKCS11::CKA_TOKEN, PKCS11::CKA_PRIVATE, PKCS11::CKA_MODIFIABLE,
|
28
|
+
PKCS11::CKA_LABEL, PKCS11::CKA_CERTIFICATE_TYPE,
|
29
|
+
PKCS11::CKA_SUBJECT, PKCS11::CKA_ID, PKCS11::CKA_ISSUER,
|
30
|
+
PKCS11::CKA_SERIAL_NUMBER, PKCS11::CKA_VALUE,
|
31
|
+
]
|
32
|
+
template = attribute_types.collect{|a| PKCS11::CK_ATTRIBUTE.new(a, nil) }
|
33
|
+
handles.each do |handle|
|
34
|
+
attributes = pkcs11.C_GetAttributeValue(session, handle, template)
|
35
|
+
attributes.each do |attribute|
|
36
|
+
type_name = PKCS11::ATTRIBUTES[attribute.type]
|
37
|
+
case attribute.type
|
38
|
+
when PKCS11::CKA_LABEL
|
39
|
+
p [type_name, attribute.value]
|
40
|
+
when PKCS11::CKA_SUBJECT, PKCS11::CKA_ISSUER
|
41
|
+
p [type_name, OpenSSL::X509::Name.new(attribute.value)]
|
42
|
+
when PKCS11::CKA_SERIAL_NUMBER
|
43
|
+
serial = OpenSSL::ASN1.decode(attribute.value).value rescue nil
|
44
|
+
attribute.value.unpack("w").first
|
45
|
+
p [type_name, serial]
|
46
|
+
when PKCS11::CKA_VALUE
|
47
|
+
cert = OpenSSL::X509::Certificate.new(attribute.value)
|
48
|
+
p [cert.serial, cert.not_before, cert.not_after]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
data/test/helper.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require "openssl"
|
2
|
+
|
3
|
+
def open_softokn
|
4
|
+
|
5
|
+
if RUBY_PLATFORM =~ /win32/
|
6
|
+
lLIBSOFTOKEN3_SO = "softokn3.dll"
|
7
|
+
|
8
|
+
# Try to find the firefox path.
|
9
|
+
unless ENV['SOFTOKN_PATH']
|
10
|
+
require 'win32/registry'
|
11
|
+
begin
|
12
|
+
firefox_path = Win32::Registry::HKEY_LOCAL_MACHINE.open('SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\firefox.exe'){|reg|
|
13
|
+
reg.read('Path')[1]
|
14
|
+
}
|
15
|
+
rescue Win32::Registry::Error
|
16
|
+
end
|
17
|
+
if firefox_path
|
18
|
+
ENV['Path'] = ENV['Path'] + ";" + firefox_path
|
19
|
+
so_path = File.join(firefox_path, lLIBSOFTOKEN3_SO)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
else
|
23
|
+
lLIBSOFTOKEN3_SO = "libsoftokn3.so"
|
24
|
+
lLIBNSS_PATHS = %w(
|
25
|
+
/usr/lib64 /usr/lib/ /usr/lib64/nss /usr/lib/nss
|
26
|
+
)
|
27
|
+
unless so_path = ENV['SOFTOKN_PATH']
|
28
|
+
paths = lLIBNSS_PATHS.collect{|path| File.join(path, lLIBSOFTOKEN3_SO) }
|
29
|
+
so_path = paths.find{|path| File.exist?(path) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
raise "#{lLIBSOFTOKEN3_SO} not found - please install firefox or set ENV['SOFTOKN_PATH']" unless so_path
|
34
|
+
|
35
|
+
dir = File.join(File.dirname(__FILE__), 'fixtures/softokn')
|
36
|
+
nNSS_INIT_ARGS = [
|
37
|
+
"configDir='#{dir}'",
|
38
|
+
"secmod='secmod.db'",
|
39
|
+
"flags='readWrite'",
|
40
|
+
]
|
41
|
+
|
42
|
+
pk11 = PKCS11.open(so_path, :flags=>0, :pReserved=>nNSS_INIT_ARGS.join(" "))
|
43
|
+
end
|
data/test/test_pkcs11.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "pkcs11"
|
3
|
+
require "test/helper"
|
4
|
+
|
5
|
+
class TestPkcs11 < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@pk = open_softokn
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
@pk.close
|
12
|
+
@pk = nil
|
13
|
+
GC.start
|
14
|
+
end
|
15
|
+
|
16
|
+
def pk
|
17
|
+
@pk
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_info
|
21
|
+
info = pk.info
|
22
|
+
assert info.inspect =~ /cryptokiVersion=/, 'There should be a version in the library info'
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_slots
|
26
|
+
slots = pk.active_slots
|
27
|
+
assert slots.length>=1, 'Hope there is at least one active slot'
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_close
|
31
|
+
pk.close
|
32
|
+
assert_raise(PKCS11::Error){ pk.info }
|
33
|
+
pk.close
|
34
|
+
assert_raise(PKCS11::Error){ pk.active_slots }
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "pkcs11"
|
3
|
+
require "test/helper"
|
4
|
+
require "openssl"
|
5
|
+
|
6
|
+
class TestPkcs11Crypt < Test::Unit::TestCase
|
7
|
+
include PKCS11
|
8
|
+
|
9
|
+
attr_reader :slots
|
10
|
+
attr_reader :slot
|
11
|
+
attr_reader :session
|
12
|
+
attr_reader :rsa_priv_key
|
13
|
+
attr_reader :rsa_pub_key
|
14
|
+
attr_reader :secret_key
|
15
|
+
|
16
|
+
def setup
|
17
|
+
$pkcs11 ||= open_softokn
|
18
|
+
@slots = pk.active_slots
|
19
|
+
@slot = slots.last
|
20
|
+
@session = slot.open
|
21
|
+
session.login(:USER, "")
|
22
|
+
|
23
|
+
@rsa_pub_key = session.find_objects(:CLASS => CKO_PUBLIC_KEY,
|
24
|
+
:KEY_TYPE => CKK_RSA).first
|
25
|
+
@rsa_priv_key = session.find_objects(:CLASS => CKO_PRIVATE_KEY,
|
26
|
+
:KEY_TYPE => CKK_RSA).first
|
27
|
+
@secret_key = session.create_object(
|
28
|
+
:CLASS=>CKO_SECRET_KEY,
|
29
|
+
:KEY_TYPE=>CKK_DES2,
|
30
|
+
:ENCRYPT=>true, :WRAP=>true, :DECRYPT=>true, :UNWRAP=>true, :TOKEN=>false,
|
31
|
+
:VALUE=>'0123456789abcdef',
|
32
|
+
:LABEL=>'test_secret_key')
|
33
|
+
end
|
34
|
+
|
35
|
+
def teardown
|
36
|
+
@secret_key.destroy
|
37
|
+
@session.logout
|
38
|
+
@session.close
|
39
|
+
end
|
40
|
+
|
41
|
+
def pk
|
42
|
+
$pkcs11
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_endecrypt
|
46
|
+
plaintext1 = "secret text"
|
47
|
+
cryptogram = session.encrypt( :RSA_PKCS, rsa_pub_key, plaintext1)
|
48
|
+
assert cryptogram.length>10, 'The cryptogram should contain some data'
|
49
|
+
assert_not_equal cryptogram, plaintext1, 'The cryptogram should be different to plaintext'
|
50
|
+
|
51
|
+
plaintext2 = session.decrypt( :RSA_PKCS, rsa_priv_key, cryptogram)
|
52
|
+
assert_equal plaintext1, plaintext2, 'Decrypted plaintext should be the same'
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_sign_verify
|
56
|
+
plaintext = "important text"
|
57
|
+
signature = session.sign( :SHA1_RSA_PKCS, rsa_priv_key, plaintext)
|
58
|
+
assert signature.length>10, 'The signature should contain some data'
|
59
|
+
|
60
|
+
signature2 = session.sign( :SHA1_RSA_PKCS, rsa_priv_key){|c|
|
61
|
+
c.update(plaintext[0..3])
|
62
|
+
c.update(plaintext[4..-1])
|
63
|
+
}
|
64
|
+
assert_equal signature, signature2, 'results of one-step and two-step signatures should be equal'
|
65
|
+
|
66
|
+
valid = session.verify( :SHA1_RSA_PKCS, rsa_pub_key, signature, plaintext)
|
67
|
+
assert valid, 'The signature should be correct'
|
68
|
+
|
69
|
+
assert_raise(PKCS11::Error, 'The signature should be invalid on different text') do
|
70
|
+
session.verify( :SHA1_RSA_PKCS, rsa_pub_key, signature, "modified text")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def create_openssl_cipher(pk11_key)
|
75
|
+
rsa = OpenSSL::PKey::RSA.new
|
76
|
+
rsa.n = OpenSSL::BN.new pk11_key[:MODULUS], 2
|
77
|
+
rsa.e = OpenSSL::BN.new pk11_key[:PUBLIC_EXPONENT], 2
|
78
|
+
rsa
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_compare_sign_with_openssl
|
82
|
+
signature = session.sign( :SHA1_RSA_PKCS, rsa_priv_key, "important text")
|
83
|
+
|
84
|
+
osslc = create_openssl_cipher rsa_pub_key
|
85
|
+
valid = osslc.verify(OpenSSL::Digest::SHA1.new, signature, "important text")
|
86
|
+
assert valid, 'The signature should be correct'
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_compare_endecrypt_with_openssl
|
90
|
+
plaintext1 = "secret text"
|
91
|
+
osslc = create_openssl_cipher rsa_pub_key
|
92
|
+
cryptogram = osslc.public_encrypt(plaintext1)
|
93
|
+
|
94
|
+
plaintext2 = session.decrypt( :RSA_PKCS, rsa_priv_key, cryptogram)
|
95
|
+
assert_equal plaintext1, plaintext2, 'Decrypted plaintext should be the same'
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_digest
|
99
|
+
plaintext = "secret text"
|
100
|
+
digest1 = session.digest( :SHA_1, plaintext)
|
101
|
+
digest2 = OpenSSL::Digest::SHA1.new(plaintext).digest
|
102
|
+
assert_equal digest1, digest2, 'Digests should be equal'
|
103
|
+
digest3 = session.digest(:SHA_1){|c|
|
104
|
+
c.update(plaintext[0..3])
|
105
|
+
c.update(plaintext[4..-1])
|
106
|
+
}
|
107
|
+
assert_equal digest1, digest3, 'Digests should be equal'
|
108
|
+
|
109
|
+
digest3 = session.digest(:SHA256){|c|
|
110
|
+
c.update(plaintext)
|
111
|
+
c.digest_key(secret_key)
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_wrap_key
|
116
|
+
wrapped_key_value = session.wrap_key(:DES3_ECB, secret_key, secret_key)
|
117
|
+
assert_equal 16, wrapped_key_value.length, '112 bit 3DES key should have same size wrapped'
|
118
|
+
|
119
|
+
unwrapped_key = session.unwrap_key(:DES3_ECB, secret_key, wrapped_key_value, :CLASS=>CKO_SECRET_KEY, :KEY_TYPE=>CKK_DES2, :ENCRYPT=>true, :DECRYPT=>true)
|
120
|
+
|
121
|
+
secret_key_kcv = session.encrypt( :DES3_ECB, secret_key, "\0"*8)
|
122
|
+
unwrapped_key_kcv = session.encrypt( :DES3_ECB, unwrapped_key, "\0"*8)
|
123
|
+
assert_equal secret_key_kcv, unwrapped_key_kcv, 'Key check values of original and wrapped/unwrapped key should be equal'
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_wrap_private_key
|
127
|
+
wrapped_key_value = session.wrap_key({:DES3_CBC_PAD=>"\0"*8}, secret_key, rsa_priv_key)
|
128
|
+
assert wrapped_key_value.length>100, 'RSA private key should have bigger size wrapped'
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_generate_secret_key
|
132
|
+
key = session.generate_key(:DES2_KEY_GEN,
|
133
|
+
{:ENCRYPT=>true, :WRAP=>true, :DECRYPT=>true, :UNWRAP=>true, :TOKEN=>false, :LOCAL=>true})
|
134
|
+
assert_equal true, key[:LOCAL], 'Keys created on the token should be marked as local'
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_generate_key_pair
|
138
|
+
pub_key, priv_key = session.generate_key_pair(:RSA_PKCS_KEY_PAIR_GEN,
|
139
|
+
{:ENCRYPT=>true, :VERIFY=>true, :WRAP=>true, :MODULUS_BITS=>768, :PUBLIC_EXPONENT=>[3].pack("N"), :TOKEN=>false},
|
140
|
+
{:PRIVATE=>true, :SUBJECT=>'test', :ID=>[123].pack("n"),
|
141
|
+
:SENSITIVE=>true, :DECRYPT=>true, :SIGN=>true, :UNWRAP=>true, :TOKEN=>false, :LOCAL=>true})
|
142
|
+
|
143
|
+
assert_equal true, priv_key[:LOCAL], 'Private keys created on the token should be marked as local'
|
144
|
+
assert_equal priv_key[:CLASS], CKO_PRIVATE_KEY
|
145
|
+
assert_equal pub_key[:CLASS], CKO_PUBLIC_KEY
|
146
|
+
assert_equal true, priv_key[:SENSITIVE], 'Private key should be sensitive'
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_derive_key
|
150
|
+
# Generate DH key for side 1
|
151
|
+
key1 = OpenSSL::PKey::DH.new(512)
|
152
|
+
|
153
|
+
# Generate key side 2 with same prime and base as side 1
|
154
|
+
pub_key2, priv_key2 = session.generate_key_pair(:DH_PKCS_KEY_PAIR_GEN,
|
155
|
+
{:PRIME=>key1.p.to_s(2), :BASE=>key1.g.to_s(2), :TOKEN=>false},
|
156
|
+
{:VALUE_BITS=>512, :DERIVE=>true, :TOKEN=>false})
|
157
|
+
|
158
|
+
# Derive secret DES key for side 1 with OpenSSL
|
159
|
+
new_key1 = key1.compute_key(OpenSSL::BN.new pub_key2[:VALUE], 2)
|
160
|
+
|
161
|
+
# Derive secret DES key for side 2 with softokn3
|
162
|
+
new_key2 = session.derive_key( {:DH_PKCS_DERIVE=>key1.pub_key.to_s(2)}, priv_key2,
|
163
|
+
:CLASS=>CKO_SECRET_KEY, :KEY_TYPE=>CKK_AES, :VALUE_LEN=>16, :ENCRYPT=>true, :DECRYPT=>true, :SENSITIVE=>false )
|
164
|
+
|
165
|
+
assert_equal new_key1[0,16], new_key2[:VALUE], 'Exchanged session key should be equal'
|
166
|
+
end
|
167
|
+
end
|