首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >散列漏洞

问散列漏洞
EN

Stack Overflow用户
提问于 2018-12-18 13:06:38
回答 2查看 483关注 0票数 2

我想为我的项目添加一些安全性,所以我添加了一个密码字段。为了存储密码,我要使用txt并将其保存在那里,为了增加一些安全性,我使用下面的代码对密码进行散列(如果这很重要,他们的多个密码就这样保存)。这只是我如何做散列的例子,实际程序使用文本文件等。

代码语言:javascript
复制
public static void main(String[] args) throws NoSuchAlgorithmException {

    System.out.println("Enter Password: ");
    Scanner scanner = new Scanner(System.in);
    String enteredPassword = scanner.nextLine();
    String storedPassword = "�D�Ϛ-�UK�c�=�,�}��}��D��Zj>�m";

    MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
    messageDigest.update(enteredPassword.getBytes());
    String hashedString = new String(messageDigest.digest());
    System.out.println(hashedString);

    if(storedPassword.equals(hashedString)){
        System.out.println("Passwords Match!");   
    }else{
        System.out.println("Passwords Do Not Match!");
    }
}

我的问题是,我这样做是安全的,除了反编译我的项目和绕过这个特性是我的项目安全还是这个方法可以被利用?另外,是否有一种方法来保护一个项目不被反编译,并重新编写代码以绕过安全特性?谢谢

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-12-18 13:24:46

这种方法本身是好的;SHA-256本身是一个强大的单向散列函数.它不能被“解密”。但是它是快速的,从而允许使用字典快速强制密码。

为了获得更好的安全性,您可以使用bcrypt或PBKDF2来降低速度。大约100毫秒将不会被用户注意到,但会使蛮力变得不切实际。

下面是一个使用100000次SHA-256迭代的PBKDF2的例子。它也使用随机盐。

代码语言:javascript
复制
SecureRandom random = SecureRandom.getInstanceStrong();
byte[] salt = new byte[16];
random.nextBytes(salt);
KeySpec spec = new PBEKeySpec("my-secret-password".toCharArray(), salt, 100000, 256);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] hash = f.generateSecret(spec).getEncoded();
Base64.Encoder enc = Base64.getEncoder();
System.out.printf("salt: %s%n", enc.encodeToString(salt));
System.out.printf("hash: %s%n", enc.encodeToString(hash));

注意:从Java8开始就可以使用PBKDF2WithHmacSHA256了。

下面是一个更完整的例子:

代码语言:javascript
复制
private static final SecureRandom random = new SecureRandom();

/**
 * One-way encrypts (hashes) the given password.
 * 
 * @param saltpw  the salt (will be generated when null)
 * @param pw      the password to encrypt
 * @return        encrypted salted password
 */
public static String encrypt(String saltpw, String pw) throws GeneralSecurityException {
    byte[] salt;
    if (saltpw == null) {
        salt = new byte[16];
        random.nextBytes(salt);
    } else {
        salt = Base64.getDecoder().decode(saltpw.replaceFirst("\\$.*", ""));
    }
    KeySpec spec = new PBEKeySpec(pw.toCharArray(), salt, 100000, 256);
    SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
    byte[] hash = f.generateSecret(spec).getEncoded();
    Base64.Encoder enc = Base64.getEncoder();
    return enc.encodeToString(salt) + "$" + enc.encodeToString(hash);
}

public static void main(String[] args) throws Exception {
    String enc = encrypt(null, "my-secret-password");
    System.out.printf("enc   : %s\n", enc);
    String test1 = encrypt(enc, "my-secret-password");
    System.out.printf("test 1: %s, valid: %b\n", test1, enc.equals(test1));
    String test2 = encrypt(enc, "some-other-password");
    System.out.printf("test 2: %s, valid: %b\n", test2, enc.equals(test2));
}

指纹:

代码语言:javascript
复制
enc   : B5V6SjkjJpeOxvMAkPf7EA==$NNDA7o+Dpd+M+H99WVxY0B8adqVWJHZ+HIjgPxMljwo=
test 1: B5V6SjkjJpeOxvMAkPf7EA==$NNDA7o+Dpd+M+H99WVxY0B8adqVWJHZ+HIjgPxMljwo=, valid: true
test 2: B5V6SjkjJpeOxvMAkPf7EA==$4H1SpH8N+/jqU40G6RWb+ReHUB3C58iAaU4l39j+TV8=, valid: false

注意test 1是如何产生与原始密码完全相同的加密字符串的,而test 2 (有错误的密码)并不是这样,所以您可以通过比较散列来验证所提供的密码是否有效。

票数 2
EN

Stack Overflow用户

发布于 2018-12-18 13:10:55

没有办法禁止java的反编译。

但是,如果使用混淆器,则很难理解反编译代码。例如https://www.guardsquare.com/en/products/proguard

这会将所有的方法名、类名、变量名更改为无意义的短名称。一个副作用是你的类文件也会缩小.

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53833711

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档