通过 java 的 sha1 加 salt 加密,和 node crypto 生成的加密值不一致。有踩过坑的吗?
1
sagaxu 2017-12-19 20:01:28 +08:00 via Android 2
那只能说明你写错了
|
2
Jaylee 2017-12-19 20:15:02 +08:00
如果要加密的字符串有中文的话,node 需要指定编码
|
3
mcfog 2017-12-19 20:17:24 +08:00 via Android
//密码学问题不要自作聪明,加盐就乖乖用 hmac 来加
|
4
dennisge OP 1. 这是原 java 的加密
a123456 => 79893503e8074330321974fa14dc44f8aa1b3df0 plainPassword = StringUtils.trim(plainPassword); byte[] salt = Digests.generateSalt(SALT_SIZE); // af350c3413179ab4 byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, HASH_INTERATIONS); private static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) { try { MessageDigest digest = MessageDigest.getInstance(algorithm); if (salt != null) { digest.update(salt); } byte[] result = digest.digest(input); for (int i = 1; i < iterations; i++) { digest.reset(); result = digest.digest(result); } return result; } catch (GeneralSecurityException e) { throw Exceptions.unchecked(e); } } 2. node |
5
dennisge OP 2.node
const old = 'af350c3413179ab479893503e8074330321974fa14dc44f8aa1b3df0'; const origin = 'a123456'; const saltStr = old.substring(0, 16); const salt = new Buffer(saltStr, 'hex'); const originBuf = new Buffer(origin); console.log('originBuf>>'); console.log(originBuf); console.log(originBuf.length); const encrypt1 = crypto.createHash('sha1') .update(salt) .update(originBuf) .digest('hex'); const encrypt2 = crypto.createHmac('sha1', salt) .update(originBuf) .digest('hex'); console.log(encrypt1); console.log(encrypt2); => originBuf>> <Buffer 61 31 32 33 34 35 36> 7 e03f07ac2befce638c5886adecbec96a06ce5a51 ab7b28b75346d63105a9bdc5a0365c1967eb132c |
9
SlipStupig 2017-12-19 20:54:17 +08:00
我遇到过 pypy 和 python hmac 不一样过......
|
11
lihongjie0209 2017-12-19 20:56:29 +08:00
盐( Salt ),在密码学中,是指在散列之前将散列内容(例如:密码)的任意固定位置插入特定的字符串。这个在散列中加入字符串的方式称为“加盐”。其作用是让加盐后的散列结果和没有加盐的结果不相同,在不同的应用情景中,这个处理可以增加额外的安全性。
在大部分情况,盐是不需要保密的。盐可以是随机产生的字符串,**其插入的位置可以也是随意而定**。如果这个散列结果在将来需要进行验证(例如:验证用户输入的密码),则需要将已使用的盐记录下来。 加盐的位置是随机的. |
12
rrfeng 2017-12-19 20:57:14 +08:00 via Android
一般来说就是参数不一致。
不同语言的库可能有不同的默认参数的,仔细看一下文档应该能解决。 |
13
dennisge OP @lihongjie0209 解释的很详细。但是我现在就是 java 加密的密码,用相同的盐,结果 node 却解不出来
|
15
dennisge OP 我怀疑是不是 java 支持的带符号整型,而 node 不支持。af350c3413179ab4 。这个是 salt 的 hex 值,java 的 8 个字节有负数,而 node 是不支持的,这个造成了 salt 不一样???
|
16
hsuan 2017-12-19 21:38:30 +08:00 via Android
sha1 能叫加密吗
|
17
metrxqin 2017-12-19 22:07:11 +08:00
代码能贴完整点吗?
|
18
zhicheng 2017-12-19 22:12:37 +08:00 1
原因很简单,你写错了。
|
19
sagaxu 2017-12-19 22:17:08 +08:00
|
20
sagaxu 2017-12-19 22:18:03 +08:00
node 结点的黑底白字配色,让我这个近视加散光严重的,彻底受不了了,逃离
|
21
neoblackcap 2017-12-19 22:27:25 +08:00
在一段时间我曾经写过多种语言的客户端校验模块,曾用了多种语言自带的 sha1 等实现。针对题主的问题,我只能很肯定地说你写错了。
我只能猜你那 digest 函数出问题了,你那多次的迭代是干嘛的?我没看到 node 版本有多次迭代,你若要比较请给出你的迭代参数 iterations |
22
superhan 2017-12-19 22:49:37 +08:00 via Android
|
25
dennisge OP @neoblackcap 上面的 java 实现,是先人的代码,我也不清楚那个多个迭代的作用。iterations 是 1024。不懂 java,所以没理解透。
|
26
dennisge OP @superhan 看了您发的这个,学习了。但和我的场景有些不一样。以前他们 java 生成的密码加密值,现在用 node 得不到。你给的例子,salt 的都是 string 的,而这里 salt 是一个 bytes [], 这个会有关系吗?
|
27
zhicheng 2017-12-19 23:43:03 +08:00
@dennisge 你写错了,不要怀疑语言,不要怀疑算法,不要怀疑类库,不要找借口,不要说这是坑。
没有什么可指教的,就是调用一个函数的事儿,我不知道这种事情怎么“指教”,要是还不懂,就把上边那句话再念一遍。 Java ``` import java.security.MessageDigest; import javax.xml.bind.DatatypeConverter; class a { public static void main(String args[]) { String str = "a123456"; String salt = "af350c3413179ab4"; try { MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update(DatatypeConverter.parseHexBinary(salt)); md.update(str.getBytes()); System.out.println(DatatypeConverter.printHexBinary(md.digest())); } catch (Exception e) { e.printStackTrace(); } } } ``` JS ``` crypto = require('crypto'); const str = 'a123456'; const salt = new Buffer('af350c3413179ab4', 'hex'); console.log(crypto.createHash('sha1').update(salt).update(str).digest('hex')); ``` Python ``` import hashlib print hashlib.sha1('af350c3413179ab4'.decode('hex') + 'a123456').hexdigest() ``` |
28
dennisge OP @zhicheng 感谢您的回答,但是您能得到这个最终的加密值吗? 79893503e8074330321974fa14dc44f8aa1b3df0。 我感觉和你用的方法没啥不一样啊,但就是得不到最后的值。是不是和原 java 实现的
for (int i = 1; i < iterations; i++) { digest.reset(); result = digest.digest(result); } 有关系? |
30
neoblackcap 2017-12-20 00:02:10 +08:00
@dennisge 我看你这 Java 实现是对加盐并 sha1 处理一次后的二进制流再进行了 1024 次的 sha1 迭代。你试试用 node 版本对你现在的结果再进行 1024 次 sha1 看看
|
31
dennisge OP @neoblackcap java 是以前别人的代码。并没有理解透。能麻烦您你解释下吗
|
32
zhicheng 2017-12-20 00:06:45 +08:00
@dennisge 我并不想打击你,这真的是一眨眼,一个函数调用的事儿。
``` import hashlib result = hashlib.sha1('af350c3413179ab4'.decode('hex') + 'a123456').digest() for i in range(1, 1024): result = hashlib.sha1(result).digest() print result.encode('hex') ``` 79893503e8074330321974fa14dc44f8aa1b3df0 |
36
dennisge OP @zhicheng 不过我刚用 node 实现一遍,还是不一样哦,结果不对。
const crypto = require('crypto'); const salt = 'af350c3413179ab4'; const saltStr = new Buffer(salt, 'hex').toString('utf8'); console.log(saltStr); let result = crypto.createHash('sha1').update(saltStr + 'a123456').digest('hex'); for (let i = 1; i <= 1024; i++) { result = crypto.createHash('sha1').update(result).digest('hex'); } console.log(result); |
38
ryd994 2017-12-20 03:40:49 +08:00 via Android
循环 hash1024 次,真是意义不明
反复 hash 只会减小值域不可能增加 初中数学去哪了? |
39
ryd994 2017-12-20 03:44:40 +08:00 via Android
还有,就算是 1024 次 sha1 也是快的一比
bcrypt 调调难度系数,分分钟超过你的兔子算法 密码储存讲究的是慢,才能避免字典攻击 |
41
dennisge OP @ryd994 恩,因为 java 代码是以前别人 java 实现了。现在我们要 node 重写,只能按以前的破逻辑重写了。不过你说的 bcrypt 会更好吗,还会引入 node-gyp
|
42
dexterlei 2017-12-20 09:08:06 +08:00
我的经验是,总可以发现是自己写错了
|
44
kohos 2017-12-20 09:31:29 +08:00
这种加盐迭代 sha1 的方法应该就是 pbkdf2 算法吧……恭喜解决问题
|
45
dennisge OP |
46
vefawn1 2017-12-20 09:46:38 +08:00 via Android
我很好奇,为何打开这个页面后网页背景变黑了?
|
48
pusadao 2017-12-20 10:21:56 +08:00
const crypto = require('crypto')
const sha1 = crypto.createHash('sha1') const salt = new Buffer('af350c3413179ab4', 'hex') const origin = new Buffer('a123456') sha1.update(salt) sha1.update(origin) let result = sha1.digest() for (let i = 1; i < 1024; i++) { result = crypto.createHash('sha1').update(result).digest() } console.log(result.toString('hex')) // 79893503e8074330321974fa14dc44f8aa1b3df0 |
49
hantsy 2017-12-20 11:53:12 +08:00
不同语言加密结果不一样的可能性不大。
对 Spring Stack, Spring Security 4 开始使用新的 PasswordEncoder,早不需要 Salt 了,我早不关心 Salt 了。一直其使用推荐的 BCrypt,即使密码相同,加密结果也不一样,不用担心密码碰撞问题 。 Spring Secuirty 5 也加强更为现代的 PasswordEncoder 功能, BCrypt 是默认的(如果启用的话)。 |
50
hantsy 2017-12-20 12:11:38 +08:00
不过我对密码加密之类没什么太多的研究,有这方面经验的人,不妨分享一下一些基本的知识:
1. crypt 2. salt 3. hash 等等 |
54
metrxqin 2017-12-20 15:46:13 +08:00
`高手` **如云**!
|
55
edsgerlin 2017-12-22 10:12:52 +08:00
密码加密乖乖用 PBKDF2, BCrypt, Argon2 这些专业的 KDF,别自己瞎搞。
|