最近项目上遇到一个让我感觉比较困扰的问题,我们提供的用java编写的sm4加密算法计算得到的结果和项目上反馈的js编写的结果不一样。对比代码发现了一个有趣的事情。

java和js的加密步骤及方法几乎是一样的,最后把问题定位在了下面这个方法上:

java:

private long SHL(long x, int n)
	{
		return (x & 0xFFFFFFFF) << n;
	}

javascript:

this.SHL=function(x,n){
            return (x & 0xFFFFFFFF) << n;
     }

这里的返回结果为什么不一致呢,起初我百思不得其解;后来看到这样一篇文章

javascript 数字(Number类型)的范围,整数的范围是多少?_cvper's world !-CSDN博客_javascript number 范围

由于js整形对应的十进制只有16位,所以整数范围是-2^53  ------  2^53   。 所以在& 和<<之后会把长于16位的二进制给截掉。所以sm4算法在这里开始产生分歧。这也就是为什么js和java用sm4加密,结果不一样。

这里可以看一下我在java上的一些处理

如果我没有转成long类型的话,默认的是int,java同样也会有两种计算结果。

问题到此就复现完成了,后续解决方法需要我们以其中一个为准改另外一个就可以了

现在js也有了bigDecimal工具类,有兴趣的同学可以通过这个工具类实现加密同步。

更多推荐

SM4算法的ECB模式在java和js中的一些区别