当前位置:   article > 正文

密钥派生函数的java实现_java kdf算法

java kdf算法

一,什么是密钥派生函数

    引用国密规范GM/T 0003.4-2012SM2椭圆曲线公钥密码算法 4部分:公钥加密算法》中5.4.3小节描述,密钥派生函数的作用是从一个共享的秘密比特串中派生出密钥数据。通俗的讲,是将一个输入比特串转换成特定长度的输出比特串,转换过程中使用了密码杂凑函数(也就是摘要函数)。密钥派生函数在椭圆曲线公钥加解密与密钥协商等密码运算场景都有应用。

二、密钥派生函数的定义

   定义: KDF(Z, klen)

   输入: Z,比特串;klen,整数,派生结果比特串的长度

   输出:长度为klen的密钥比特串K

   算法:

         a) 初始化一个32比特的计数器ct = 0x00000001;

         b) i 1    éklen/vù执行:

                  b.1) 计算 Hai = Hv(Z || ct) ;    --Hv() 表示输出长度为vHash函数

                  b.2) ct++;

        c) klen/v 是整数,Ha ! éklen/vù = Ha éklen/vù,否则Ha ! éklen/vù Ha éklen/vù最左边的 (klen-(v*ëklen/vû))比特。  --éklen/vù是顶函数,ëklen/vû是底函数

      d) K=Ha1||Ha2||||Haéklen/vù-1|| Ha ! éklen/vù 

三、JAVA代码实现

 

public static byte[] KDF(byte[] Z, int klen) {

              int sm3_v = 256;

              int hashNum = (int)Math.ceil((double)klen/sm3_v);

              boolean isInt = klen % sm3_v == 0 ? true : false;

 

              SM3Digest sm3 = new SM3Digest();

              int ct = 0x1;

 

              byte[] tempK = new byte[hashNum * 32];

             

              int realByteNum = 0;

              for (int i = 1; i <= hashNum; i++) {

 

                     byte[] ctBytes = Pack.intToBigEndian(ct);

                    

                     sm3.reset();

                     sm3.update(Z, 0, Z.length);

                     sm3.update(ctBytes, 0, ctBytes.length);

 

                     byte[] Ha = new byte[32];

                     sm3.doFinal(Ha, 0);

                    

                     ct++;

                    

                     if (hashNum == i && !isInt) { //最后一个hash,取最左边lastHashBitNum

                            int floor = (int)Math.floor((double)klen/sm3_v);

                            int lastHashBitNum = klen - sm3_v * floor;

                            int maskedByteLen = lastHashBitNum / 8;

                           

                            System.arraycopy(Ha, 0, tempK, (i - 1) * 32, maskedByteLen);

                            realByteNum += maskedByteLen;

                           

                            if (0 != lastHashBitNum % 8) {

                                   int maskedBitLen = 8 - lastHashBitNum % 8;

                                   byte maskByte = (byte)(~((1 << (8 - maskedBitLen)) - 1));

                                   tempK[(i - 1) * 32 + maskedByteLen] = (byte)(maskByte & Ha[maskedByteLen]);

                                   realByteNum += 1;

                            }

                           

                     } else {

                            System.arraycopy(Ha, 0, tempK, (i - 1) * 32, Ha.length);

                            realByteNum += 32;

                     }

              }

 

              byte[] k = new byte[realByteNum];

              System.arraycopy(tempK, 0, k, 0, realByteNum);

              return k;

       }

 

注:由于KDF函数在java实现时返回值k是以字节位单位,所以不能严格以klen长度的比特串返回,所以在做最后一次HASH运算时,如果klen不是字节(8)的整数倍,需要对最后一个字节做掩码运算处理。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/687787
推荐阅读
相关标签
  

闽ICP备14008679号