require 'gcrypto' require_relative 'secretkey' require_relative 'error' require_relative 'io_utils' require_relative 'provider' require_relative 'global' module GcryptoJce module KDF module HKDF #def extract(opts = { }) # # salt = opts[:salt] # if salt.nil? # salt = Java::byte[hmac.mac_length].new # end # # secKey = javax.crypto.spec.SecretKeySpec.new(salt, "AES") # # hmacSpec = opts[:hmacEng] || 'HmacSHA256' # hmac = javax.crypto.Mac.getInstance(hmacSpec) # hmac.init(secKey) # ikm = opts[:ikm] # if ikm.nil? # raise GcryptoJce::Error, "Input Key Material (IKM) cannot be nil. It can be any random value or message itself" # end # is = IoUtils.load_input(ikm) # # os = java.io.ByteArrayOutputStream.new # begin # bufConf = opts[:int_buf] || { } # total = 0 # IoUtils.read_chunk(is, bufConf) do |buf, from, len| # os.write(hmac.update(buf, from, len)) # total += len # GcryptoJce::GConf.instance.glog.debug "Processed #{NumberHelper.number_to_human_size(total)}" # end # os.write(hmac.doFinal) # rescue Exception # ensure # begin # is.close # os.flush # os.close # rescue Exception # end # end # #end # end extract # # allow key to be expended to arbitary length according to RFC5869 def expand(opts = {}) key = opts[:key] if key.nil? raise GcryptoJce::Error, "Key is not given to HKDF for expansion operation" else key = IoUtils.ensure_java_bytes(key) end kcType = opts[:key_type] || :aes case kcType when :aes, "AES", "aes" secKey = javax.crypto.spec.SecretKeySpec.new(key, "AES") else raise GcryptoJce::Error, "Unknown key type '#{kcType}'" end hmacSpec = opts[:hmacEng] || 'HmacSHA256' hmac = javax.crypto.Mac.getInstance(hmacSpec) hmac.init(secKey) ctxInfo = opts[:contextInfo] if ctxInfo.nil? ctxInfoBytes = "".to_java.getBytes else ctxInfoBytes = IoUtils.ensure_java_bytes(ctxInfo) end baseBuf = java.io.ByteArrayOutputStream.new baseBuf.write(key) baseBuf.write(ctxInfoBytes) baseBufBin = baseBuf.toByteArray baseBufLen = baseBufBin.length GcryptoJce::GConf.instance.glog.debug "baseBufBin : #{baseBufBin}" baseBlock = Java::byte[baseBufLen+1].new java.lang.System.arraycopy(baseBufBin,0,baseBlock,0,baseBufLen) GcryptoJce::GConf.instance.glog.debug "baseBlock : #{baseBlock}" # always in bits reqKeyLen = opts[:outKeyLen] loopCnt = ((reqKeyLen*1.0) / (hmac.mac_length*8*1.0)).ceil GcryptoJce::GConf.instance.glog.debug "loopCnt : #{loopCnt}" exOut = java.io.ByteArrayOutputStream.new cnt = 0 while (cnt < loopCnt) do baseBlock[baseBlock.length-1] = cnt #GcryptoJce::GConf.instance.glog.debug "baseBlock (#{cnt}) : #{baseBlock[baseBlock.length-1]}" hash = hmac.doFinal(baseBlock) exOut.write(hash) cnt += 1 end expanded = exOut.toByteArray ret = Java::byte[reqKeyLen/8].new java.lang.System.arraycopy(expanded,0,ret,0,ret.length) ret end # end expand # end # end HKDF # class HKDFEngine extend HKDF end end # end KDF # end # end GcryptoJce