首页 > 编程语言 >hmacSha256 php java结果不一样问题

hmacSha256 php java结果不一样问题

时间:2023-01-04 22:01:52浏览次数:41  
标签:PHP java String System hmacSha256 println php digest out

  1. 比如我们有个服务是PHP提供的,要求的签名方式 hmacSha256取摘要,然后 Base64编码转化成可见字符。

  2. PHP那边的源码是这样的

    $result = base64_encode(hash_hmac("SHA256" , "内容" , '密钥'));
    echo $result; 
    

    我们放到php在线调试平台取看看执行结果:

  3. 然后看看Java的

     @Test
     void sendMessage2() {
         String  secretKey = "密钥";
         String  apiUser = "";
         String  msisdn = "内容";
    
         HMac hmac = SecureUtil.hmac(HmacAlgorithm.HmacSHA256, secretKey );
    
         byte[] digest = hmac.digest(msisdn);
    
         System.out.println( "code="+ Base64.encodeToString( digest  )  );
    
     }
    

    执行结果如下:

  4. 明显Java的比php的结果短了一半

  5. 修改代码看看真实的签名长度

    @Test
    void sendMessage2() {
        String  secretKey = "密钥";
        String  apiUser = "";
        String  msisdn = "内容";

        HMac hmac = SecureUtil.hmac(HmacAlgorithm.HmacSHA256, secretKey );

        byte[] digest = hmac.digest(msisdn);


        System.out.println( "code="+ Base64.encodeToString( digest  )  );


        //打印签名长度
        System.out.println("Java签名长度:" + digest.length * 8 );
        System.out.println("php签名长度长度:" + Base64.decode( "MjZiOThhMjE1NDVjMWEzYWNkZGZjMzRjYTM4Mjc3MjYzMTE0NTE4MTIwZjhmMGQ5YTcxYWNmMzhlMDQ1YmRhOA==" ).length*8 );

    }

执行结果:

  1. 明显PHP不止256位,但是前面用的算法确实是 sha256?为啥呢?原因是PHP那边用的字符串编码方式是源文件的编码方式。Java 用的unicode码,8个字节表示一个字符,PHP字符串更具源码编码方式不同,可能占用的是16个字节表示一个字符。所以PHP的长了一倍,变成了512位。

  2. 怎么解决其实16字节表示一个8位能表示的字符的时候,高位都是0,如果服务提供方是PHP,那么我们只能Java这边兼容PHP的编码方式。在每个字符的扩展成16字节的字符,高位都补上0。

    下面是处理代码:

     /**
      * 一个字节的换成2个字节的(PHP那边的编码方式决定占用2个字节)
      */
     static final String HEXES = "0123456789abcdef";
     public static String getHex( byte [] raw ) {
         if ( raw == null ) {
             return null;
         }
         final StringBuilder hex = new StringBuilder( 2 * raw.length );
         for ( final byte b : raw ) {
             hex.append(HEXES.charAt((b & 0xF0) >> 4))
                     .append(HEXES.charAt((b & 0x0F)));
         }
         return hex.toString();
     }
    
  3. 最终结果

    @Test
    void sendMessage2() {
        String  secretKey = "密钥";
        String  apiUser = "";
        String  msisdn = "内容";

        HMac hmac = SecureUtil.hmac(HmacAlgorithm.HmacSHA256, secretKey );

        byte[] digest = hmac.digest(msisdn);


        //System.out.println( "code="+ Base64.encodeToString( digest  )  );
        //扩展成PHP的一个字符占用16字节
        System.out.println( "code="+ Base64.encodeToString( getHex(digest).getBytes()  )  );


        //打印签名长度
        System.out.println("Java签名长度:" + getHex(digest).getBytes().length * 8 );
        System.out.println("php签名长度长度:" + Base64.decode( "MjZiOThhMjE1NDVjMWEzYWNkZGZjMzRjYTM4Mjc3MjYzMTE0NTE4MTIwZjhmMGQ5YTcxYWNmMzhlMDQ1YmRhOA==" ).length*8 );

    }

    public static String base64sha256(String data, String secret) {
        String hash = null;
        try {
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256");
            sha256_HMAC.init(secret_key);
            byte[] res = sha256_HMAC.doFinal(data.getBytes("UTF-8"));

            System.out.println("长度:"  + res.length );
            hash = getHex(res);

            System.out.println("长度:"  + hash.getBytes().length );
            hash = Base64.encodeToString(hash.getBytes("UTF-8"));
        } catch (Exception e){}
        return hash;
    }

运行结果结果:

长度是一样的了,核对签名内容也是一样的,sha256的算法得到256位,强行填充成了,512位,实在没必要。

如果是别人给你提供的服务那么你只能按照别的的规矩来,如果你是PHP服务的提供方,我建议源文件用unicode编码,毕竟sha256算法算出来的摘要的结果本来就应该是256位。

标签:PHP,java,String,System,hmacSha256,println,php,digest,out
From: https://www.cnblogs.com/cxygg/p/17026117.html

相关文章

  • Java8新特性-Lambda表达式
    Lambda表达式在Java语言中引入了一个操作符**“->”**,该操作符被称为Lambda操作符或箭头操作符。它将Lambda分为两个部分:左侧:指定了Lambda表达式需要的所有参数......
  • Day2 Java基础小记
    Java基础小记Java特性和优势简单性面向对象可移植性性高性能分布式动态性多线程安全性健壮性Java为什么能够成功?Java三大版本JavaSE:标准版(桌面程序,控......
  • javaWeb实现完整的登录功能(新手使用)
    十一部写一个完整的javaWeb登录(一个正在路上的小白纯手敲代码,无复制,大神绕路,供新上路的同学们一起交流)建议从底层往上编写dao接口--->dao实现类--->service接口--->servic......
  • Java反射机制详解
     时间:2022/11/03 一.引出在学习反射的时候,大家可能会纠结反射技术有什么作用,下面我们通过这里需求来说明反射是如何解决现有技术不能解决的问题的:根据配置文件re......
  • resin报错:java.lang.IllegalStateException: block Block
    java.lang.IllegalStateException:blockBlock启动resin时报错主要的提示信息就是下面这个java.lang.IllegalStateException:blockBlock[Table[mnode:2,d:\XXXX\resi......
  • 第2章:Java基本语法
    1、关键字和保留字关键字(keyword)的定义和特点:定义:被Java语言赋予了特殊含义,用做专门用途的字符串(或单词)。特点:关键字中所有字母都为小写字母。官方发布的所有关键字:......
  • Java 复习篇2---jdk
    jdk文件:bin该路径下存放了各种工具命令,其中重要的有javac和Javaconf:改路径下存放了相关配置文件include:该路径下存放了一些平台特定的头文件jmods;该路径下存放......
  • Java复习篇3---基础概念
    关键字关键字:被Java赋予了特定含义的英文单词关键字的字母全是小写常用的代码编辑器,针对关键字会有特殊的颜色标记,非常直观例如:class:用于(创建\定义)一个类,后面紧......
  • Java流程控制
    1.Scanner对象  2.顺序结构  3.选择结构if单选择结构 if双选择结构 if多选择结构 嵌套的if结构 switch多选择结构  4......
  • java 基础 -- Comparable 和 Comparator
    packagecom.example.javareview.comparable;importjava.util.*;/***一、说明:Java中的对象,正常情况下,只能进行比较:==或!=。不能使用>或<的*......