ccrypto-java 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.java-version +1 -1
- data/.release_history.yml +4 -0
- data/.ruby-version +1 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +68 -53
- data/Rakefile +2 -1
- data/bin/console +14 -0
- data/jars/bcjmail-jdk18on-172.jar +0 -0
- data/jars/bcmail-jdk18on-172.jar +0 -0
- data/jars/bcpg-jdk18on-172.1.jar +0 -0
- data/jars/bcpkix-jdk18on-172.jar +0 -0
- data/jars/bcprov-ext-jdk18on-172.jar +0 -0
- data/jars/bcprov-jdk18on-172.jar +0 -0
- data/jars/bctls-jdk18on-172.jar +0 -0
- data/jars/bcutil-jdk18on-172.jar +0 -0
- data/lib/ccrypto/java/bc_const_mapping.rb +42 -0
- data/lib/ccrypto/java/data_conversion.rb +23 -2
- data/lib/ccrypto/java/engines/argon2_engine.rb +95 -0
- data/lib/ccrypto/java/engines/asn1_engine.rb +2 -1
- data/lib/ccrypto/java/engines/bcrypt_engine.rb +56 -0
- data/lib/ccrypto/java/engines/cipher_engine.rb +462 -130
- data/lib/ccrypto/java/engines/compression_engine.rb +7 -28
- data/lib/ccrypto/java/engines/crystal_dilithium_engine.rb +226 -0
- data/lib/ccrypto/java/engines/crystal_kyber_engine.rb +260 -0
- data/lib/ccrypto/java/engines/decompression_engine.rb +5 -4
- data/lib/ccrypto/java/engines/digest_engine.rb +221 -139
- data/lib/ccrypto/java/engines/ecc_engine.rb +249 -96
- data/lib/ccrypto/java/engines/ed25519_engine.rb +211 -0
- data/lib/ccrypto/java/engines/hkdf_engine.rb +82 -23
- data/lib/ccrypto/java/engines/hmac_engine.rb +98 -23
- data/lib/ccrypto/java/engines/pbkdf2_engine.rb +82 -33
- data/lib/ccrypto/java/engines/pkcs7_engine.rb +44 -33
- data/lib/ccrypto/java/engines/rsa_engine.rb +85 -31
- data/lib/ccrypto/java/engines/scrypt_engine.rb +12 -3
- data/lib/ccrypto/java/engines/secret_key_engine.rb +77 -12
- data/lib/ccrypto/java/engines/secret_sharing_engine.rb +17 -2
- data/lib/ccrypto/java/engines/x25519_engine.rb +249 -0
- data/lib/ccrypto/java/engines/x509_csr_engine.rb +141 -0
- data/lib/ccrypto/java/engines/x509_engine.rb +365 -71
- data/lib/ccrypto/java/ext/secret_key.rb +37 -25
- data/lib/ccrypto/java/ext/x509_cert.rb +429 -5
- data/lib/ccrypto/java/ext/x509_csr.rb +151 -0
- data/lib/ccrypto/java/jce_provider.rb +0 -11
- data/lib/ccrypto/java/keystore/jce_keystore.rb +205 -0
- data/lib/ccrypto/java/keystore/jks_keystore.rb +52 -0
- data/lib/ccrypto/java/keystore/keystore.rb +97 -0
- data/lib/ccrypto/java/keystore/pem_keystore.rb +147 -0
- data/lib/ccrypto/java/keystore/pkcs12_keystore.rb +56 -0
- data/lib/ccrypto/java/utils/comparator.rb +25 -2
- data/lib/ccrypto/java/version.rb +1 -1
- data/lib/ccrypto/java.rb +46 -0
- data/lib/ccrypto/provider.rb +139 -3
- metadata +40 -24
- data/ccrypto-java.gemspec +0 -44
- 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/ccrypto/java/keybundle_store/pkcs12.rb +0 -125
@@ -0,0 +1,141 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Ccrypto
|
4
|
+
module Java
|
5
|
+
|
6
|
+
class X509CSREngine
|
7
|
+
include TR::CondUtils
|
8
|
+
include TeLogger::TeLogHelper
|
9
|
+
teLogger_tag :j_csr
|
10
|
+
|
11
|
+
def initialize(csrProf)
|
12
|
+
@csrProfile = csrProf
|
13
|
+
end
|
14
|
+
|
15
|
+
def generate(privKey, &block)
|
16
|
+
|
17
|
+
cp = @csrProfile
|
18
|
+
|
19
|
+
subject = to_cert_subject(cp)
|
20
|
+
|
21
|
+
signHash = cp.hashAlgo
|
22
|
+
raise X509CSREngineException, "Certificate hash algorithm '#{signHash}' is not supported" if not DigestEngine.is_digest_supported?(signHash)
|
23
|
+
|
24
|
+
provider = block.call(:jce_provider) if block
|
25
|
+
|
26
|
+
if provider.nil?
|
27
|
+
teLogger.debug "Adding default provider"
|
28
|
+
prov = Ccrypto::Java::JCEProvider::DEFProv
|
29
|
+
else
|
30
|
+
teLogger.debug "Adding provider #{provider.name}"
|
31
|
+
prov = Ccrypto::Java::JCEProvider.add_provider(provider)
|
32
|
+
end
|
33
|
+
|
34
|
+
foundDigest = DigestEngine.find_digest_config(signHash)
|
35
|
+
if foundDigest.length == 1
|
36
|
+
selDigest = foundDigest.first
|
37
|
+
else
|
38
|
+
## prompt user for digest
|
39
|
+
if block
|
40
|
+
selDigest = block.call(:multiple_digest_algo_found, foundDigest)
|
41
|
+
else
|
42
|
+
raise X509EngineException, "Multiple digest algo found but not given a block. Not able to proceed."
|
43
|
+
end
|
44
|
+
end
|
45
|
+
signHashVal = selDigest.provider_config[:algo_name].gsub("-","")
|
46
|
+
|
47
|
+
|
48
|
+
#signHashVal = DigestEngine.find_digest_config(signHash).provider_config[:algo_name]
|
49
|
+
#signHashVal.gsub!("-","")
|
50
|
+
|
51
|
+
signAlgo = nil
|
52
|
+
gKey = privKey
|
53
|
+
loop do
|
54
|
+
case gKey
|
55
|
+
when org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey
|
56
|
+
signAlgo = "#{signHashVal}WithECDSA"
|
57
|
+
break
|
58
|
+
when java.security.interfaces.RSAPrivateKey , org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPrivateCrtKey
|
59
|
+
signAlgo = "#{signHashVal}WithRSA"
|
60
|
+
break
|
61
|
+
when Ccrypto::PrivateKey
|
62
|
+
teLogger.debug "Found Ccrypto::Private key #{gKey}."
|
63
|
+
gKey = gKey.native_privKey
|
64
|
+
else
|
65
|
+
raise X509CSREngineException, "Unsupported signing key type '#{gKey}'"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
p10Builder = org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder.new(subject, cp.public_key)
|
70
|
+
|
71
|
+
ext = []
|
72
|
+
cp.email.each do |e|
|
73
|
+
ext << org.bouncycastle.asn1.x509.GeneralName.new(org.bouncycastle.asn1.x509.GeneralName.rfc822Name,e)
|
74
|
+
end
|
75
|
+
|
76
|
+
cp.dns_name.each do |dn|
|
77
|
+
ext << org.bouncycastle.asn1.x509.GeneralName.new(org.bouncycastle.asn1.x509.GeneralName.dNSName,dn)
|
78
|
+
end
|
79
|
+
|
80
|
+
cp.ip_addr.each do |ip|
|
81
|
+
ext << org.bouncycastle.asn1.x509.GeneralName.new(org.bouncycastle.asn1.x509.GeneralName.iPAddress,ip)
|
82
|
+
end
|
83
|
+
|
84
|
+
cp.uri.each do |u|
|
85
|
+
ext << org.bouncycastle.asn1.x509.GeneralName.new(org.bouncycastle.asn1.x509.GeneralName.uniformResourceIdentifier,u)
|
86
|
+
end
|
87
|
+
|
88
|
+
#cp.custom_extension.each do |k,v|
|
89
|
+
# val = v[:value]
|
90
|
+
# val = "" if is_empty?(val)
|
91
|
+
# ev = org.bouncycastle.asn1.x509.Extension.new(org.bouncycastle.asn1.DERObjectIdentifier.new(k), v[:critical], org.bouncycastle.asn1.DEROctetString.new(val.to_java.getBytes))
|
92
|
+
# ext << org.bouncycastle.asn1.x509.GeneralName.new(org.bouncycastle.asn1.x509.GeneralName.otherName,ev)
|
93
|
+
#end
|
94
|
+
|
95
|
+
gn = org.bouncycastle.asn1.x509.GeneralNames.new(ext.to_java(org.bouncycastle.asn1.x509.GeneralName))
|
96
|
+
eg = org.bouncycastle.asn1.x509.ExtensionsGenerator.new
|
97
|
+
eg.addExtension(org.bouncycastle.asn1.x509.Extension.subjectAlternativeName, false, gn)
|
98
|
+
|
99
|
+
cp.custom_extension.each do |k,v|
|
100
|
+
val = v[:value]
|
101
|
+
val = "" if is_empty?(val)
|
102
|
+
ev = org.bouncycastle.asn1.x509.Extension.new(org.bouncycastle.asn1.ASN1ObjectIdentifier.new(k), v[:critical], org.bouncycastle.asn1.DEROctetString.new(val.to_java.getBytes))
|
103
|
+
eg.addExtension(ev)
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
p10Builder.addAttribute(org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, eg.generate)
|
108
|
+
|
109
|
+
sign = org.bouncycastle.operator.jcajce.JcaContentSignerBuilder.new(signAlgo).setProvider(prov).build(gKey)
|
110
|
+
csr = p10Builder.build(sign)
|
111
|
+
|
112
|
+
Ccrypto::X509CSR.new(csr)
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
private
|
118
|
+
def to_cert_subject(cp)
|
119
|
+
|
120
|
+
builder = org.bouncycastle.asn1.x500.X500NameBuilder.new
|
121
|
+
builder.addRDN(org.bouncycastle.asn1.x500.style::BCStyle::CN, cp.owner_name)
|
122
|
+
|
123
|
+
builder.addRDN(org.bouncycastle.asn1.x500.style::BCStyle::O, cp.org) if not_empty?(cp.org)
|
124
|
+
|
125
|
+
cp.org_unit.each do |ou|
|
126
|
+
builder.addRDN(org.bouncycastle.asn1.x500.style::BCStyle::OU, ou)
|
127
|
+
end
|
128
|
+
|
129
|
+
e = cp.email.first
|
130
|
+
if not_empty?(e)
|
131
|
+
builder.addRDN(org.bouncycastle.asn1.x500.style::BCStyle::EmailAddress, e)
|
132
|
+
end
|
133
|
+
|
134
|
+
builder.build
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
@@ -1,35 +1,54 @@
|
|
1
1
|
|
2
|
+
require_relative '../bc_const_mapping'
|
3
|
+
|
2
4
|
module Ccrypto
|
3
5
|
module Java
|
4
6
|
|
5
7
|
class X509Engine
|
6
8
|
include TR::CondUtils
|
7
9
|
|
8
|
-
|
10
|
+
def self.cert_to_bin(cert)
|
11
|
+
cert.encoded
|
12
|
+
end
|
9
13
|
|
10
|
-
|
14
|
+
def self.bin_to_cert(bin)
|
15
|
+
cf = java.security.cert.CertificateFactory.getInstance("X509",JCEProvider::DEFProv)
|
16
|
+
cf.generateCertificate(bin)
|
17
|
+
end
|
11
18
|
|
12
19
|
def initialize(certProf)
|
13
20
|
@certProfile = certProf
|
14
21
|
end
|
15
22
|
|
16
23
|
def generate(issuerKey, &block)
|
24
|
+
if @certProfile.csr.nil?
|
25
|
+
generate_from_cert_profile(@certProfile, issuerKey, &block)
|
26
|
+
else
|
27
|
+
generate_from_csr(@certProfile, issuerKey, &block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def generate_from_csr(cp, issuerKey, &block)
|
32
|
+
|
33
|
+
csrObj = Ccrypto::X509CSR.new(cp.csr)
|
34
|
+
csrCp = csrObj.csr_info
|
17
35
|
|
18
|
-
cp = @certProfile
|
19
36
|
|
20
37
|
raise X509EngineException, "Issuer key must be given" if issuerKey.nil?
|
21
38
|
raise X509EngineException, "Issuer key must be a private key. Given #{issuerKey}" if not issuerKey.is_a?(Ccrypto::PrivateKey)
|
22
39
|
|
23
40
|
prov = Ccrypto::Java::JCEProvider::DEFProv
|
41
|
+
signHash = cp.hashAlgo
|
24
42
|
signSpec = nil
|
25
43
|
if block
|
26
44
|
uprov = block.call(:jce_provider_name)
|
27
45
|
prov if not_empty?(uprov)
|
28
46
|
signSpec = block.call(:sign_spec)
|
29
|
-
signHash = block.call(:sign_hash)
|
47
|
+
signHash = block.call(:sign_hash) if is_empty?(signHash)
|
30
48
|
end
|
31
49
|
|
32
50
|
signHash = :sha256 if is_empty?(signHash)
|
51
|
+
raise X509EngineException, "Given digest algo '#{signHash}' is not suported" if not DigestEngine.is_digest_supported?(signHash)
|
33
52
|
|
34
53
|
validFrom = cp.not_before
|
35
54
|
validTo = cp.not_after
|
@@ -42,16 +61,260 @@ module Ccrypto
|
|
42
61
|
serial = java.math.BigInteger.new(cp.serial, 16)
|
43
62
|
end
|
44
63
|
|
64
|
+
iss = cp.issuer_cert
|
65
|
+
if not_empty?(iss)
|
66
|
+
raise X509EngineException, "Issuer certificate must be Ccrypto::X509Cert object (#{iss.class})" if not iss.is_a?(Ccrypto::X509Cert)
|
67
|
+
|
68
|
+
certGen = org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder.new(Ccrypto::X509Cert.to_java_cert(iss), serial, validFrom, validTo, to_cert_subject(csrCp), csrCp.public_key)
|
69
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo.getInstance(iss.getPublicKey.encoded)))
|
70
|
+
|
71
|
+
else
|
72
|
+
|
73
|
+
name = to_cert_subject(csrCp)
|
74
|
+
certGen = org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder.new(name, serial, validFrom, validTo, name, csrCp.public_key.native_pubKey)
|
75
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo.getInstance(csrCp.public_key.to_bin)))
|
76
|
+
end
|
77
|
+
|
78
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::basicConstraints, true, org.bouncycastle.asn1.x509.BasicConstraints.new(true)) if cp.gen_issuer_cert?
|
79
|
+
|
80
|
+
#certGen.addExtension(org.bouncycastle.asn1.x509.Extension::keyUsage, false, org.bouncycastle.asn1.x509.KeyUsage.new(to_keyusage))
|
81
|
+
#criticalKu = 0
|
82
|
+
#nonCriticalKu = 0
|
83
|
+
kuv = 0
|
84
|
+
criticalKu = false
|
85
|
+
cp.key_usage.selected.each do |ku, critical|
|
86
|
+
kur = BCConstMapping::KeyUsageMapping[ku]
|
87
|
+
#case ku
|
88
|
+
#when :digitalSignature
|
89
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::digitalSignature
|
90
|
+
#when :nonRepudiation
|
91
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::nonRepudiation
|
92
|
+
#when :keyEncipherment
|
93
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::keyEncipherment
|
94
|
+
#when :dataEncipherment
|
95
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::dataEncipherment
|
96
|
+
#when :keyAgreement
|
97
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::keyAgreement
|
98
|
+
#when :keyCertSign
|
99
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::keyCertSign
|
100
|
+
#when :crlSign
|
101
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::cRLSign
|
102
|
+
#when :encipherOnly
|
103
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::encipherOnly
|
104
|
+
#when :decipherOnly
|
105
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::decipherOnly
|
106
|
+
#end
|
107
|
+
|
108
|
+
criticalKu = critical if critical
|
109
|
+
|
110
|
+
kuv |= kur
|
111
|
+
|
112
|
+
#if critical
|
113
|
+
# criticalKu |= kur
|
114
|
+
#else
|
115
|
+
# nonCriticalKu |= kur
|
116
|
+
#end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::keyUsage, criticalKu, org.bouncycastle.asn1.x509.KeyUsage.new(kuv))
|
121
|
+
#certGen.addExtension(org.bouncycastle.asn1.x509.Extension::keyUsage, true, org.bouncycastle.asn1.x509.KeyUsage.new(criticalKu)) if criticalKu != 0
|
122
|
+
#certGen.addExtension(org.bouncycastle.asn1.x509.Extension::keyUsage, false, org.bouncycastle.asn1.x509.KeyUsage.new(nonCriticalKu)) if nonCriticalKu != 0
|
123
|
+
|
124
|
+
ekuCritical = false
|
125
|
+
eku = java.util.Vector.new
|
126
|
+
#ekuCritical = java.util.Vector.new
|
127
|
+
#ekuNonCritical = java.util.Vector.new
|
128
|
+
cp.ext_key_usage.selected.each do |ku,critical|
|
129
|
+
kur = BCConstMapping::ExtKeyUsageMapping[ku]
|
130
|
+
#case ku
|
131
|
+
#when :allPurpose
|
132
|
+
# kur = org.bouncycastle.asn1.x509.KeyPurposeId::anyExtendedKeyUsage
|
133
|
+
#when :serverAuth
|
134
|
+
# kur = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_serverAuth
|
135
|
+
#when :clientAuth
|
136
|
+
# kur = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_clientAuth
|
137
|
+
#when :codeSigning
|
138
|
+
# kur = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_codeSigning
|
139
|
+
#when :emailProtection
|
140
|
+
# kur = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_emailProtection
|
141
|
+
#when :timeStamping
|
142
|
+
# kur = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_timeStamping
|
143
|
+
#when :ocspSigning
|
144
|
+
# kur = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_OCSPSigning
|
145
|
+
#end
|
146
|
+
|
147
|
+
ekuCritical = critical if critical
|
148
|
+
eku.add_element(kur)
|
149
|
+
#if critical
|
150
|
+
# ekuCritical.add_element(kur)
|
151
|
+
#else
|
152
|
+
# ekuNonCritical.add_element(kur)
|
153
|
+
#end
|
154
|
+
end
|
155
|
+
|
156
|
+
#extKeyUsage = java.util.Vector.new
|
157
|
+
cp.domain_key_usage.each do |dku, critical|
|
158
|
+
#kur = org.bouncycastle.asn1.DERObjectIdentifier.new(dku)
|
159
|
+
kur = org.bouncycastle.asn1.ASN1ObjectIdentifier.new(dku)
|
160
|
+
|
161
|
+
ekuCritical = critical if critical
|
162
|
+
eku.add_element(kur)
|
163
|
+
#if critical
|
164
|
+
# ekuCritical.add_element(kur)
|
165
|
+
#else
|
166
|
+
# ekuNonCritical.add_element(kur)
|
167
|
+
#end
|
168
|
+
end
|
169
|
+
|
170
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::extendedKeyUsage, ekuCritical, org.bouncycastle.asn1.x509.ExtendedKeyUsage.new(eku)) if not_empty?(eku)
|
171
|
+
#certGen.addExtension(org.bouncycastle.asn1.x509.Extension::extendedKeyUsage, true, org.bouncycastle.asn1.x509.ExtendedKeyUsage.new(ekuCritical)) if not_empty?(ekuCritical)
|
172
|
+
#certGen.addExtension(org.bouncycastle.asn1.x509.Extension::extendedKeyUsage, false, org.bouncycastle.asn1.x509.ExtendedKeyUsage.new(ekuNonCritical)) if not_empty?(ekuNonCritical)
|
173
|
+
#certGen.addExtension(org.bouncycastle.asn1.x509.Extension::extendedKeyUsage, false, org.bouncycastle.asn1.x509.ExtendedKeyUsage.new(extKeyUsage)) if not extKeyUsage.is_empty?
|
174
|
+
|
175
|
+
altName = []
|
176
|
+
csrCp.email.uniq.each do |e|
|
177
|
+
altName << org.bouncycastle.asn1.x509.GeneralName.new(org.bouncycastle.asn1.x509.GeneralName::rfc822Name,e)
|
178
|
+
end
|
179
|
+
|
180
|
+
csrCp.dns_name.uniq.each do |d|
|
181
|
+
altName << org.bouncycastle.asn1.x509.GeneralName.new(org.bouncycastle.asn1.x509.GeneralName::dNSName,d)
|
182
|
+
end
|
183
|
+
|
184
|
+
csrCp.ip_addr.uniq.each do |d|
|
185
|
+
altName << org.bouncycastle.asn1.x509.GeneralName.new(org.bouncycastle.asn1.x509.GeneralName::iPAddress,d)
|
186
|
+
end
|
187
|
+
|
188
|
+
csrCp.uri.uniq.each do |u|
|
189
|
+
altName << org.bouncycastle.asn1.x509.GeneralName.new(org.bouncycastle.asn1.x509.GeneralName::uniformResourceIdentifier,u)
|
190
|
+
end
|
191
|
+
|
192
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::subjectAlternativeName, false, org.bouncycastle.asn1.x509.GeneralNames.new(altName.to_java(org.bouncycastle.asn1.x509.GeneralName)) )
|
193
|
+
|
194
|
+
csrCp.custom_extension.each do |k, v|
|
195
|
+
val = v[:value]
|
196
|
+
val = "" if is_empty?(val)
|
197
|
+
#ev = org.bouncycastle.asn1.x509.Extension.new(org.bouncycastle.asn1.DERObjectIdentifier.new(k), v[:critical], org.bouncycastle.asn1.DEROctetString.new(val.to_java.getBytes))
|
198
|
+
ev = org.bouncycastle.asn1.x509.Extension.new(org.bouncycastle.asn1.ASN1ObjectIdentifier.new(k), v[:critical], org.bouncycastle.asn1.DEROctetString.new(val.to_java.getBytes))
|
199
|
+
certGen.addExtension(ev)
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
if not_empty?(cp.crl_dist_point)
|
204
|
+
crls = []
|
205
|
+
cp.crl_dist_point.each do |c|
|
206
|
+
crls << org.bouncycastle.asn1.x509.GeneralName.new(org.bouncycastle.asn1.x509.GeneralName::uniformResourceIdentifier, org.bouncycastle.asn1.DERIA5String.new(c))
|
207
|
+
end
|
208
|
+
gns = org.bouncycastle.asn1.x509.GeneralNames.new(crls.to_java(org.bouncycastle.asn1.x509.GeneralName))
|
209
|
+
dpn = org.bouncycastle.asn1.x509.DistributionPointName.new(gns)
|
210
|
+
dp = org.bouncycastle.asn1.x509.DistributionPoint.new(dpn,nil,nil)
|
211
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.X509Extensions::CRLDistributionPoints,false,org.bouncycastle.asn1.DERSequence.new(dp))
|
212
|
+
end
|
213
|
+
|
214
|
+
aia = []
|
215
|
+
cp.ocsp_url.each do |o|
|
216
|
+
ov = org.bouncycastle.asn1.x509.GeneralName.new(org.bouncycastle.asn1.x509.GeneralName::uniformResourceIdentifier, org.bouncycastle.asn1.DERIA5String.new(o))
|
217
|
+
aia << org.bouncycastle.asn1.x509.AccessDescription.new(org.bouncycastle.asn1.x509.AccessDescription.id_ad_ocsp, ov)
|
218
|
+
end
|
219
|
+
|
220
|
+
cp.issuer_url.each do |i|
|
221
|
+
iv = org.bouncycastle.asn1.x509.GeneralName.new(org.bouncycastle.asn1.x509.GeneralName::uniformResourceIdentifier, org.bouncycastle.asn1.DERIA5String.new(i))
|
222
|
+
aia << org.bouncycastle.asn1.x509.AccessDescription.new(org.bouncycastle.asn1.x509.AccessDescription.id_ad_caIssuers, iv)
|
223
|
+
end
|
224
|
+
|
225
|
+
if not_empty?(aia)
|
226
|
+
authorityInformationAccess = org.bouncycastle.asn1.x509.AuthorityInformationAccess.new(aia.to_java(org.bouncycastle.asn1.x509.AccessDescription))
|
227
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.X509Extensions::AuthorityInfoAccess, false, authorityInformationAccess)
|
228
|
+
end
|
229
|
+
|
230
|
+
|
231
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo.getInstance(csrCp.public_key.to_bin)))
|
232
|
+
|
233
|
+
signAlgo = nil
|
234
|
+
# alreacy check if digest algo exist or not at the entry of the method
|
235
|
+
foundDigest = DigestEngine.find_digest_config(signHash)
|
236
|
+
if foundDigest.length == 1
|
237
|
+
selDigest = foundDigest.first
|
238
|
+
else
|
239
|
+
## prompt user for digest
|
240
|
+
if block
|
241
|
+
selDigest = block.call(:multiple_digest_algo_found, foundDigest)
|
242
|
+
else
|
243
|
+
raise X509EngineException, "Multiple digest algo configuration found based on given value '#{signHash}' but not given a block. Not able to proceed."
|
244
|
+
end
|
245
|
+
end
|
246
|
+
signHashVal = selDigest.provider_config[:algo_name].gsub("-","")
|
247
|
+
|
248
|
+
gKey = issuerKey
|
249
|
+
loop do
|
250
|
+
case gKey
|
251
|
+
when org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey
|
252
|
+
signAlgo = "#{signHashVal}WithECDSA"
|
253
|
+
break
|
254
|
+
when java.security.interfaces.RSAPrivateKey , org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPrivateCrtKey
|
255
|
+
signAlgo = "#{signHashVal}WithRSA"
|
256
|
+
break
|
257
|
+
when Ccrypto::PrivateKey
|
258
|
+
logger.debug "Found Ccrypto::Private key #{gKey}."
|
259
|
+
gKey = gKey.native_privKey
|
260
|
+
else
|
261
|
+
raise X509EngineException, "Unsupported issuer key type '#{gKey}'"
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
#signAlgo = "SHA256WithECDSA"
|
266
|
+
#signer = org.bouncycastle.operator.jcajce.JcaContentSignerBuilder.new(signAlgo).setProvider(prov).build(issuerKey.private_key)
|
267
|
+
signer = org.bouncycastle.operator.jcajce.JcaContentSignerBuilder.new(signAlgo).setProvider(prov).build(gKey)
|
268
|
+
|
269
|
+
cert = org.bouncycastle.cert.jcajce.JcaX509CertificateConverter.new().setProvider(prov).getCertificate(certGen.build(signer))
|
270
|
+
cert
|
271
|
+
|
272
|
+
Ccrypto::X509Cert.new(cert)
|
273
|
+
|
274
|
+
end
|
275
|
+
|
276
|
+
|
277
|
+
def generate_from_cert_profile(cp, issuerKey, &block)
|
278
|
+
|
279
|
+
raise X509EngineException, "Issuer key must be given" if issuerKey.nil?
|
280
|
+
raise X509EngineException, "Issuer key must be a private key. Given #{issuerKey}" if not issuerKey.is_a?(Ccrypto::PrivateKey)
|
281
|
+
|
282
|
+
prov = Ccrypto::Java::JCEProvider::DEFProv
|
283
|
+
signHash = cp.hashAlgo
|
284
|
+
signSpec = nil
|
285
|
+
if block
|
286
|
+
uprov = block.call(:jce_provider_name)
|
287
|
+
prov if not_empty?(uprov)
|
288
|
+
signSpec = block.call(:sign_spec)
|
289
|
+
signHash = block.call(:sign_hash) if is_empty?(signHash)
|
290
|
+
end
|
291
|
+
|
292
|
+
signHash = :sha256 if is_empty?(signHash)
|
293
|
+
raise X509EngineException, "Given digest algo '#{signHash}' is not suported" if not DigestEngine.is_digest_supported?(signHash)
|
294
|
+
|
295
|
+
validFrom = cp.not_before
|
296
|
+
validTo = cp.not_after
|
297
|
+
|
298
|
+
extUtils = org.bouncycastle.cert.bc.BcX509ExtensionUtils.new
|
299
|
+
|
300
|
+
if is_empty?(cp.serial)
|
301
|
+
serial = SecureRandom.hex(16)
|
302
|
+
elsif cp.serial.is_a?(java.math.BigInteger)
|
303
|
+
serial = cp.serial
|
304
|
+
else
|
305
|
+
serial = java.math.BigInteger.new(cp.serial, 16)
|
306
|
+
end
|
307
|
+
|
45
308
|
iss = cp.issuer_cert
|
46
309
|
if not_empty?(iss)
|
47
310
|
raise X509EngineException, "Issuer certificate must be Ccrypto::X509Cert object (#{iss.class})" if not iss.is_a?(Ccrypto::X509Cert) #iss.is_a?(java.security.cert.Certificate)
|
48
311
|
|
49
|
-
certGen = org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder.new(Ccrypto::X509Cert.to_java_cert(iss), serial, validFrom, validTo, to_cert_subject, cp.public_key)
|
312
|
+
certGen = org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder.new(Ccrypto::X509Cert.to_java_cert(iss), serial, validFrom, validTo, to_cert_subject(cp), cp.public_key)
|
50
313
|
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo.getInstance(iss.getPublicKey.encoded)))
|
51
314
|
|
52
315
|
else
|
53
316
|
|
54
|
-
name = to_cert_subject
|
317
|
+
name = to_cert_subject(cp)
|
55
318
|
certGen = org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder.new(name, serial, validFrom, validTo, name, cp.public_key.native_pubKey)
|
56
319
|
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo.getInstance(cp.public_key.to_bin)))
|
57
320
|
end
|
@@ -64,26 +327,27 @@ module Ccrypto
|
|
64
327
|
kuv = 0
|
65
328
|
criticalKu = false
|
66
329
|
cp.key_usage.selected.each do |ku, critical|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
330
|
+
kur = BCConstMapping::KeyUsageMapping[ku]
|
331
|
+
#case ku
|
332
|
+
#when :digitalSignature
|
333
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::digitalSignature
|
334
|
+
#when :nonRepudiation
|
335
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::nonRepudiation
|
336
|
+
#when :keyEncipherment
|
337
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::keyEncipherment
|
338
|
+
#when :dataEncipherment
|
339
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::dataEncipherment
|
340
|
+
#when :keyAgreement
|
341
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::keyAgreement
|
342
|
+
#when :keyCertSign
|
343
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::keyCertSign
|
344
|
+
#when :crlSign
|
345
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::cRLSign
|
346
|
+
#when :encipherOnly
|
347
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::encipherOnly
|
348
|
+
#when :decipherOnly
|
349
|
+
# kur = org.bouncycastle.asn1.x509::KeyUsage::decipherOnly
|
350
|
+
#end
|
87
351
|
|
88
352
|
criticalKu = critical if critical
|
89
353
|
|
@@ -106,22 +370,23 @@ module Ccrypto
|
|
106
370
|
#ekuCritical = java.util.Vector.new
|
107
371
|
#ekuNonCritical = java.util.Vector.new
|
108
372
|
cp.ext_key_usage.selected.each do |ku,critical|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
373
|
+
kur = BCConstMapping::ExtKeyUsageMapping[ku]
|
374
|
+
#case ku
|
375
|
+
#when :allPurpose
|
376
|
+
# kur = org.bouncycastle.asn1.x509.KeyPurposeId::anyExtendedKeyUsage
|
377
|
+
#when :serverAuth
|
378
|
+
# kur = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_serverAuth
|
379
|
+
#when :clientAuth
|
380
|
+
# kur = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_clientAuth
|
381
|
+
#when :codeSigning
|
382
|
+
# kur = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_codeSigning
|
383
|
+
#when :emailProtection
|
384
|
+
# kur = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_emailProtection
|
385
|
+
#when :timeStamping
|
386
|
+
# kur = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_timeStamping
|
387
|
+
#when :ocspSigning
|
388
|
+
# kur = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_OCSPSigning
|
389
|
+
#end
|
125
390
|
|
126
391
|
ekuCritical = critical if critical
|
127
392
|
eku.add_element(kur)
|
@@ -134,7 +399,8 @@ module Ccrypto
|
|
134
399
|
|
135
400
|
#extKeyUsage = java.util.Vector.new
|
136
401
|
cp.domain_key_usage.each do |dku, critical|
|
137
|
-
kur = org.bouncycastle.asn1.DERObjectIdentifier.new(dku)
|
402
|
+
#kur = org.bouncycastle.asn1.DERObjectIdentifier.new(dku)
|
403
|
+
kur = org.bouncycastle.asn1.ASN1ObjectIdentifier.new(dku)
|
138
404
|
|
139
405
|
ekuCritical = critical if critical
|
140
406
|
eku.add_element(kur)
|
@@ -169,6 +435,14 @@ module Ccrypto
|
|
169
435
|
|
170
436
|
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::subjectAlternativeName, false, org.bouncycastle.asn1.x509.GeneralNames.new(altName.to_java(org.bouncycastle.asn1.x509.GeneralName)) )
|
171
437
|
|
438
|
+
cp.custom_extension.each do |k, v|
|
439
|
+
val = v[:value]
|
440
|
+
val = "" if is_empty?(val)
|
441
|
+
#ev = org.bouncycastle.asn1.x509.Extension.new(org.bouncycastle.asn1.DERObjectIdentifier.new(k), v[:critical], org.bouncycastle.asn1.DEROctetString.new(val.to_java.getBytes))
|
442
|
+
ev = org.bouncycastle.asn1.x509.Extension.new(org.bouncycastle.asn1.ASN1ObjectIdentifier.new(k), v[:critical], org.bouncycastle.asn1.DEROctetString.new(val.to_java.getBytes))
|
443
|
+
certGen.addExtension(ev)
|
444
|
+
end
|
445
|
+
|
172
446
|
if not_empty?(cp.crl_dist_point)
|
173
447
|
crls = []
|
174
448
|
cp.crl_dist_point.each do |c|
|
@@ -200,24 +474,39 @@ module Ccrypto
|
|
200
474
|
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo.getInstance(cp.public_key.to_bin)))
|
201
475
|
|
202
476
|
signAlgo = nil
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
signAlgo = "#{signHash.to_s.upcase}WithECDSA"
|
209
|
-
break
|
210
|
-
when java.security.interfaces.RSAPrivateKey , org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPrivateCrtKey
|
211
|
-
signAlgo = "#{signHash.to_s.upcase}WithRSA"
|
212
|
-
break
|
213
|
-
when Ccrypto::PrivateKey
|
214
|
-
teLogger.debug "Found Ccrypto::Private key #{gKey}."
|
215
|
-
gKey = gKey.native_privKey
|
216
|
-
else
|
217
|
-
raise X509EngineException, "Unsupported issuer key type '#{gKey}'"
|
218
|
-
end
|
219
|
-
end
|
477
|
+
|
478
|
+
# alreacy check if digest algo exist or not at the entry of the method
|
479
|
+
foundDigest = DigestEngine.find_digest_config(signHash)
|
480
|
+
if foundDigest.length == 1
|
481
|
+
selDigest = foundDigest.first
|
220
482
|
else
|
483
|
+
p foundDigest
|
484
|
+
## prompt user for digest
|
485
|
+
if block
|
486
|
+
selDigest = block.call(:multiple_digest_algo_found, foundDigest)
|
487
|
+
else
|
488
|
+
raise X509EngineException, "Multiple digest algo found but not given a block. Not able to proceed."
|
489
|
+
end
|
490
|
+
end
|
491
|
+
signHashVal = selDigest.provider_config[:algo_name].gsub("-","")
|
492
|
+
|
493
|
+
#signHashVal = DigestEngine.find_digest_config(signHash).provider_config[:algo_name].gsub("-","")
|
494
|
+
|
495
|
+
gKey = issuerKey
|
496
|
+
loop do
|
497
|
+
case gKey
|
498
|
+
when org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey
|
499
|
+
signAlgo = "#{signHashVal}WithECDSA"
|
500
|
+
break
|
501
|
+
when java.security.interfaces.RSAPrivateKey , org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPrivateCrtKey
|
502
|
+
signAlgo = "#{signHashVal}WithRSA"
|
503
|
+
break
|
504
|
+
when Ccrypto::PrivateKey
|
505
|
+
logger.debug "Found Ccrypto::Private key #{gKey}."
|
506
|
+
gKey = gKey.native_privKey
|
507
|
+
else
|
508
|
+
raise X509EngineException, "Unsupported issuer key type '#{gKey}'"
|
509
|
+
end
|
221
510
|
end
|
222
511
|
|
223
512
|
#signAlgo = "SHA256WithECDSA"
|
@@ -231,23 +520,21 @@ module Ccrypto
|
|
231
520
|
|
232
521
|
end
|
233
522
|
|
234
|
-
def to_cert_subject
|
523
|
+
def to_cert_subject(cp)
|
235
524
|
|
236
525
|
builder = org.bouncycastle.asn1.x500.X500NameBuilder.new
|
237
|
-
builder.addRDN(org.bouncycastle.asn1.x500.style::BCStyle::CN,
|
526
|
+
builder.addRDN(org.bouncycastle.asn1.x500.style::BCStyle::CN, cp.owner_name)
|
238
527
|
|
239
|
-
builder.addRDN(org.bouncycastle.asn1.x500.style::BCStyle::O,
|
528
|
+
builder.addRDN(org.bouncycastle.asn1.x500.style::BCStyle::O, cp.org) if not_empty?(cp.org)
|
240
529
|
|
241
|
-
|
242
|
-
builder.addRDN(org.bouncycastle.asn1.x500.style::BCStyle::OU, ou)
|
530
|
+
cp.org_unit.each do |ou|
|
531
|
+
builder.addRDN(org.bouncycastle.asn1.x500.style::BCStyle::OU, ou) if not_empty?(ou)
|
243
532
|
end
|
244
533
|
|
245
|
-
#
|
246
|
-
|
247
|
-
e
|
248
|
-
|
249
|
-
builder.addRDN(org.bouncycastle.asn1.x500.style::BCStyle::EmailAddress, e)
|
250
|
-
end
|
534
|
+
#e = cp.email.first
|
535
|
+
#if not_empty?(e)
|
536
|
+
# builder.addRDN(org.bouncycastle.asn1.x500.style::BCStyle::EmailAddress, e)
|
537
|
+
#end
|
251
538
|
|
252
539
|
builder.build
|
253
540
|
|
@@ -305,6 +592,13 @@ module Ccrypto
|
|
305
592
|
kur
|
306
593
|
end
|
307
594
|
|
595
|
+
def self.logger(&block)
|
596
|
+
Ccrypto::Java.logger(:x509_eng, &block)
|
597
|
+
end
|
598
|
+
def logger(&block)
|
599
|
+
self.class.logger(&block)
|
600
|
+
end
|
601
|
+
|
308
602
|
end
|
309
603
|
|
310
604
|
end
|