Java 生成的密码不适用于 LDIF 文件
Java generated password not working on LDIF file
我正在尝试使用来自此处 [LDIF 示例][1] 的 LDIF 的简单 LDAP 示例。我能够设置所有内容并 运行 使用默认值 user/pass 正确设置它。
但是,我正在尝试生成新用户,我使用下面的 Java 代码为 "joe" 生成密码,但它似乎不起作用:
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
private static String get_SHA_1_SecurePassword(String passwordToHash)
{
String generatedPassword = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] bytes = md.digest(passwordToHash.getBytes());
StringBuilder sb = new StringBuilder();
for(int i=0; i< bytes.length ;i++)
{
sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
}
generatedPassword = sb.toString();
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
return generatedPassword;
}
上面示例 link 中用于检查密码的代码:
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups")
.contextSource()
.url("ldap://localhost:8389/dc=springframework,dc=org")
.and()
.passwordCompare()
.passwordEncoder(new LdapShaPasswordEncoder())
.passwordAttribute("userPassword");
}
这是带有密码的 LDIF 文件片段:
//working copy for ben from example
dn: uid=ben,ou=people,dc=springframework,dc=org
dn: uid=ben,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Ben Alex
sn: Alex
uid: ben
userPassword: {SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ=
//new user "joe"
dn: uid=joe,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Joe S
sn: joe
uid: joe
userPassword: {SHA}9c509e6d68f17da2db1c71b5424e54538b6b6ef4
我给 joe 使用的密码是 "joe",我似乎无法接受它。加密方式不同吗?顺便说一下,我正在使用 Windows。
您可以将其用于 SHA-512
您使用 MessageDigest.getInstance("SHA-1") -->MessageDigest.getInstance("SHA-512");
的实例
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public String get_SHA_512_SecurePassword(String passwordToHash, String salt){
String generatedPassword = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-512");
md.update(salt.getBytes(StandardCharsets.UTF_8));
byte[] bytes = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for(int i=0; i< bytes.length ;i++){
sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
}
generatedPassword = sb.toString();
}
catch (NoSuchAlgorithmException e){
e.printStackTrace();
}
return generatedPassword;
}
请检查这个问题
您的函数看起来不错,应该会输出正确的加盐 SHA-1 哈希值。
但是,您的 LDIF 文件中的存储方案前缀应该是 {SSHA}(用于加盐 SHA1)而不是 {SHA} - 或者您不打算使用加盐 (?)。
此外,哈希算法的实际输出是二进制数据,可以用十六进制或 base64 字符串表示。 LDAP 存储方案使用 base64 编码。
你能做什么?
在你的 LDIF 中我们可以识别十六进制字符串,所以第一件事是使哈希编码为 base64 而不是十六进制,具体取决于导入的 base64 包:
// Using org.apache.commons.codec.binary.Base64
generatedPassword = Base64.encodeBase64String(bytes);
// Using java.util.Base64
generatedPassword = Base64.getEncoder().encodeToString(bytes);
如果您不想加盐,则需要注释掉以下行(如果加盐字符串为空,它仍然是 "salt",并且不会产生与不加盐):
md.update(salt.getBytes(StandardCharsets.UTF_8));
根据以上几点设置合适的存储方案前缀。例如,使用带盐的 SHA-1,ldif 中的密码属性值应如下所示:
userPassword: {SSHA}<base64_encoded_hash>
其他一些需要考虑的事情:
OpenLDAP 支持以下加密方案:SHA、SSHA、MD5、SMD5 和 CRYPT。
SHA 和 SSHA 都使用 SHA-1 算法。
要支持 SHA-2 及其变体,请使用 slapd 的 pw-sha2 覆盖(支持 SHA-224、SHA-256、SHA-384、SSHA-224、SSHA- 256,SSHA-384)。它既可以用 slapd 静态编译,也可以动态加载,因为它启用了模块支持。
另请参阅:14.4。来自 https://www.openldap.org/doc/admin24/security.html
的密码存储
我正在尝试使用来自此处 [LDIF 示例][1] 的 LDIF 的简单 LDAP 示例。我能够设置所有内容并 运行 使用默认值 user/pass 正确设置它。
但是,我正在尝试生成新用户,我使用下面的 Java 代码为 "joe" 生成密码,但它似乎不起作用:
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
private static String get_SHA_1_SecurePassword(String passwordToHash)
{
String generatedPassword = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] bytes = md.digest(passwordToHash.getBytes());
StringBuilder sb = new StringBuilder();
for(int i=0; i< bytes.length ;i++)
{
sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
}
generatedPassword = sb.toString();
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
return generatedPassword;
}
上面示例 link 中用于检查密码的代码:
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups")
.contextSource()
.url("ldap://localhost:8389/dc=springframework,dc=org")
.and()
.passwordCompare()
.passwordEncoder(new LdapShaPasswordEncoder())
.passwordAttribute("userPassword");
}
这是带有密码的 LDIF 文件片段:
//working copy for ben from example
dn: uid=ben,ou=people,dc=springframework,dc=org
dn: uid=ben,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Ben Alex
sn: Alex
uid: ben
userPassword: {SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ=
//new user "joe"
dn: uid=joe,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Joe S
sn: joe
uid: joe
userPassword: {SHA}9c509e6d68f17da2db1c71b5424e54538b6b6ef4
我给 joe 使用的密码是 "joe",我似乎无法接受它。加密方式不同吗?顺便说一下,我正在使用 Windows。
您可以将其用于 SHA-512 您使用 MessageDigest.getInstance("SHA-1") -->MessageDigest.getInstance("SHA-512");
的实例import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public String get_SHA_512_SecurePassword(String passwordToHash, String salt){
String generatedPassword = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-512");
md.update(salt.getBytes(StandardCharsets.UTF_8));
byte[] bytes = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for(int i=0; i< bytes.length ;i++){
sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
}
generatedPassword = sb.toString();
}
catch (NoSuchAlgorithmException e){
e.printStackTrace();
}
return generatedPassword;
}
请检查这个问题
您的函数看起来不错,应该会输出正确的加盐 SHA-1 哈希值。
但是,您的 LDIF 文件中的存储方案前缀应该是 {SSHA}(用于加盐 SHA1)而不是 {SHA} - 或者您不打算使用加盐 (?)。
此外,哈希算法的实际输出是二进制数据,可以用十六进制或 base64 字符串表示。 LDAP 存储方案使用 base64 编码。
你能做什么?
在你的 LDIF 中我们可以识别十六进制字符串,所以第一件事是使哈希编码为 base64 而不是十六进制,具体取决于导入的 base64 包:
// Using org.apache.commons.codec.binary.Base64 generatedPassword = Base64.encodeBase64String(bytes); // Using java.util.Base64 generatedPassword = Base64.getEncoder().encodeToString(bytes);
如果您不想加盐,则需要注释掉以下行(如果加盐字符串为空,它仍然是 "salt",并且不会产生与不加盐):
md.update(salt.getBytes(StandardCharsets.UTF_8));
根据以上几点设置合适的存储方案前缀。例如,使用带盐的 SHA-1,ldif 中的密码属性值应如下所示:
userPassword: {SSHA}<base64_encoded_hash>
其他一些需要考虑的事情:
OpenLDAP 支持以下加密方案:SHA、SSHA、MD5、SMD5 和 CRYPT。
SHA 和 SSHA 都使用 SHA-1 算法。
要支持 SHA-2 及其变体,请使用 slapd 的 pw-sha2 覆盖(支持 SHA-224、SHA-256、SHA-384、SSHA-224、SSHA- 256,SSHA-384)。它既可以用 slapd 静态编译,也可以动态加载,因为它启用了模块支持。
另请参阅:14.4。来自 https://www.openldap.org/doc/admin24/security.html
的密码存储