| | |
| | | * |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2010 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | |
| | | */ |
| | | private static final int NUM_SALT_BYTES = 8; |
| | | |
| | | |
| | | // Size of the dgiest in bytes. |
| | | private static final int SHA256_LENGTH = 256 / 8; |
| | | |
| | | // The message digest that will actually be used to generate the 256-bit SHA-2 |
| | | // hashes. |
| | |
| | | public boolean passwordMatches(ByteSequence plaintextPassword, |
| | | ByteSequence storedPassword) |
| | | { |
| | | // Base64-decode the stored value and take the last 8 bytes as the salt. |
| | | byte[] saltBytes = new byte[NUM_SALT_BYTES]; |
| | | byte[] digestBytes; |
| | | // Base64-decode the stored value and take the first 256 bits |
| | | // (SHA256_LENGTH) as the digest. |
| | | byte[] saltBytes; |
| | | byte[] digestBytes = new byte[SHA256_LENGTH]; |
| | | int saltLength = 0; |
| | | |
| | | try |
| | | { |
| | | byte[] decodedBytes = Base64.decode(storedPassword.toString()); |
| | | |
| | | int digestLength = decodedBytes.length - NUM_SALT_BYTES; |
| | | digestBytes = new byte[digestLength]; |
| | | System.arraycopy(decodedBytes, 0, digestBytes, 0, digestLength); |
| | | System.arraycopy(decodedBytes, digestLength, saltBytes, 0, |
| | | NUM_SALT_BYTES); |
| | | saltLength = decodedBytes.length - SHA256_LENGTH; |
| | | saltBytes = new byte[saltLength]; |
| | | System.arraycopy(decodedBytes, 0, digestBytes, 0, SHA256_LENGTH); |
| | | System.arraycopy(decodedBytes, SHA256_LENGTH, saltBytes, 0, |
| | | saltLength); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | |
| | | |
| | | // Use the salt to generate a digest based on the provided plain-text value. |
| | | int plainBytesLength = plaintextPassword.length(); |
| | | byte[] plainPlusSalt = new byte[plainBytesLength + NUM_SALT_BYTES]; |
| | | byte[] plainPlusSalt = new byte[plainBytesLength + saltLength]; |
| | | plaintextPassword.copyTo(plainPlusSalt); |
| | | System.arraycopy(saltBytes, 0,plainPlusSalt, plainBytesLength, |
| | | NUM_SALT_BYTES); |
| | | saltLength); |
| | | |
| | | byte[] userDigestBytes; |
| | | |
| | |
| | | * |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2010 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | |
| | | private static final int NUM_SALT_BYTES = 8; |
| | | |
| | | |
| | | // The size of the digest in bytes. |
| | | private static final int SHA384_LENGTH = 384 / 8; |
| | | |
| | | // The message digest that will actually be used to generate the 384-bit SHA-2 |
| | | // hashes. |
| | |
| | | public boolean passwordMatches(ByteSequence plaintextPassword, |
| | | ByteSequence storedPassword) |
| | | { |
| | | // Base64-decode the stored value and take the last 8 bytes as the salt. |
| | | byte[] saltBytes = new byte[NUM_SALT_BYTES]; |
| | | byte[] digestBytes; |
| | | // Base64-decode the stored value and take the first 384 bits |
| | | // (SHA384_LENGTH) as the digest. |
| | | byte[] saltBytes; |
| | | byte[] digestBytes = new byte[SHA384_LENGTH]; |
| | | int saltLength = 0; |
| | | |
| | | try |
| | | { |
| | | byte[] decodedBytes = Base64.decode(storedPassword.toString()); |
| | | |
| | | int digestLength = decodedBytes.length - NUM_SALT_BYTES; |
| | | digestBytes = new byte[digestLength]; |
| | | System.arraycopy(decodedBytes, 0, digestBytes, 0, digestLength); |
| | | System.arraycopy(decodedBytes, digestLength, saltBytes, 0, |
| | | NUM_SALT_BYTES); |
| | | saltLength = decodedBytes.length - SHA384_LENGTH; |
| | | saltBytes = new byte[saltLength]; |
| | | System.arraycopy(decodedBytes, 0, digestBytes, 0, SHA384_LENGTH); |
| | | System.arraycopy(decodedBytes, SHA384_LENGTH, saltBytes, 0, |
| | | saltLength); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | |
| | | |
| | | // Use the salt to generate a digest based on the provided plain-text value. |
| | | int plainBytesLength = plaintextPassword.length(); |
| | | byte[] plainPlusSalt = new byte[plainBytesLength + NUM_SALT_BYTES]; |
| | | byte[] plainPlusSalt = new byte[plainBytesLength + saltLength]; |
| | | plaintextPassword.copyTo(plainPlusSalt); |
| | | System.arraycopy(saltBytes, 0,plainPlusSalt, plainBytesLength, |
| | | NUM_SALT_BYTES); |
| | | saltLength); |
| | | |
| | | byte[] userDigestBytes; |
| | | |
| | |
| | | * |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2010 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | |
| | | private static final int NUM_SALT_BYTES = 8; |
| | | |
| | | |
| | | // The size of the digest in bytes. |
| | | private static final int SHA512_LENGTH = 512 / 8; |
| | | |
| | | // The message digest that will actually be used to generate the 512-bit SHA-2 |
| | | // hashes. |
| | |
| | | public boolean passwordMatches(ByteSequence plaintextPassword, |
| | | ByteSequence storedPassword) |
| | | { |
| | | // Base64-decode the stored value and take the last 8 bytes as the salt. |
| | | byte[] saltBytes = new byte[NUM_SALT_BYTES]; |
| | | byte[] digestBytes; |
| | | // Base64-decode the stored value and take the first 512 bits |
| | | // (SHA512_LENGTH) as the digest. |
| | | byte[] saltBytes; |
| | | byte[] digestBytes = new byte[SHA512_LENGTH]; |
| | | int saltLength = 0; |
| | | |
| | | try |
| | | { |
| | | byte[] decodedBytes = Base64.decode(storedPassword.toString()); |
| | | |
| | | int digestLength = decodedBytes.length - NUM_SALT_BYTES; |
| | | digestBytes = new byte[digestLength]; |
| | | System.arraycopy(decodedBytes, 0, digestBytes, 0, digestLength); |
| | | System.arraycopy(decodedBytes, digestLength, saltBytes, 0, |
| | | NUM_SALT_BYTES); |
| | | saltLength = decodedBytes.length - SHA512_LENGTH; |
| | | saltBytes = new byte[saltLength]; |
| | | System.arraycopy(decodedBytes, 0, digestBytes, 0, SHA512_LENGTH); |
| | | System.arraycopy(decodedBytes, SHA512_LENGTH, saltBytes, 0, |
| | | saltLength); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | |
| | | |
| | | // Use the salt to generate a digest based on the provided plain-text value. |
| | | int plainBytesLength = plaintextPassword.length(); |
| | | byte[] plainPlusSalt = new byte[plainBytesLength + NUM_SALT_BYTES]; |
| | | byte[] plainPlusSalt = new byte[plainBytesLength + saltLength]; |
| | | plaintextPassword.copyTo(plainPlusSalt); |
| | | System.arraycopy(saltBytes, 0,plainPlusSalt, plainBytesLength, |
| | | NUM_SALT_BYTES); |
| | | saltLength); |
| | | |
| | | byte[] userDigestBytes; |
| | | |
| | |
| | | * |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2010 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | |
| | | * @param allowPreencoded whether or not to allow pre-encoded passwords |
| | | * @return the previous value for the allow preencoded passwords |
| | | */ |
| | | private boolean setAllowPreencodedPasswords(boolean allowPreencoded) |
| | | protected boolean setAllowPreencodedPasswords(boolean allowPreencoded) |
| | | throws Exception |
| | | { |
| | | // This code was borrowed from |
| | |
| | | * |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2010 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | | |
| | | import static org.testng.Assert.*; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.admin.std.meta. |
| | | SaltedSHA256PasswordStorageSchemeCfgDefn; |
| | | import org.opends.server.admin.std.server.SaltedSHA256PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | import org.opends.server.types.Entry; |
| | | |
| | | |
| | | |
| | |
| | | scheme.initializePasswordStorageScheme(configuration); |
| | | return scheme; |
| | | } |
| | | |
| | | /** |
| | | * Retrieves a set of passwords (plain and SSHA256 encrypted) that may |
| | | * be used to test the compatibility of SSHA256 passwords. |
| | | * The encrypted versions have been provided by external tools or |
| | | * users |
| | | * |
| | | * @return A set of couple (cleartext, encrypted) passwords that |
| | | * may be used to test the SSHA256 password storage scheme |
| | | */ |
| | | |
| | | @DataProvider(name = "testSSHA256Passwords") |
| | | public Object[][] getTestSSHA256Passwords() |
| | | throws Exception |
| | | { |
| | | return new Object[][] |
| | | { |
| | | new Object[] { "secret", "{SSHA256}xIar81hLva6DoMGVtk5WWfJTnBvkyAsYkj0phSdBBDW2DC1dXI79cw==" } |
| | | }; |
| | | } |
| | | |
| | | @Test(dataProvider = "testSSHA256Passwords") |
| | | public void testAuthSSHA256Passwords( |
| | | String plaintextPassword, |
| | | String encodedPassword) throws Exception |
| | | { |
| | | // Start/clear-out the memory backend |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | boolean allowPreencodedDefault = setAllowPreencodedPasswords(true); |
| | | |
| | | try { |
| | | |
| | | Entry userEntry = TestCaseUtils.makeEntry( |
| | | "dn: uid=testSSHA256.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: testSSHA256.user", |
| | | "givenName: TestSSHA256", |
| | | "sn: User", |
| | | "cn: TestSSHA256 User", |
| | | "userPassword: " + encodedPassword); |
| | | |
| | | |
| | | // Add the entry |
| | | TestCaseUtils.addEntry(userEntry); |
| | | |
| | | assertTrue(TestCaseUtils.canBind("uid=testSSHA256.user,o=test", |
| | | plaintextPassword), |
| | | "Failed to bind when pre-encoded password = \"" + |
| | | encodedPassword + "\" and " + |
| | | "plaintext password = \"" + |
| | | plaintextPassword + "\"" ); |
| | | } finally { |
| | | setAllowPreencodedPasswords(allowPreencodedDefault); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | * |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2010 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | | |
| | | import static org.testng.Assert.*; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | | import org.opends.server.admin.std.meta. |
| | | SaltedSHA512PasswordStorageSchemeCfgDefn; |
| | | import org.opends.server.admin.std.server.SaltedSHA512PasswordStorageSchemeCfg; |
| | | import org.opends.server.api.PasswordStorageScheme; |
| | | import org.opends.server.types.Entry; |
| | | |
| | | |
| | | |
| | |
| | | scheme.initializePasswordStorageScheme(configuration); |
| | | return scheme; |
| | | } |
| | | |
| | | /** |
| | | * Retrieves a set of passwords (plain and SSHA512 encrypted) that may |
| | | * be used to test the compatibility of SSHA512 passwords. |
| | | * The encrypted versions have been provided by external tools or |
| | | * users |
| | | * |
| | | * @return A set of couple (cleartext, encrypted) passwords that |
| | | * may be used to test the SSHA512 password storage scheme |
| | | */ |
| | | |
| | | @DataProvider(name = "testSSHA512Passwords") |
| | | public Object[][] getTestSSHA512Passwords() |
| | | throws Exception |
| | | { |
| | | return new Object[][] |
| | | { |
| | | new Object[] { "secret", "{SSHA512}8gRXO3lD2fGN3JIhbNJOsh31IRFKnWbDNl+cPH3HoJCkUpxZPG617TnN6Nvl2mVMSBLlzPu2eMpOhCDKoolNG6QCsYf2hppQTAVaqfx25PUJ1ngbuBiNDCpK6Xj5PYZiFwa+cpkY/Pzs77bLn3VMxmHhwa+vowfGhy5RRW+6npQ=" } |
| | | }; |
| | | } |
| | | |
| | | @Test(dataProvider = "testSSHA512Passwords") |
| | | public void testAuthSSHA512Passwords( |
| | | String plaintextPassword, |
| | | String encodedPassword) throws Exception |
| | | { |
| | | // Start/clear-out the memory backend |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | boolean allowPreencodedDefault = setAllowPreencodedPasswords(true); |
| | | |
| | | try { |
| | | |
| | | Entry userEntry = TestCaseUtils.makeEntry( |
| | | "dn: uid=testSSHA512.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: testSSHA512.user", |
| | | "givenName: TestSSHA512", |
| | | "sn: User", |
| | | "cn: TestSSHA512 User", |
| | | "userPassword: " + encodedPassword); |
| | | |
| | | |
| | | // Add the entry |
| | | TestCaseUtils.addEntry(userEntry); |
| | | |
| | | assertTrue(TestCaseUtils.canBind("uid=testSSHA512.user,o=test", |
| | | plaintextPassword), |
| | | "Failed to bind when pre-encoded password = \"" + |
| | | encodedPassword + "\" and " + |
| | | "plaintext password = \"" + |
| | | plaintextPassword + "\"" ); |
| | | } finally { |
| | | setAllowPreencodedPasswords(allowPreencodedDefault); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |