pkernel_jce 0.3 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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()
|