如果有人可以给出一些指示: 我有一个由PBEKeySpec生成的KeySpec:
KeySpec spec = new PBEKeySpec(password.toCharArray(), "SALTSALT".getBytes(), 20000, 160);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] encoded = f.generateSecret(spec).getEncoded();
编码的byte []变量存储在Postgres DB 9.x上,测试环境中的这个值工作得很好,但是当我将它部署到OpenShift时,PBEKeySpec生成的byte []不会返回相同的值(它应该),与我存储在DB上的值相比,编码问题可能吗?任何线索?
来自相同密码的对应日志: 另一件事,OS上的byte []将大小从20改为39
Test environment, passwd stored on DB: [-87, 98, 56, 51,55, 99, 99, 100, 53, 56, 57, 52, 51, 54, 101, 100, 50, 98, 51, 51, 57, 100, 98, 54, 99, 51, 98, 56, 102, 50, 99, 50, 50, 98, 51, 51, 49, 57, 49] size 39
OpenShift gear, password from login: [-117, -12, -115, -38, -58, -100, -62, 70, -87, 98, -73, 114, -56, 115, -91, 5, 23, 44, 119, 21] size: 20
完整代码:
public abstract class PasswordServiceImpl implements PasswordByteService {
private String ENCRIPT_ALGORITHM = "PBKDF2WithHmacSHA1";
private int ENCRYPT_DEVIRED_KEY_LENGTH = 160;
private int ENCRIPT_ITERATIONS = 20000;
private String SALT_ALGORITHM = "SHA1PRNG";
@Override
public boolean authenticate(final String attemptedPassword, final byte[] encryptedPassword, final byte[] salt)
throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] encryptedAttemptedPassword = getEncryptedPassword(attemptedPassword, salt);
return Arrays.equals(encryptedPassword, encryptedAttemptedPassword);
}
@Override
public byte[] getEncryptedPassword(final String password, byte[] salt)
throws NoSuchAlgorithmException, InvalidKeySpecException {
String algorithm = ENCRIPT_ALGORITHM;
int derivedKeyLength = ENCRYPT_DEVIRED_KEY_LENGTH;
int iterations = ENCRIPT_ITERATIONS;
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations, derivedKeyLength);
SecretKeyFactory f = SecretKeyFactory.getInstance(algorithm);
byte[] encoded = f.generateSecret(spec).getEncoded();
return encoded;
}
@Override
public byte[] generateSalt() throws NoSuchAlgorithmException, NoSuchProviderException {
SecureRandom random;
random = SecureRandom.getInstance(SALT_ALGORITHM,"SUN");
byte[] salt = new byte[8];
random.nextBytes(salt);
return salt;
}
}
通过entityManager存储用户,休眠。 实体
@Entity
public class UserData implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
@Basic(optional = false)
@Column
private byte[] password;
...
配置类
@Stateless
public class ConfigurationBean implements Configuration {
...
@PersistenceContext(unitName = "primary")
private EntityManager em;
...
private void populateFailSafeUser(){
try {
PasswordService pws = new PasswordServiceImpl();
byte[] salt = pws.generateSalt();
byte[] encryptedPassword = pws.getEncryptedPassword(Values.FAILSAFE_USER_PASS, salt);
UserData failsafeUser = new UserData(Values.FAILSAFE_USER_NAME, encryptedPassword, salt );
em.persist(failsafeUser);
em.flush();
} catch (NoSuchAlgorithmException | InvalidKeySpecException ex) {
LOGGER.error(Msg.ERROR_ENCRIPTION_SERVICES);
} catch (NoSuchProviderException ex) {
LOGGER.error(Msg.ERROR_ENCRIPTION_SERVICES + " proveedor de seguridad no encontrado!");
}
}
答案 0 :(得分:0)
根据您发布的代码,您似乎并未将盐存储在数据库中。您需要存储加密密码时使用的生成的盐。然后,在验证用户输入的密码时,需要使用数据库中的相同盐。
<强>更新强>
如果您确实在生成原始加密密码和生成尝试密码以进行身份验证时使用完全相同的盐,并从f.generateSecret(spec)
获取不同的值,那么我最好的猜测是,有某种OpenShift上的错误。特别是如果它在本地使用完全相同的代码。
我建议尽可能少地重现问题,并使用OpenShift opening a bug report。试着让Postgres离开它;如果你确定你从Postgres那里得到的东西和你原来的东西一样,那么它不是问题的一部分。