pkernel_jce 0.3 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +3 -0
- data/Gemfile +0 -0
- data/LICENSE.txt +0 -0
- data/README.md +0 -0
- data/Rakefile +2 -0
- data/jars/bcmail-jdk15on-165.jar +0 -0
- data/jars/bcpg-jdk15on-165.jar +0 -0
- data/jars/bcpkix-jdk15on-165.jar +0 -0
- data/jars/bcprov-ext-jdk15on-165.jar +0 -0
- data/jars/bcprov-jdk15on-165.jar +0 -0
- data/jars/bctls-jdk15on-165.jar +0 -0
- data/lib/pkernel_jce.rb +16 -0
- data/lib/pkernel_jce/bc_helpers.rb +0 -0
- data/lib/pkernel_jce/certificate.rb +450 -30
- data/lib/pkernel_jce/certificate_owner.rb +0 -2
- data/lib/pkernel_jce/converter.rb +21 -0
- data/lib/pkernel_jce/crl.rb +0 -0
- data/lib/pkernel_jce/csr.rb +24 -0
- data/lib/pkernel_jce/error.rb +0 -0
- data/lib/pkernel_jce/global.rb +5 -1
- data/lib/pkernel_jce/identity.rb +557 -82
- data/lib/pkernel_jce/io_utils.rb +2 -0
- data/lib/pkernel_jce/jfile.rb +134 -0
- data/lib/pkernel_jce/jmembuf.rb +7 -0
- data/lib/pkernel_jce/keypair.rb +409 -91
- data/lib/pkernel_jce/ocsp.rb +0 -0
- data/lib/pkernel_jce/provider.rb +26 -4
- data/lib/pkernel_jce/rfc3161.rb +0 -0
- data/lib/pkernel_jce/utils.rb +0 -0
- data/lib/pkernel_jce/version.rb +1 -1
- data/pkernel_jce.gemspec +7 -4
- data/release.job +0 -0
- metadata +42 -27
- data/.ruby-version +0 -1
- data/Gemfile.lock +0 -56
- data/jars/bcmail-jdk15on-157.jar +0 -0
- data/jars/bcpg-jdk15on-157.jar +0 -0
- data/jars/bcpkix-jdk15on-157.jar +0 -0
- data/jars/bcprov-ext-jdk15on-157.jar +0 -0
- data/jars/bcprov-jdk15on-157.jar +0 -0
data/lib/pkernel_jce/io_utils.rb
CHANGED
@@ -0,0 +1,134 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module PkernelJce
|
4
|
+
module JFile
|
5
|
+
def JFile.create_temp_file(opts = { })
|
6
|
+
prefix = opts[:prefix]
|
7
|
+
suffix = opts[:suffix]
|
8
|
+
dir = opts[:directory]
|
9
|
+
java.io.File.createTempFile(prefix,suffix,dir)
|
10
|
+
end # create_temp_file
|
11
|
+
|
12
|
+
def JFile.absolute_path(file)
|
13
|
+
if file.nil?
|
14
|
+
raise PkernelJce::Error, "Cannot get absolute path for file is nil"
|
15
|
+
else
|
16
|
+
file.absolute_path
|
17
|
+
end
|
18
|
+
end # absolute_path
|
19
|
+
|
20
|
+
def JFile.equal?(*files,&block)
|
21
|
+
if files.length > 1
|
22
|
+
|
23
|
+
if block
|
24
|
+
bufLen = block.call(:bufLen)
|
25
|
+
end
|
26
|
+
bufLen = bufLen || 102400
|
27
|
+
|
28
|
+
equal = false
|
29
|
+
result = nil
|
30
|
+
md = java.security.MessageDigest.getInstance("SHA256")
|
31
|
+
files.each do |f|
|
32
|
+
ff = java.io.File.new(f)
|
33
|
+
if ff.exist?
|
34
|
+
buf = Java::byte[bufLen].new
|
35
|
+
fis = java.io.FileInputStream.new(ff)
|
36
|
+
while((read = fis.read(buf,0,buf.length)) != -1)
|
37
|
+
md.update(buf,0,read)
|
38
|
+
end
|
39
|
+
res = md.digest
|
40
|
+
if result.nil?
|
41
|
+
result = res
|
42
|
+
elsif not java.util.Arrays.is_equals(res, result)
|
43
|
+
equal = false
|
44
|
+
break
|
45
|
+
else
|
46
|
+
result = res
|
47
|
+
end
|
48
|
+
|
49
|
+
md.reset
|
50
|
+
else
|
51
|
+
raise PkernelJce::Error, "Given file to compare equal '#{f}' does not exist"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
equal
|
56
|
+
else
|
57
|
+
true
|
58
|
+
end
|
59
|
+
end # equals?
|
60
|
+
|
61
|
+
def JFile.copy(src,dest,opts = { },&block)
|
62
|
+
raise PkernelJce::Error, "Source cannot be nil or empty" if src.nil? or src.empty?
|
63
|
+
raise PkernelJce::Error, "Destination cannot be nil" if dest.nil?
|
64
|
+
|
65
|
+
if src.is_a?(java.io.InputStream)
|
66
|
+
src = src
|
67
|
+
srcLength = src.length
|
68
|
+
elsif src.is_a?(String)
|
69
|
+
# assume is file path?
|
70
|
+
f = java.io.File.new(src)
|
71
|
+
raise PkernelJce::Error, "Given file doesn't exist [#{f.absolute_path}]" if not f.exists
|
72
|
+
raise PkernelJce::Error, "Cannot read source file from a directory [#{f.absolute_path}]" if f.is_directory?
|
73
|
+
src = java.io.FileInputStream.new(f)
|
74
|
+
srcLength = f.length
|
75
|
+
else
|
76
|
+
raise PkernelJce::Error, "Unsupported source file type #{src.class}"
|
77
|
+
end
|
78
|
+
|
79
|
+
if dest.is_a?(java.io.OutputStream)
|
80
|
+
PkernelJce::GConf.instance.glog.debug "Given dest is an OutputStream. Direct use the object."
|
81
|
+
os = dest
|
82
|
+
elsif dest.is_a?(String)
|
83
|
+
# assume is file path?
|
84
|
+
f = java.io.File.new(dest)
|
85
|
+
raise PkernelJce::Error, "Cannot write dest to a directory [#{f.absolute_path}]" if f.is_directory?
|
86
|
+
|
87
|
+
PkernelJce::GConf.instance.glog.debug "Opening given path #{f.absolute_path} to copy file into"
|
88
|
+
os = java.io.FileOutputStream.new(f)
|
89
|
+
|
90
|
+
else
|
91
|
+
raise PkernelJce::Error, "Unsupported destination type #{dest.class}"
|
92
|
+
end
|
93
|
+
|
94
|
+
bufSize = opts[:bufSize] || 1024000
|
95
|
+
b = Java::byte[bufSize].new
|
96
|
+
totalWritten = 0
|
97
|
+
while((read = src.read(b,0,b.length)) != -1)
|
98
|
+
if block
|
99
|
+
block.call(:before_write, { buf: b, from: 0, len: read })
|
100
|
+
end
|
101
|
+
|
102
|
+
os.write(b,0,read)
|
103
|
+
|
104
|
+
totalWritten += read
|
105
|
+
if block
|
106
|
+
block.call(:progress, { total: srcLength, written: read, processed: totalWritten })
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end # copy
|
111
|
+
|
112
|
+
def to_memory(file, opts = { }, &block)
|
113
|
+
raise PkernelJce::Error, "No file given" if file.nil?
|
114
|
+
f = java.io.File.new(file)
|
115
|
+
raise PkernelJce::Error, "Given file #{f.absolute_path} does not exist" if not f.exists
|
116
|
+
raise PkernelJce::Error, "Given file #{f.absolute_path} is a directory" if f.directory?
|
117
|
+
|
118
|
+
total = f.length
|
119
|
+
bufSize = opts[:bufSize] || 1024000
|
120
|
+
b = Java::byte[bufSize].new
|
121
|
+
baos = java.io.ByteArrayOutputStream.new
|
122
|
+
processed = 0
|
123
|
+
fis = java.io.FileInputStream.new(f)
|
124
|
+
while((read = fis.read(b,0,b.length)) != -1)
|
125
|
+
baos.write(b,0,read)
|
126
|
+
processed += read
|
127
|
+
|
128
|
+
block.call(:progress, { total: total, processed: processed, wwritten: read }) if block
|
129
|
+
end
|
130
|
+
|
131
|
+
baos.toByteArray
|
132
|
+
end # to_memory
|
133
|
+
end # module JFile
|
134
|
+
end
|
data/lib/pkernel_jce/keypair.rb
CHANGED
@@ -4,19 +4,11 @@ require 'pkernel'
|
|
4
4
|
require_relative 'provider'
|
5
5
|
require_relative 'global'
|
6
6
|
|
7
|
+
require_relative 'converter'
|
8
|
+
|
7
9
|
module PkernelJce
|
8
10
|
module KeyPair
|
9
11
|
|
10
|
-
def KeyPair.capabilities(type)
|
11
|
-
case type
|
12
|
-
when :rsa
|
13
|
-
when :dsa
|
14
|
-
when :ecc
|
15
|
-
else
|
16
|
-
{}
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
12
|
def generate(algo, conf = {})
|
21
13
|
|
22
14
|
log = conf[:log]
|
@@ -40,6 +32,7 @@ module PkernelJce
|
|
40
32
|
|
41
33
|
kpg.java_send :initialize, [Java::int], len
|
42
34
|
kpg.generate_key_pair
|
35
|
+
|
43
36
|
when "DSA"
|
44
37
|
len = conf[:len] || 2048
|
45
38
|
log.debug "Generating DSA #{len} bits with provider #{prov == nil ? 'default' : prov.name}"
|
@@ -54,6 +47,17 @@ module PkernelJce
|
|
54
47
|
when "ECC","EC"
|
55
48
|
# this only supported by bc?
|
56
49
|
curve = conf[:curve] || "prime256v1"
|
50
|
+
curve.strip!
|
51
|
+
# Fp
|
52
|
+
# X9.62 : prime192v1, prime192v2, prime192v3, prime239v1, prime239v2, prime239v3, prime256v1
|
53
|
+
# SEC : secp192k1, secp192r1, secp224k1, secp224r1, secp256k1, secp256r1, secp384r1, secp521r1
|
54
|
+
# NIST: P-224, P-256, P-384, P-521
|
55
|
+
# F 2m
|
56
|
+
# X9.62 : c2pnb163v1, c2pnb163v2, c2pnb163v3, c2pnb176w1, c2tnb191v1, c2tnb191v2, c2tnb191v3, c2pnb208w1, c2tnb239v1, c2tnb239v2, c2tnb239v3, c2pnb272w1, c2pnb304w1, c2tnb359v1, c2pnb368w1, c2tnb431r1
|
57
|
+
# SEC: sect163k1, sect163r1, sect163r2, sect193r1, sect193r2, sect233k1, sect233r1, sect239k1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1
|
58
|
+
# NIST : B-163, B-233, B-283, B-409, B-571
|
59
|
+
# Teletrust : brainpoolp160r1, brainpoolp160t1, brainpoolp192r1, brainpoolp192t1, brainpoolp224r1, brainpoolp224t1, brainpoolp256r1, brainpoolp256t1, brainpoolp320r1, brainpoolp320t1, brainpoolp384r1, brainpoolp384t1, brainpoolp512r1, brainpoolp512t1
|
60
|
+
# GostR3410-2001-CryptoPro-A, GostR3410-2001-CryptoPro-XchB, GostR3410-2001-CryptoPro-XchA, GostR3410-2001-CryptoPro-C, GostR3410-2001-CryptoPro-B
|
57
61
|
if prov.nil?
|
58
62
|
#kpg = java.security.KeyPairGenerator.getInstance("ECDSA")
|
59
63
|
# default Java does not have ECDSA yet as of Java 8
|
@@ -65,6 +69,48 @@ module PkernelJce
|
|
65
69
|
kpg = java.security.KeyPairGenerator.getInstance("ECDSA", prov)
|
66
70
|
kpg.java_send :initialize, [java.security.spec.AlgorithmParameterSpec, java.security.SecureRandom], java.security.spec.ECGenParameterSpec.new(curve), java.security.SecureRandom.new
|
67
71
|
kpg.generate_key_pair
|
72
|
+
|
73
|
+
when "DH"
|
74
|
+
|
75
|
+
len = conf[:len] || 1024
|
76
|
+
certainty = conf[:certainty] || org.bouncycastle.jcajce.provider.asymmetric.util.PrimeCertaintyCalculator.getDefaultCertainty(len)
|
77
|
+
# for DH key, these two values can be shared...
|
78
|
+
# https://news.ycombinator.com/item?id=10397326
|
79
|
+
# this two values shall be in hex
|
80
|
+
p = conf[:p]
|
81
|
+
g = conf[:g]
|
82
|
+
|
83
|
+
if not p.nil?
|
84
|
+
p = java.math.BigInteger.new(p,16)
|
85
|
+
end
|
86
|
+
|
87
|
+
if not g.nil?
|
88
|
+
g = java.math.BigInteger.new(g,16)
|
89
|
+
end
|
90
|
+
|
91
|
+
prov = PkernelJce::Provider::DefProvider
|
92
|
+
|
93
|
+
if not (p.nil? and g.nil?)
|
94
|
+
log.debug "Generating DH key from given p and g"
|
95
|
+
gparam = org.bouncycastle.crypto.params.DHParameters.new(p,g)
|
96
|
+
|
97
|
+
else
|
98
|
+
|
99
|
+
log.debug "Generating DH #{len} bits with provider #{prov.name}, certainty : #{certainty}."
|
100
|
+
if len > 1024
|
101
|
+
log.warn "Generating #{len} bits of DH key may take some time... so be patient..."
|
102
|
+
end
|
103
|
+
|
104
|
+
dhParamGen = org.bouncycastle.crypto.generators.DHParametersGenerator.new
|
105
|
+
dhParamGen.init(len,certainty, java.security.SecureRandom.new)
|
106
|
+
gparam = dhParamGen.generate_parameters
|
107
|
+
end
|
108
|
+
|
109
|
+
kgParam = org.bouncycastle.crypto.params.DHKeyGenerationParameters.new(java.security.SecureRandom.new, gparam)
|
110
|
+
kpg = org.bouncycastle.crypto.generators.DHKeyPairGenerator.new
|
111
|
+
kpg.init(kgParam)
|
112
|
+
kpg.generateKeyPair
|
113
|
+
|
68
114
|
else
|
69
115
|
log.error "Unknown '#{algo}' for java keypair"
|
70
116
|
raise PkernelJce::Error, "Unknown algo '#{algo}' for java keypair"
|
@@ -74,20 +120,28 @@ module PkernelJce
|
|
74
120
|
#
|
75
121
|
|
76
122
|
def KeyPair.key_type(key)
|
77
|
-
|
123
|
+
|
124
|
+
case key
|
125
|
+
when java.security.KeyPair, org.bouncycastle.crypto.AsymmetricCipherKeyPair
|
78
126
|
privKey = key.getPrivate
|
79
127
|
else
|
80
128
|
# given is private key
|
81
|
-
|
129
|
+
if KeyPair.is_private_key?(key)
|
130
|
+
privKey = key
|
131
|
+
else
|
132
|
+
raise PkernelJce::Error, "key_type API only check for keypair and private key. For public key type shall call pub_key_type() API. Given key is #{key}"
|
133
|
+
end
|
82
134
|
end
|
83
|
-
|
135
|
+
|
84
136
|
case privKey
|
85
|
-
when java.security.interfaces.RSAPrivateCrtKey
|
137
|
+
when java.security.interfaces.RSAPrivateCrtKey, Java::OrgBouncycastleCryptoParams::RSAPrivateCrtKeyParameters
|
86
138
|
Pkernel::KeyPair::RSA_KEY_NAME
|
87
|
-
when Java::sun.security.provider.DSAPrivateKey, org.bouncycastle.jcajce.provider.asymmetric.dsa.BCDSAPrivateKey
|
139
|
+
when Java::sun.security.provider.DSAPrivateKey, org.bouncycastle.jcajce.provider.asymmetric.dsa.BCDSAPrivateKey, Java::OrgBouncycastleCryptoParams::DSAPrivateKeyParameters
|
88
140
|
Pkernel::KeyPair::DSA_KEY_NAME
|
89
|
-
when org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey
|
141
|
+
when org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey, Java::OrgBouncycastleCryptoParams::ECPrivateKeyParameters, Java::SunSecurityEc::ECPrivateKeyImpl
|
90
142
|
Pkernel::KeyPair::EC_KEY_NAME
|
143
|
+
when org.bouncycastle.crypto.params.DHPrivateKeyParameters
|
144
|
+
Pkernel::KeyPair::DH_KEY_NAME
|
91
145
|
else
|
92
146
|
raise PkernelJce::Error, "Unknown priv key type '#{privKey.class}'"
|
93
147
|
end
|
@@ -96,6 +150,19 @@ module PkernelJce
|
|
96
150
|
# end get_key_type
|
97
151
|
#
|
98
152
|
|
153
|
+
def KeyPair.is_private_key?(key)
|
154
|
+
if key.nil?
|
155
|
+
false
|
156
|
+
else
|
157
|
+
case key
|
158
|
+
when java.security.interfaces.RSAPrivateCrtKey, Java::sun.security.provider.DSAPrivateKey, org.bouncycastle.jcajce.provider.asymmetric.dsa.BCDSAPrivateKey, org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey, Java::OrgBouncycastleCryptoParams::RSAPrivateCrtKeyParameters, Java::OrgBouncycastleCryptoParams::DSAPrivateKeyParameters, Java::OrgBouncycastleCryptoParams::ECPrivateKeyParameters, Java::SunSecurityEc::ECPrivateKeyImpl, org.bouncycastle.crypto.AsymmetricCipherKeyPair, java.security.KeyPair
|
159
|
+
true
|
160
|
+
else
|
161
|
+
false
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
99
166
|
def KeyPair.pub_key_type(key)
|
100
167
|
if key.java_kind_of?(java.security.KeyPair)
|
101
168
|
pubKey = key.public
|
@@ -110,8 +177,10 @@ module PkernelJce
|
|
110
177
|
Pkernel::KeyPair::RSA_KEY_NAME
|
111
178
|
when Java::sun.security.provider.DSAPublicKey, Java::OrgBouncycastleJcajceProviderAsymmetricDsa::BCDSAPublicKey
|
112
179
|
Pkernel::KeyPair::DSA_KEY_NAME
|
113
|
-
when Java::OrgBouncycastleJcajceProviderAsymmetricEc::BCECPublicKey
|
180
|
+
when Java::OrgBouncycastleJcajceProviderAsymmetricEc::BCECPublicKey, Java::SunSecurityEc::ECPublicKeyImpl
|
114
181
|
Pkernel::KeyPair::EC_KEY_NAME
|
182
|
+
when org.bouncycastle.crypto.params.DHPublicKeyParameters
|
183
|
+
Pkernel::KeyPair::DH_KEY_NAME
|
115
184
|
else
|
116
185
|
raise PkernelJce::Error, "Unknown pub key type '#{pubKey.class}'"
|
117
186
|
end
|
@@ -134,19 +203,6 @@ module PkernelJce
|
|
134
203
|
end
|
135
204
|
end
|
136
205
|
|
137
|
-
def KeyPair.is_private_key?(key)
|
138
|
-
if key.nil?
|
139
|
-
false
|
140
|
-
else
|
141
|
-
case key
|
142
|
-
when java.security.interfaces.RSAPrivateCrtKey, Java::sun.security.provider.DSAPrivateKey, org.bouncycastle.jcajce.provider.asymmetric.dsa.BCDSAPrivateKey, org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey
|
143
|
-
true
|
144
|
-
else
|
145
|
-
false
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
206
|
def KeyPair.is_keypair?(key)
|
151
207
|
if key.nil?
|
152
208
|
false
|
@@ -160,7 +216,7 @@ module PkernelJce
|
|
160
216
|
end
|
161
217
|
end
|
162
218
|
|
163
|
-
def KeyPair.public_key(priv)
|
219
|
+
def KeyPair.public_key(priv, opts = { })
|
164
220
|
if priv.nil?
|
165
221
|
raise PkernelJce::Error, "Cannot derive public key from nil key"
|
166
222
|
else
|
@@ -177,11 +233,40 @@ module PkernelJce
|
|
177
233
|
prov = PkernelJce::Provider.add_default
|
178
234
|
java.security.KeyFactory.getInstance("DSA",prov).generatePublic(spec)
|
179
235
|
when Pkernel::KeyPair::EC_KEY_NAME
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
236
|
+
case priv
|
237
|
+
# No way to recover public key using SUN provider yet
|
238
|
+
#when Java::SunSecurityEc::ECPrivateKeyImpl
|
239
|
+
# this uses BC also so add provider first
|
240
|
+
#pProv = PkernelJce::Provider.add_default
|
241
|
+
#curveName = priv.params.name.split(" ")[0]
|
242
|
+
|
243
|
+
#ecSpec = org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util.convertSpec(priv.params,false)
|
244
|
+
#q = ecSpec.g.to_java.multiply(priv.s)
|
245
|
+
#bcW = ecSpec.curve.decodePoint(q.getEncoded(false))
|
246
|
+
##w = org.bouncycastle.math.ec.ECPoint.new(bcW.getAffineXCoord.toBigInteger, bcW.getAffineYCoord.toBigInteger)
|
247
|
+
#w = java.security.spec.ECPoint.new(bcW.getAffineXCoord.toBigInteger, bcW.getAffineYCoord.toBigInteger)
|
248
|
+
#curveParam = org.bouncycastle.jce.ECNamedCurveTable.getParameterSpec(curveName)
|
249
|
+
##keySpec = org.bouncycastle.jce.spec.ECPublicKeySpec.new(w,curveParam)
|
250
|
+
#keySpec = java.security.spec.ECPublicKeySpec.new(w,curveParam)
|
251
|
+
|
252
|
+
##java.security.KeyFactory.getInstance("EC",pProv).generatePublic(keySpec)
|
253
|
+
|
254
|
+
when Java::OrgBouncycastleCryptoParams::ECPrivateKeyParameters, org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey
|
255
|
+
d = priv.d
|
256
|
+
q = priv.parameters.g.to_java.multiply(d)
|
257
|
+
pubSpec = org.bouncycastle.jce.spec.ECPublicKeySpec.new(q, priv.parameters)
|
258
|
+
prov = PkernelJce::Provider.add_default
|
259
|
+
java.security.KeyFactory.getInstance("EC",prov).generatePublic(pubSpec)
|
260
|
+
else
|
261
|
+
raise PkernelJce::Error, "Haven't figure out how to convert #{priv.class} into public key yet..."
|
262
|
+
end
|
263
|
+
#p priv
|
264
|
+
#p priv.methods.sort
|
265
|
+
#d = priv.d;
|
266
|
+
#q = priv.parameters.g.to_java.multiply(d);
|
267
|
+
#pubSpec = org.bouncycastle.jce.spec.ECPublicKeySpec.new(q, priv.parameters);
|
268
|
+
#prov = PkernelJce::Provider.add_default
|
269
|
+
#java.security.KeyFactory.getInstance("EC",prov).generatePublic(pubSpec)
|
185
270
|
else
|
186
271
|
end
|
187
272
|
elsif priv.java_kind_of?(java.security.PublicKey)
|
@@ -200,6 +285,21 @@ module PkernelJce
|
|
200
285
|
# end public_key(priv)
|
201
286
|
#
|
202
287
|
|
288
|
+
#
|
289
|
+
# Compare 2 public keys
|
290
|
+
#
|
291
|
+
def KeyPair.is_public_key_equals?(pub1, pub2)
|
292
|
+
if not (pub1.nil? and pub2.nil?)
|
293
|
+
pubkey1 = KeyPair.public_key(pub1)
|
294
|
+
pubkey2 = KeyPair.public_key(pub2)
|
295
|
+
|
296
|
+
pubkey1.equals(pubkey2)
|
297
|
+
|
298
|
+
else
|
299
|
+
false
|
300
|
+
end
|
301
|
+
end # is_public_key_equals?
|
302
|
+
|
203
303
|
# harmonize the private key acquiring
|
204
304
|
# There are BC and Java, keypair and private key
|
205
305
|
def KeyPair.private_key(kp)
|
@@ -247,7 +347,48 @@ module PkernelJce
|
|
247
347
|
end
|
248
348
|
end
|
249
349
|
|
250
|
-
def
|
350
|
+
def KeyPair.key_size(kp)
|
351
|
+
if KeyPair.is_keypair?(kp)
|
352
|
+
type = PkernelJce::KeyPair.key_type(KeyPair.private_key(kp))
|
353
|
+
elsif KeyPair.is_public_key?(kp)
|
354
|
+
type = PkernelJce::KeyPair.pub_key_type(kp)
|
355
|
+
elsif Certificate.is_cert_object?(kp)
|
356
|
+
type = PkernelJce::KeyPair.pub_key_type(Certificate.public_key(kp))
|
357
|
+
elsif KeyPair.is_private_key?(kp)
|
358
|
+
type = PkernelJce::KeyPair.key_type(kp)
|
359
|
+
else
|
360
|
+
raise PkernelJce::Error, "Unknown key type to derive signing key algo from"
|
361
|
+
end
|
362
|
+
|
363
|
+
case type
|
364
|
+
when Pkernel::KeyPair::RSA_KEY_NAME
|
365
|
+
if PkernelJce::KeyPair::is_keypair?(kp)
|
366
|
+
rsaKey = PkernelJce::KeyPair.private_key(kp)
|
367
|
+
elsif PkernelJce::KeyPair::is_private_key?(kp)
|
368
|
+
rsaKey = PkernelJce::KeyPair.private_key(kp)
|
369
|
+
elsif PkernelJce::KeyPair::is_public_key?(kp)
|
370
|
+
rsaKey = PkernelJce::KeyPair::public_key(kp)
|
371
|
+
end
|
372
|
+
|
373
|
+
rsaKey.modulus.bit_length
|
374
|
+
|
375
|
+
when Pkernel::KeyPair::DSA_KEY_NAME
|
376
|
+
if PkernelJce::KeyPair::is_keypair?(kp)
|
377
|
+
dsaKey = PkernelJce::KeyPair.private_key(kp)
|
378
|
+
elsif PkernelJce::KeyPair::is_private_key?(kp)
|
379
|
+
dsaKey = PkernelJce::KeyPair.private_key(kp)
|
380
|
+
elsif PkernelJce::KeyPair::is_public_key?(kp)
|
381
|
+
dsaKey = PkernelJce::KeyPair::public_key(kp)
|
382
|
+
end
|
383
|
+
|
384
|
+
dsaKey.params.p.bit_length
|
385
|
+
|
386
|
+
when Pkernel::KeyPair::EC_KEY_NAME
|
387
|
+
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
def dump(keypair, options = {} ,&block)
|
251
392
|
if keypair.nil?
|
252
393
|
raise PkernelJce::Error, "Keypair is nil during writing PEM"
|
253
394
|
end
|
@@ -257,43 +398,115 @@ module PkernelJce
|
|
257
398
|
file = options[:file]
|
258
399
|
pass = options[:password]
|
259
400
|
|
260
|
-
binOut = java.io.ByteArrayOutputStream.new
|
401
|
+
#binOut = java.io.ByteArrayOutputStream.new
|
261
402
|
|
262
|
-
if
|
263
|
-
|
264
|
-
# return binary to caller
|
265
|
-
writer = org.bouncycastle.openssl.jcajce.JcaPEMWriter.new(java.io.OutputStreamWriter.new(binOut));
|
266
|
-
else
|
267
|
-
PkernelJce::GConf.instance.glog.debug "Dump output to file '#{file}'"
|
268
|
-
out = java.io.FileOutputStream.new(file)
|
269
|
-
writer = org.bouncycastle.openssl.jcajce.JcaPEMWriter.new(java.io.OutputStreamWriter.new(out));
|
403
|
+
if (pass.nil? or pass.empty?) and block
|
404
|
+
pass = block.call(:prompt_pass)
|
270
405
|
end
|
271
406
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
407
|
+
## BC API
|
408
|
+
#if file.nil?
|
409
|
+
# PkernelJce::GConf.instance.glog.debug "Dump output to memory"
|
410
|
+
# # return binary to caller
|
411
|
+
# writer = org.bouncycastle.openssl.jcajce.JcaPEMWriter.new(java.io.OutputStreamWriter.new(binOut));
|
412
|
+
#else
|
413
|
+
# PkernelJce::GConf.instance.glog.debug "Dump output to file '#{file}'"
|
414
|
+
# out = java.io.FileOutputStream.new(file)
|
415
|
+
# writer = org.bouncycastle.openssl.jcajce.JcaPEMWriter.new(java.io.OutputStreamWriter.new(out));
|
416
|
+
#end
|
417
|
+
|
418
|
+
#begin
|
419
|
+
# if pass.nil? or pass.empty?
|
420
|
+
# writer.writeObject(keypair.getPrivate)
|
421
|
+
# else
|
422
|
+
# builder = org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder.new(org.bouncycastle.openssl.PKCS8Generator::AES_256_CBC).setProvider(PkernelJce::Provider::DefProvider).setPasssword(pass.to_java.toCharArray());
|
423
|
+
|
424
|
+
# pkcs8 = org.bouncycastle.openssl.jcajce.JcaPKCS8Generator.new(keypair.getPrivate, builder.build);
|
425
|
+
# writer.writeObject(pkcs8)
|
426
|
+
# end
|
427
|
+
#ensure
|
428
|
+
# writer.flush
|
429
|
+
# writer.close
|
430
|
+
#end
|
431
|
+
|
432
|
+
# Java API
|
433
|
+
prov = options[:provider]
|
434
|
+
if not prov.nil?
|
435
|
+
prov = PkernelJce::Provider.add_provider(prov)
|
436
|
+
end
|
277
437
|
|
278
|
-
|
279
|
-
|
438
|
+
if pass.nil? or pass.empty?
|
439
|
+
PkernelJce::GConf.instance.glog.warn "Dumping of private key without password!"
|
440
|
+
encInfo = java.security.spec.PKCS8EncodedKeySpec.new(PkernelJce::KeyPair.private_key(keypair).encoded)
|
441
|
+
else
|
442
|
+
pbeAlgo = options[:pbeAlgo]
|
443
|
+
# todo test this algo with openssl and see...
|
444
|
+
pbeAlgo = "PBEWithSHA1AndRC4_128" if pbeAlgo.nil? or pbeAlgo.empty?
|
445
|
+
|
446
|
+
salt = Java::byte[32].new
|
447
|
+
Java::JavaSecurity::SecureRandom.new.nextBytes(salt)
|
448
|
+
pbeParamSpec = Java::JavaxCryptoSpec::PBEParameterSpec.new(salt,88)
|
449
|
+
pbeKeySpec = Java::JavaxCryptoSpec::PBEKeySpec.new(pass.to_java.toCharArray)
|
450
|
+
if not prov.nil?
|
451
|
+
|
452
|
+
secKeyFact = Java::JavaxCrypto::SecretKeyFactory.getInstance(pbeAlgo,prov)
|
453
|
+
pbeKey = secKeyFact.generateSecret(pbeKeySpec)
|
454
|
+
cipher = Java::JavaxCrypto::Cipher.getInstance(pbeAlgo,prov)
|
455
|
+
cipher.init(Java::JavaxCrypto::Cipher::ENCRYPT_MODE,pbeKey,pbeParamSpec)
|
456
|
+
output = cipher.doFinal(PkernelJce::KeyPair.private_key(keypair).getEncoded())
|
457
|
+
algoParam = Java::JavaSecurity::AlgorithmParameters.getInstance(pbeAlgo,prov)
|
458
|
+
|
459
|
+
else
|
460
|
+
secKeyFact = Java::JavaxCrypto::SecretKeyFactory.getInstance(pbeAlgo)
|
461
|
+
pbeKey = secKeyFact.generateSecret(pbeKeySpec)
|
462
|
+
cipher = Java::JavaxCrypto::Cipher.getInstance(pbeAlgo)
|
463
|
+
cipher.init(Java::JavaxCrypto::Cipher::ENCRYPT_MODE,pbeKey,pbeParamSpec)
|
464
|
+
output = cipher.doFinal(PkernelJce::KeyPair.private_key(keypair).getEncoded())
|
465
|
+
algoParam = Java::JavaSecurity::AlgorithmParameters.getInstance(pbeAlgo)
|
280
466
|
end
|
281
|
-
|
282
|
-
|
283
|
-
|
467
|
+
|
468
|
+
algoParam.init(pbeParamSpec)
|
469
|
+
encPrivInfo = Java::JavaxCrypto::EncryptedPrivateKeyInfo.new(algoParam,output)
|
470
|
+
encInfo = encPrivInfo
|
284
471
|
end
|
285
472
|
|
286
|
-
|
287
|
-
|
473
|
+
cont = []
|
474
|
+
keyType = KeyPair.key_type(keypair)
|
475
|
+
case keyType
|
476
|
+
when Pkernel::KeyPair::RSA_KEY_NAME
|
477
|
+
cont << "-----BEGIN RSA PRIVATE KEY-----"
|
478
|
+
cont << PkernelJce::Converter.to_mb64(encInfo.getEncoded)
|
479
|
+
cont << "-----END RSA PRIVATE KEY-----"
|
480
|
+
when Pkernel::KeyPair::DSA_KEY_NAME
|
481
|
+
cont << "-----BEGIN DSA PRIVATE KEY-----"
|
482
|
+
cont << PkernelJce::Converter.to_mb64(encInfo.getEncoded)
|
483
|
+
cont << "-----END DSA PRIVATE KEY-----"
|
484
|
+
when Pkernel::KeyPair::EC_KEY_NAME
|
485
|
+
cont << "-----BEGIN EC PRIVATE KEY-----"
|
486
|
+
cont << PkernelJce::Converter.to_mb64(encInfo.getEncoded)
|
487
|
+
cont << "-----END EC PRIVATE KEY-----"
|
488
|
+
else
|
489
|
+
raise PkernelJce::Error, "Unsupported key type #{keyType}"
|
288
490
|
end
|
491
|
+
|
492
|
+
pkcs8Envelope = cont.join("\n")
|
493
|
+
|
494
|
+
#pkcs8Envelope = encPrivInfo.getEncoded()
|
495
|
+
|
496
|
+
if not file.nil?
|
497
|
+
fos = java.io.FileOutputStream.new(file)
|
498
|
+
fos.write(pkcs8Envelope.to_java.getBytes)
|
499
|
+
fos.flush
|
500
|
+
fos.close
|
501
|
+
end
|
502
|
+
|
503
|
+
pkcs8Envelope
|
504
|
+
|
289
505
|
end
|
290
506
|
# end dump
|
291
507
|
|
292
508
|
def load(opts = {}, &block)
|
293
|
-
|
294
|
-
#if is.nil?
|
295
|
-
# raise PkernelJce::Error, "InputStream not given"
|
296
|
-
#end
|
509
|
+
|
297
510
|
file = opts[:file]
|
298
511
|
bin = opts[:bin]
|
299
512
|
|
@@ -319,40 +532,145 @@ module PkernelJce
|
|
319
532
|
raise PkernelJce::Error, "No 'file' or 'bin' is defined to load keypair"
|
320
533
|
end
|
321
534
|
|
322
|
-
prov = opts[:provider]
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
535
|
+
prov = opts[:provider]
|
536
|
+
if not prov.nil?
|
537
|
+
prov = PkernelJce::Provider.add_provider(prov)
|
538
|
+
end
|
539
|
+
|
540
|
+
pass = opts[:password]
|
541
|
+
if (pass.nil? or pass.empty?) and block
|
542
|
+
pass = block.call(:prompt_pass)
|
543
|
+
end
|
544
|
+
|
545
|
+
cont = String.from_java_bytes(baos.toByteArray)
|
546
|
+
cont.gsub!("-----BEGIN RSA PRIVATE KEY-----","")
|
547
|
+
cont.gsub!("-----END RSA PRIVATE KEY-----","")
|
548
|
+
cont.gsub!("-----BEGIN DSA PRIVATE KEY-----","")
|
549
|
+
cont.gsub!("-----END DSA PRIVATE KEY-----","")
|
550
|
+
cont.gsub!("-----BEGIN EC PRIVATE KEY-----","")
|
551
|
+
cont.gsub!("-----END EC PRIVATE KEY-----","")
|
552
|
+
econt = PkernelJce::Converter.from_mb64(cont)
|
553
|
+
#fos = java.io.FileOutputStream.new("test.bin")
|
554
|
+
#fos.write(econt)
|
555
|
+
#fos.flush
|
556
|
+
#fos.close
|
557
|
+
|
558
|
+
# Java API
|
559
|
+
if not (pass.nil? or pass.empty?)
|
560
|
+
|
561
|
+
PkernelJce::GConf.instance.glog.debug "Password protected envelope"
|
562
|
+
encPrivInfo = Java::JavaxCrypto::EncryptedPrivateKeyInfo.new(econt)
|
563
|
+
cipher = Java::JavaxCrypto::Cipher::getInstance(encPrivInfo.getAlgName())
|
564
|
+
pbeKeySpec = Java::JavaxCryptoSpec::PBEKeySpec.new(pass.to_java.toCharArray)
|
565
|
+
if(prov != nil)
|
566
|
+
secKeyFact = Java::JavaxCrypto::SecretKeyFactory.getInstance(encPrivInfo.getAlgName(),prov)
|
567
|
+
else
|
568
|
+
secKeyFact = Java::JavaxCrypto::SecretKeyFactory.getInstance(encPrivInfo.getAlgName())
|
338
569
|
end
|
339
|
-
|
340
|
-
|
570
|
+
pbeKey = secKeyFact.generateSecret(pbeKeySpec)
|
571
|
+
|
572
|
+
cipher.init(Java::JavaxCrypto::Cipher::DECRYPT_MODE, pbeKey,encPrivInfo.getAlgParameters())
|
341
573
|
|
342
|
-
|
343
|
-
|
574
|
+
pkcs8KeySpec = encPrivInfo.getKeySpec(cipher)
|
575
|
+
#privKeyParam = Java::OrgBouncycastleCryptoUtil::PrivateKeyFactory::createKey(pkcs8KeySpec)
|
344
576
|
else
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
577
|
+
pkcs8KeySpec = java.security.spec.PKCS8EncodedKeySpec.new(econt)
|
578
|
+
end
|
579
|
+
|
580
|
+
key = org.bouncycastle.crypto.util.PrivateKeyFactory::createKey(java.io.ByteArrayInputStream.new(pkcs8KeySpec.getEncoded))
|
581
|
+
keyType = KeyPair.key_type(key)
|
582
|
+
case keyType
|
583
|
+
when Pkernel::KeyPair::RSA_KEY_NAME
|
352
584
|
|
353
|
-
|
354
|
-
|
585
|
+
if prov.nil?
|
586
|
+
keyFact = Java::JavaSecurity::KeyFactory.getInstance("RSA")
|
587
|
+
else
|
588
|
+
keyFact = Java::JavaSecurity::KeyFactory.getInstance("RSA",prov)
|
589
|
+
end
|
590
|
+
#privKey = keyFact.generatePrivate(pkcs8KeySpec)
|
591
|
+
## here is how to convert into RSAPublicKey, become keypair!
|
592
|
+
#pubKeySpec = Java::JavaSecuritySpec::RSAPublicKeySpec.new(privKey.getModulus(),privKey.getPublicExponent())
|
593
|
+
#pubKey = keyFact.generatePublic(pubKeySpec)
|
594
|
+
|
595
|
+
#Java::JavaSecurity::KeyPair.new(pubKey,privKey)
|
596
|
+
|
597
|
+
when Pkernel::KeyPair::DSA_KEY_NAME
|
598
|
+
|
599
|
+
if prov.nil?
|
600
|
+
keyFact = Java::JavaSecurity::KeyFactory.getInstance("DSA")
|
601
|
+
else
|
602
|
+
keyFact = Java::JavaSecurity::KeyFactory.getInstance("DSA",prov)
|
603
|
+
end
|
604
|
+
|
605
|
+
when Pkernel::KeyPair::EC_KEY_NAME
|
606
|
+
|
607
|
+
if prov.nil?
|
608
|
+
keyFact = Java::JavaSecurity::KeyFactory.getInstance("EC")
|
609
|
+
else
|
610
|
+
keyFact = Java::JavaSecurity::KeyFactory.getInstance("EC",prov)
|
611
|
+
end
|
612
|
+
|
613
|
+
else
|
614
|
+
|
615
|
+
raise PkernelJce::Error, "Unknown key type #{keyType}"
|
616
|
+
|
355
617
|
end
|
618
|
+
|
619
|
+
privKey = keyFact.generatePrivate(pkcs8KeySpec)
|
620
|
+
## here is how to convert into RSAPublicKey, become keypair!
|
621
|
+
#pubKeySpec = Java::JavaSecuritySpec::RSAPublicKeySpec.new(privKey.getModulus(),privKey.getPublicExponent())
|
622
|
+
#pubKey = keyFact.generatePublic(pubKeySpec)
|
623
|
+
|
624
|
+
#pubKey = PkernelJce::KeyPair.public_key(privKey)
|
625
|
+
#Java::JavaSecurity::KeyPair.new(pubKey,privKey)
|
626
|
+
|
627
|
+
privKey
|
628
|
+
|
629
|
+
|
630
|
+
#if key.java_kind_of? org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters
|
631
|
+
# keyFact = Java::JavaSecurity::KeyFactory.getInstance("RSA")
|
632
|
+
# privKey = keyFact.generatePrivate(pkcs8KeySpec)
|
633
|
+
# # here is how to convert into RSAPublicKey, become keypair!
|
634
|
+
# pubKeySpec = Java::JavaSecuritySpec::RSAPublicKeySpec.new(privKey.getModulus(),privKey.getPublicExponent())
|
635
|
+
# pubKey = keyFact.generatePublic(pubKeySpec)
|
636
|
+
|
637
|
+
# Java::JavaSecurity::KeyPair.new(pubKey,privKey)
|
638
|
+
#else
|
639
|
+
# raise PkernelJce::Error, "Unsupported PKCS8 store of type #{key}"
|
640
|
+
#end
|
641
|
+
|
642
|
+
# BC API
|
643
|
+
#reader = org.bouncycastle.openssl.PEMParser.new(java.io.InputStreamReader.new(java.io.ByteArrayInputStream.new(baos.toByteArray)))
|
644
|
+
#obj = reader.readObject
|
645
|
+
##p obj.inspect
|
646
|
+
##p obj.methods.sort
|
647
|
+
##p obj.java_kind_of?(org.bouncycastle.openssl.PEMEncryptedKeyPair)
|
648
|
+
#if obj.is_a?(org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo)
|
649
|
+
# pass = opts[:password]
|
650
|
+
# if pass.nil?
|
651
|
+
# if block
|
652
|
+
# pass = block.call(:password)
|
653
|
+
# else
|
654
|
+
# raise PkernelJce::Error, "PEM key is encrypted. Please provide a password to load the key."
|
655
|
+
# end
|
656
|
+
# end
|
657
|
+
# decProv = org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder.new.setProvider(PkernelJce::Provider::DefProvider).build(pass.to_java.toCharArray)
|
658
|
+
# keyinfo = obj.decryptPrivateKeyInfo(decProv)
|
659
|
+
|
660
|
+
# converter = org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter.new
|
661
|
+
# converter.getPrivateKey(keyinfo)
|
662
|
+
#else
|
663
|
+
# keySpec = java.security.spec.PKCS8EncodedKeySpec.new(obj.getPrivateKeyInfo.encoded)
|
664
|
+
# # Now it's in a PKCS#8 PrivateKeyInfo structure. Read its Algorithm
|
665
|
+
# # OID and use that to construct a KeyFactory.
|
666
|
+
# bIn = org.bouncycastle.asn1.ASN1InputStream.new(java.io.ByteArrayInputStream.new(keySpec.getEncoded()));
|
667
|
+
# pki = org.bouncycastle.asn1.pkcs.PrivateKeyInfo.getInstance(bIn.readObject());
|
668
|
+
# algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId();
|
669
|
+
# java.security.KeyFactory.getInstance(algOid,prov).generatePrivate(keySpec);
|
670
|
+
#
|
671
|
+
# #privKey = java.security.KeyFactory.getInstance("RSA").generatePrivate(keySpec)
|
672
|
+
# #privKey
|
673
|
+
#end
|
356
674
|
|
357
675
|
end
|
358
676
|
# end load()
|