首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

JAVA JCE兑现HASH+SALT强密文

2012-09-02 
JAVA JCE实现HASH+SALT强密文口令的安全策略在传统密码学家眼中只有一种加密是理想的,那就是“一次一密”,当

JAVA JCE实现HASH+SALT强密文

口令的安全策略
在传统密码学家眼中只有一种加密是理想的,那就是“一次一密”,当然事实上这是不可能的。但如果我们套用这种词法,我们也可以说,口令安全策略的理想境界,我们可以称为单向、一人一密、一站一密。

单向:标准HASH算法的价值尽管在这个场景下,已经被推倒,但其单向性的思想依然是正确的,口令只要是能还原的,就意味着攻击者也能做到这一点,从而失去了意义,因此使用单向算法是必须的。

一人一密:同一个站点设置同样口令的不同用户,加密生成的密文内容并不相同。这样就能有效的应对结果碰撞和统计攻击。采用字典的攻击的方法基本是不收敛的。

一站一密:仅仅保证一人一密是不够的,还要保证使用同样信息、同样口令去注册不同网站的用户,在不同站点的口令加密结果是不同的。鉴于有大量用户用同样的信息、同样的口令去注册不同网站,如果能做到这一点,流失出的库信息会进一步打折扣。而攻击者基本会放弃生成密文字典的尝试。

实现这些说起来很简单,依然是HASH+SALT,关键在于每个站点要有不同的SALT,每个用户要有不同的盐。

具体实现
怎么来具体实现一站一密、一人一密的策略呢,在Java 6 中已支持使用JCE(JavaTM Cryptography Extension )实现PBKDF2加密算法。
在使用JCE之前须安装JCE Unlimited Strength Policy,步骤如下:
1、到 Java JCE下载(http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html);
2、解压缩ZIP;
3、将local_policy.jar and和US_export_policy.jar复制到JAVA_HOME/jre/lib/security。

安装好了,就可以用了,代码如下:

String systemPassword = "password"; //一站一密String userPassword = "User Password"; //用户密码SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");byte[] salt = new byte[16];SecureRandom random = new SecureRandom();random.nextBytes(salt); // 一人一粒‘盐’KeySpec spec = new PBEKeySpec(systemPassword.toCharArray(), salt, 1024, 256);SecretKey tmp = factory.generateSecret(spec);SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");//加密逻辑Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE, secret);AlgorithmParameters params = cipher.getParameters();byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();byte[] ciphertext = cipher.doFinal(userPassword.getBytes("UTF-8"));//保存IV,解密时需要String ivStr = new BigInteger(iv).toString(16);System.out.println("IV: " + ivStr);//保存Encrypted Data,解密时需要String encryData = new BigInteger(ciphertext).toString(16);System.out.println("Encrypted Data: " + encryData);//解密逻辑KeySpec dspec = new PBEKeySpec(systemPassword.toCharArray(), salt, 1024, 256);SecretKey dsecretKey = new SecretKeySpec(factory.generateSecret(dspec).getEncoded(), "AES");Cipher dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");dcipher.init(Cipher.DECRYPT_MODE, dsecretKey,new IvParameterSpec(new BigInteger(ivStr, 16).toByteArray()));String plaintext = new String(dcipher.doFinal(new BigInteger(encryData,16).toByteArray()),"UTF-8");//有了解密后的文本,只需和用户输入的密码比对就可以了System.out.println(plaintext);

?

?

热点排行