lib/ccrypto/java/engines/digest_engine.rb in ccrypto-java-0.1.0 vs lib/ccrypto/java/engines/digest_engine.rb in ccrypto-java-0.2.0

- old
+ new

@@ -5,203 +5,285 @@ module Java class DigestEngine include TR::CondUtils include DataConversion - include TeLogger::TeLogHelper + class SupportedDigestEngine + include InMemoryRecord - teLogger_tag :j_digest + def initialize + define_search_key(:algo, :outBitLength, :outByteLength) + end + end - Potential = [ + def self.supported + if @supported.nil? + if ENV[Java::ENV_PROBE_DIGEST_KEY] == "true" + @supported = SupportedDigestEngine.new + else + @supported = SupportedDigestEngine.load_from_storage("supported_digest") + end - Ccrypto::SHA1.provider_info("SHA-1"), - Ccrypto::SHA224.provider_info("SHA-224"), - Ccrypto::SHA256.provider_info("SHA-256"), - Ccrypto::SHA384.provider_info("SHA-384"), - Ccrypto::SHA512.provider_info("SHA-512"), - Ccrypto::SHA512_224.provider_info("SHA-512/224"), - Ccrypto::SHA512_256.provider_info("SHA-512/256"), + if @supported.empty? + @supported = SupportedDigestEngine.new + probe = java.security.Security.getAlgorithms("MessageDigest").to_a.delete_if { |e| e.include?(".") } - Ccrypto::SHA3_224.provider_info("SHA3-224"), - Ccrypto::SHA3_256.provider_info("SHA3-256"), - Ccrypto::SHA3_384.provider_info("SHA3-384"), - Ccrypto::SHA3_512.provider_info("SHA3-512"), + logger = Ccrypto::Java.logger(:digest_eng) - Ccrypto::BLAKE2b160.provider_info("BLAKE2B-160"), - Ccrypto::BLAKE2b256.provider_info("BLAKE2B-256"), - Ccrypto::BLAKE2b384.provider_info("BLAKE2B-384"), - Ccrypto::BLAKE2b512.provider_info("BLAKE2B-512"), + blacklistedDigest = ["MD2","MD4","MD5"] + probe.sort.each do |found| + next if blacklistedDigest.include?(found) + logger.debug "Found digest algo : #{found}" + begin + md = java.security.MessageDigest.getInstance(found, JCEProvider::BCProv) + case found + when "HARAKA-256" + conf = { provider_config: { algo_name: found, jceProvider: JCEProvider::BCProv.name }, fixed_input_len_byte: 32 } + when "HARAKA-512" + conf = { provider_config: { algo_name: found, jceProvider: JCEProvider::BCProv.name }, fixed_input_len_byte: 64 } + else + conf = { provider_config: { algo_name: found, jceProvider: JCEProvider::BCProv.name } } + end - Ccrypto::BLAKE2s128.provider_info("BLAKE2S-128"), - Ccrypto::BLAKE2s160.provider_info("BLAKE2s-160"), - Ccrypto::BLAKE2s224.provider_info("BLAKE2s-224"), - Ccrypto::BLAKE2s256.provider_info("BLAKE2s-256"), + digConf = Ccrypto::DigestConfig.new(found, md.getDigestLength()*8, conf) - Ccrypto::HARAKA256.provider_info("HARAKA-256"), - Ccrypto::HARAKA512.provider_info("HARAKA-512"), + testDig = Ccrypto::DigestMatcher.generate_digest(digConf) + digKey = Ccrypto::DigestMatcher.find_digest_key(testDig) + if not_empty?(digKey) + # map the algo name to common name + digConf = Ccrypto::DigestConfig.new(digKey, md.getDigestLength()*8, conf) + @supported.register(digConf, { tag_under: :jceAlgo, tag_value: found }) - Ccrypto::KECCAK224.provider_info("KECCAK-224"), - Ccrypto::KECCAK256.provider_info("KECCAK-256"), - Ccrypto::KECCAK288.provider_info("KECCAK-288"), - Ccrypto::KECCAK384.provider_info("KECCAK-384"), - Ccrypto::KECCAK512.provider_info("KECCAK-512"), + else + logger.warn "Digest algo from Java named '#{found}' not listed in the Ccrypto::DigestMatcher. Skip or add the value into the table. [#{testDig}]" - Ccrypto::RIPEMD128.provider_info("RIPEMD128"), - Ccrypto::RIPEMD160.provider_info("RIPEMD160"), - Ccrypto::RIPEMD256.provider_info("RIPEMD256"), - Ccrypto::RIPEMD320.provider_info("RIPEMD320"), + end - Ccrypto::SHAKE128_256.provider_info("SHAKE128-256"), - Ccrypto::SHAKE256_512.provider_info("SHAKE256-512"), + rescue Exception => ex + logger.error ex.message + end + end + end - Ccrypto::SKEIN1024_1024.provider_info("SKEIN-1024-1024"), - Ccrypto::SKEIN1024_384.provider_info("SKEIN-1024-384"), - Ccrypto::SKEIN1024_512.provider_info("SKEIN-1024-512"), + @supported.save_to_storage("supported_digest") - Ccrypto::SKEIN256_128.provider_info("SKEIN-256-128"), - Ccrypto::SKEIN256_160.provider_info("SKEIN-256-160"), - Ccrypto::SKEIN256_224.provider_info("SKEIN-256-224"), - Ccrypto::SKEIN256_256.provider_info("SKEIN-256-256"), - - Ccrypto::SKEIN512_128.provider_info("SKEIN-512-128"), - Ccrypto::SKEIN512_160.provider_info("SKEIN-512-160"), - Ccrypto::SKEIN512_224.provider_info("SKEIN-512-224"), - Ccrypto::SKEIN512_256.provider_info("SKEIN-512-256"), - Ccrypto::SKEIN512_384.provider_info("SKEIN-512-384"), - Ccrypto::SKEIN512_512.provider_info("SKEIN-512-512"), - - SM3 = Ccrypto::SM3.provider_info("SM3"), - WHIRLPOOL = Ccrypto::WHIRLPOOL.provider_info("WHIRLPOOL") - ] - - def self.supported - if @supported.nil? - @supported = [] - probe = java.security.Security.getAlgorithms("MessageDigest").to_a.delete_if { |e| e.include?(".") } - Potential.each do |po| - @supported << po if probe.include?(po.provider_config) - end end @supported end + class << self + alias_method :supported_digests, :supported + end - def self.is_supported?(eng, prov = nil) - if is_empty?(eng) - false + def self.is_digest_supported?(key) + (find_digest_config(key).length > 0) + end + + def self.instance(conf, &block) + + case conf + when String, Symbol + digEng = find_digest_config(conf) + when Ccrypto::DigestConfig + digEng = conf else + raise DigestEngineException, "Unsupported instance type '#{conf}'" + end - jceName = algo_jce_map[eng] - begin - if not_empty?(prov) - #java.security.MessageDigest.getInstance(eng.to_s.gsub("_","-"), prov) - java.security.MessageDigest.getInstance(jceName, prov) - else - #java.security.MessageDigest.getInstance(eng.to_s.gsub("_","-")) - java.security.MessageDigest.getInstance(jceName) - end - true - rescue java.security.NoSuchAlgorithmException => ex - p ex.message - false - end + raise DigestEngineException, "Unsupported digest type '#{conf}'" if digEng.nil? + + prov = digEng.provider_config[:jceProvider] + if not_empty?(prov) + JCEProvider.instance.add_provider(prov) if not JCEProvider.instance.is_provider_registered?(prov) + DigestEngine.new(digEng.provider_config[:algo_name], prov, &block) + else + DigestEngine.new(digEng.provider_config[:algo_name], &block) end + end - def self.default_algo - "SHA256" + def self.find_digest_config(key) + res = supported.find(algo: key) + res.concat(supported.find(jceAlgo: key)) + res.uniq end - def self.instance(conf, &block) - if block - prov = block.call(:jce_provider) - if not_empty?(prov) - DigestEngine.new(conf.provider_config, prov, &block) - else - DigestEngine.new(conf.provider_config, &block) - end + def self.to_bc_digest_inst(conf) + case conf + when Ccrypto::DigestConfig + algo = conf.provider_config[:algo_name] + when String + algo = conf.upcase + when Symbol + algo = conf.to_s.upcase else - DigestEngine.new(conf.provider_config, &block) + raise DigestEngineException, "Unsupported query type '#{conf.class}'" end - end - def self.digest(key, &block) - res = engineKeys[key] - if is_empty?(res) - raise DigestEngine, "Not supported digest engine #{key}" - else - if block - digProv = block.call(:digest_jceProvider) - end + logger.debug "BC digest matching : #{conf.inspect} ==> #{algo}" - if digProv.nil? - DigestEngine.new(res.provider_config) - else - DigestEngine.new(res.provider_config, digProv) - end + case algo + when "BLAKE2B-160","BLAKE2B_160" + "org.bouncycastle.crypto.digests.Blake2bDigest.new(160)" + when "BLAKE2B-256" + "org.bouncycastle.crypto.digests.Blake2bDigest.new(256)" + when "BLAKE2B-384" + "org.bouncycastle.crypto.digests.Blake2bDigest.new(384)" + when "BLAKE2B-512" + "org.bouncycastle.crypto.digests.Blake2bDigest.new(512)" + when "BLAKE2S-128" + "org.bouncycastle.crypto.digests.Blake2sDigest.new(128)" + when "BLAKE2S-160" + "org.bouncycastle.crypto.digests.Blake2sDigest.new(160)" + when "BLAKE2S-224" + "org.bouncycastle.crypto.digests.Blake2sDigest.new(224)" + when "BLAKE2S-256" + "org.bouncycastle.crypto.digests.Blake2sDigest.new(256)" + when "BLAKE3-256" + "org.bouncycastle.crypto.digests.Blake3Digest.new #(256)" + when "DSTU7564-256" + "org.bouncycastle.crypto.digests.DSTU7564Digest.new(256)" + when "DSTU7564-384" + "org.bouncycastle.crypto.digests.DSTU7564Digest.new(384)" + when "DSTU7564-512" + "org.bouncycastle.crypto.digests.DSTU7564Digest.new(512)" + when "GOST3411" + "org.bouncycastle.crypto.digests.GOST3411Digest.new" + when "GOST3411-2012-256" + "org.bouncycastle.crypto.digests.GOST3411_2012_256Digest.new" + when "GOST3411-2012-512" + "org.bouncycastle.crypto.digests.GOST3411_2012_512Digest.new" + #when "HARAKA-256" + # org.bouncycastle.crypto.digests.Haraka256Digest.new + #when "HARAKA-512" + # org.bouncycastle.crypto.digests.Haraka512Digest.new + when "KECCAK-224" + "org.bouncycastle.crypto.digests.KeccakDigest.new(224)" + when "KECCAK-256" + "org.bouncycastle.crypto.digests.KeccakDigest.new(256)" + when "KECCAK-288" + "org.bouncycastle.crypto.digests.KeccakDigest.new(288)" + when "KECCAK-384" + "org.bouncycastle.crypto.digests.KeccakDigest.new(384)" + when "KECCAK-512" + "org.bouncycastle.crypto.digests.KeccakDigest.new(512)" + when "RIPEMD128" + "org.bouncycastle.crypto.digests.RIPEMD128Digest.new" + when "RIPEMD160" + "org.bouncycastle.crypto.digests.RIPEMD160Digest.new" + when "RIPEMD256" + "org.bouncycastle.crypto.digests.RIPEMD256Digest.new" + when "SHA-1", "SHA1" + "org.bouncycastle.crypto.digests.SHA1Digest.new" + when "SHA-224", "SHA224" + "org.bouncycastle.crypto.digests.SHA224Digest.new" + when "SHA-256", "SHA256" + "org.bouncycastle.crypto.digests.SHA256Digest.new" + when "SHA-384", "SHA384" + "org.bouncycastle.crypto.digests.SHA384Digest.new" + when "SHA-512", "SHA512" + "org.bouncycastle.crypto.digests.SHA512Digest.new" + when "SHA3-224","SHA3_224" + "org.bouncycastle.crypto.digests.SHA3Digest.new(224)" + when "SHA3-256","SHA3_256" + "org.bouncycastle.crypto.digests.SHA3Digest.new(256)" + when "SHA3-384","SHA3_384" + "org.bouncycastle.crypto.digests.SHA3Digest.new(384)" + when "SHA3-512","SHA3_512" + "org.bouncycastle.crypto.digests.SHA3Digest.new(512)" + when "SHAKE128-256","SHAKE128_256" + "org.bouncycastle.crypto.digests.SHAKEDigest.new(128)" + when "SHAKE256-512","SHAKE256_512" + "org.bouncycastle.crypto.digests.SHAKEDigest.new(256)" + when "SKEIN-1024-1024","SKEIN_1024_1024" + "org.bouncycastle.crypto.digests.SkeinDigest.new(1024,1024)" + when "SKEIN-1024-384","SKEIN_1024_384" + "org.bouncycastle.crypto.digests.SkeinDigest.new(1024,384)" + when "SKEIN-1024-512","SKEIN_1024_512" + "org.bouncycastle.crypto.digests.SkeinDigest.new(1024,512)" + when "SKEIN-256-128","SKEIN_256_128" + "org.bouncycastle.crypto.digests.SkeinDigest.new(256,128)" + when "SKEIN-256-160","SKEIN_256_160" + "org.bouncycastle.crypto.digests.SkeinDigest.new(256,160)" + when "SKEIN-256-224","SKEIN_256_224" + "org.bouncycastle.crypto.digests.SkeinDigest.new(256,224)" + when "SKEIN-256-256","SKEIN_256_256" + "org.bouncycastle.crypto.digests.SkeinDigest.new(256,256)" + when "SKEIN-512-128","SKEIN_512_128" + "org.bouncycastle.crypto.digests.SkeinDigest.new(512,128)" + when "SKEIN-512-160","SKEIN_512_160" + "org.bouncycastle.crypto.digests.SkeinDigest.new(512,160)" + when "SKEIN-512-224","SKEIN_512_224" + "org.bouncycastle.crypto.digests.SkeinDigest.new(512,224)" + when "SKEIN-512-256","SKEIN_512_256" + "org.bouncycastle.crypto.digests.SkeinDigest.new(512,256)" + when "SKEIN-512-384","SKEIN_512_384" + "org.bouncycastle.crypto.digests.SkeinDigest.new(512,384)" + when "SKEIN-512-512","SKEIN_512_512" + "org.bouncycastle.crypto.digests.SkeinDigest.new(512,512)" + when "SM3" + "org.bouncycastle.crypto.digests.SM3Digest.new" + when "TIGER" + "org.bouncycastle.crypto.digests.TigerDigest.new" + when "WHIRLPOOL" + "org.bouncycastle.crypto.digests.WhirlpoolDigest.new" end + end - def self.engineKeys - if @engineKeys.nil? - @engineKeys = {} - supported.each do |a| - @engineKeys[a.algo.to_sym] = a - end - end - @engineKeys - end - def self.algo_jce_map - if @algoMap.nil? - @algoMap = {} - supported.each do |a| - @algoMap[a.algo.to_sym] = a.provider_config - end - end - @algoMap + private + def self.logger + Ccrypto::Java.logger(:cj_digest_eng_c) end + public + ## + # Instance method + ## + attr_reader :native_instance def initialize(algo, prov = nil, &block) - teLogger.debug "Algo : #{algo}" - @algo = algo #algo.to_s.gsub("_","-") + + logger.debug "Algo : #{algo}" + + @algo = algo begin if not_empty?(prov) - @inst = java.security.MessageDigest.getInstance(@algo, prov) + @native_instance = java.security.MessageDigest.getInstance(@algo, prov) else - @inst = java.security.MessageDigest.getInstance(@algo) + @native_instance = java.security.MessageDigest.getInstance(@algo) end - #rescue java.security.NoSuchAlgorithmException => ex rescue Exception => ex raise DigestEngineException, ex end end def digest(val, output = :binary) digest_final(val, output) end def digest_update(val) - @inst.update(to_java_bytes(val)) + @native_instance.update(to_java_bytes(val)) end def digest_final(val = nil, output = :binary) if not_empty?(val) - @inst.update(to_java_bytes(val)) + @native_instance.update(to_java_bytes(val)) end - res = @inst.digest - @inst.reset + res = @native_instance.digest + @native_instance.reset case output when :hex to_hex(res) when :b64 to_b64(res) else res end end - def reset - @inst.reset + private + def logger + Ccrypto::Java.logger(:cj_digest_eng) end end end end