require_relative '../data_conversion' module Ccrypto module Java class DigestEngine include TR::CondUtils include DataConversion class SupportedDigestEngine include InMemoryRecord def initialize define_search_key(:algo, :outBitLength, :outByteLength) end end 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 if @supported.empty? @supported = SupportedDigestEngine.new probe = java.security.Security.getAlgorithms("MessageDigest").to_a.delete_if { |e| e.include?(".") } logger = Ccrypto::Java.logger(:digest_eng) 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 digConf = Ccrypto::DigestConfig.new(found, md.getDigestLength()*8, conf) 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 }) else logger.warn "Digest algo from Java named '#{found}' not listed in the Ccrypto::DigestMatcher. Skip or add the value into the table. [#{testDig}]" end rescue Exception => ex logger.error ex.message end end end @supported.save_to_storage("supported_digest") end @supported end class << self alias_method :supported_digests, :supported end 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 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.find_digest_config(key) res = supported.find(algo: key) res.concat(supported.find(jceAlgo: key)) res.uniq 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 raise DigestEngineException, "Unsupported query type '#{conf.class}'" end logger.debug "BC digest matching : #{conf.inspect} ==> #{algo}" 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 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) logger.debug "Algo : #{algo}" @algo = algo begin if not_empty?(prov) @native_instance = java.security.MessageDigest.getInstance(@algo, prov) else @native_instance = java.security.MessageDigest.getInstance(@algo) end rescue Exception => ex raise DigestEngineException, ex end end def digest(val, output = :binary) digest_final(val, output) end def digest_update(val) @native_instance.update(to_java_bytes(val)) end def digest_final(val = nil, output = :binary) if not_empty?(val) @native_instance.update(to_java_bytes(val)) end res = @native_instance.digest @native_instance.reset case output when :hex to_hex(res) when :b64 to_b64(res) else res end end private def logger Ccrypto::Java.logger(:cj_digest_eng) end end end end