-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Question] Can shiro 2.0 + use shiro 1 's hash Algorithm, such as "SHA-256" ? #1022
Comments
No, it cannot. We're about to update the documentation about this. SHA1 is insecure for most applications, which is why only SHA256 upwards (for Hashing) and Argon2 and bcrypt (for storing passwords) are included. |
@bmarwell Thanks. |
Oh right! We actually might be able to convert that. Let me fiddle around a bit in the next few days. However, I highly recommend that you regenerate the passwords using argon2. |
yes, passwords in old project need convert or other processing, |
Hey @sam2099! Side question: @bdemers I think we talked about an upgrade path two years ago. While it would not hurt to READ old passwords ONCE, we (Shiro) would not be able if it was still used for storage again. I think this is why support was dropped altogether. Does that help? |
I would think that would be much easier to do if there was a way to read the password (but not write them) for a good upgrade path. |
Depending on the size of (and how much friction it would cause) your user base. A more complex option would be to check if a user's password has was stored in an older format, if so validate the hash. Shiro doesn't provide password write APIs so you would need to write custom code for this.
|
Hey @bmarwell
I would think shiro can be to read the old password (but not write them) , then we guide users to change new password |
No, Shiro cannot read your password. If you used the hash Algorithms from Shiro 1, then the passwords the user enters will be hashed with the same algorithm and THEN compared to the string which was saved. |
I don’t think he meant “read” literally. But to be able to authenticate using old algorithm and then prompt the user to enter new password and that would be saved using the new algorithm |
yes |
Hi, HOWEVER: I highly recommend not to do this, but to encrypt the passwords to the new Full example:
I am going to close this issue, if the fix doesn't work, please feel free to re-open it. |
@lprimak Thanks ! I can not re-open it. JDK 17/21 + spring boot 3 + shiro 2.0.0-alpha-4 public class EncryptTest {
@Test
void encryptPassword() {
DefaultPasswordService passwordService = new DefaultPasswordService();
passwordService.setHashService(new HS());
passwordService.setHashFormat(new Shiro1CryptFormat());
System.out.println(passwordService.encryptPassword("hello123"));
}
private final static class HS extends DefaultHashService {
HS() {
setDefaultAlgorithmName("SHA-256");
}
}
} result is $shiro1$SHA-512$50000$W7dSfsTHQFdLvuBKzq8EfA==$754vzFx0/pcYR4JGL2I24PIw+I8Ba5oqD4pHhEsVezK9MOP41B6ZJH4+mkxHDxTBxVQ2T90RQZ8F1T/7Bl45nw== I set "SHA-256" but output is "SHA-512" !!! |
@sam2099 Good catch! I didn't see that one.
|
or even simpler, the whole HS class is no longer necessary |
[#1022] DefaultPasswordService takes HashService default hash…
@lprimak Thanks very much ! In our old system with shiro1, We set iterations as 1, salt as null; such as password is "123456789o", saved encryptPassword is "$shiro1$SHA-256$1$$jZae727K08KaOmKSgOaGzww/XVqGr/PKEgIMkjrcbJI=". now we need authenticat with shiro 2, code as below: @Test
void encryptPassword() {
DefaultPasswordService passwordService = new PasswordService();
passwordService.setHashFormat(new Shiro1CryptFormat());
System.out.println(passwordService.encryptPassword("123456789o"));
//authenticat example
System.out.println(passwordService.passwordsMatch("123456789o", "$shiro1$SHA-256$1$$jZae727K08KaOmKSgOaGzww/XVqGr/PKEgIMkjrcbJI="));
}
private final static class PasswordService extends DefaultPasswordService {
@Override
protected HashRequest createHashRequest(ByteSource plaintext) {
return new HashRequest.Builder().setSource(plaintext)
.setAlgorithmName(Sha256Hash.ALGORITHM_NAME).addParameter("SimpleHash.iterations", 1)
.build();
}
} result Exception [main] WARN o.a.shiro.crypto.hash.SimpleHash - Cannot recreate a hash using the same parameters.
java.lang.IllegalArgumentException: Argument for byte conversion cannot be null.
at org.apache.shiro.lang.codec.CodecSupport.toBytes(CodecSupport.java:203)
at org.apache.shiro.crypto.hash.SimpleHash.toByteSource(SimpleHash.java:247)
at org.apache.shiro.crypto.hash.SimpleHash.convertSaltToBytes(SimpleHash.java:233)
at org.apache.shiro.crypto.hash.SimpleHash.<init>(SimpleHash.java:202)
at org.apache.shiro.crypto.hash.SimpleHash.matchesPassword(SimpleHash.java:280)
at org.apache.shiro.authc.credential.DefaultPasswordService.passwordsMatch(DefaultPasswordService.java:108)
at org.apache.shiro.authc.credential.DefaultPasswordService.passwordsMatch(DefaultPasswordService.java:169) |
try this and use the result in
|
[#1022] bugfix(crypto): Shiro 1 hash parser now supports unsalted passwords
@lprimak @Test
void shiro1PasswordsMatchByShiro2() {
DefaultPasswordService passwordService = new PasswordService();
passwordService.setHashFormat(new Shiro1CryptFormat());
//authenticate example
Assertions.assertTrue(passwordService.passwordsMatch("123456", toHash("$shiro1$SHA-256$1$$jZae727K08KaOmKSgOaGzww/XVqGr/PKEgIMkjrcbJI=")));
Assertions.assertTrue(passwordService.passwordsMatch("123456789o", toHash("$shiro1$SHA-256$1$$qdTQef3V/i7GigwRj0DWlgt2oAMGGbZgjOt4V4lNNoA=")));
Assertions.assertTrue(passwordService.passwordsMatch("SDGSDG123456789o#@", toHash("$shiro1$SHA-256$1$$6kVafxRNvmDiFQDLEaN09D+UkkLEYfRPSBzNfCKf6Fc=")));
Assertions.assertTrue(passwordService.passwordsMatch("我是密码123asdfA#@", toHash("$shiro1$SHA-256$1$$+sE4/mtXoDeGiywr0Yt93o1QhhLHgcrshkvV6NjnjaQ=")));
}
Hash toHash(String encryptedPassword) {
if (new DefaultHashFormatFactory().getInstance(encryptedPassword) instanceof ParsableHashFormat phf) {
if (phf.parse(encryptedPassword) instanceof SimpleHash sh) {
sh.setSalt(ByteSource.Util.bytes(new byte[0]));
sh.setIterations(1);
return sh;
}
}
throw new IllegalArgumentException("Invalid encrypted password");
}
private final static class PasswordService extends DefaultPasswordService {
@Override
protected HashRequest createHashRequest(ByteSource plaintext) {
return new HashRequest.Builder().setSource(plaintext)
.setAlgorithmName(Sha256Hash.ALGORITHM_NAME)
.build();
}
} |
Glad you were successful! You can remove the workarounds when the new version of Shiro is released. |
Summary, TL;DR: the changes are minimal and things work like before. OFBiz uses now Shiro 2.0.0 for AES ciphering instead of Shiro 1.13.0. OFBiz still uses 3-DES and other (older) ciphering methods in case AES would fail facing old data. This also removes now useless "temporary workaround to compile Shiro 2.0.0 without LDAP" component block in dependencies.gradle Details: This uses 'org.apache.shiro:shiro-crypto-cipher:2.0.0' instead of previously wrongly committed org.apache.shiro:shiro-crypto:2.0.0 It re-installs org.apache.shiro:shiro-core:1.13.0 I have still to completely review apache/shiro#1022 According to it, it seems that for now we need to keep shiro-core:1.13.0 http://svn.apache.org/viewvc?view=revision&revision=1814704, and the more complete dev ML discussion referred in the commit message explains why we keep 3-DES and other (older) ciphering methods. I see no problems with that. But, we may want to completely get rid of the old 3-DES and old ways by refactoring this part of code. And maybe offering a way to migrate the data to AES. The Shiro issue referred above may help in this way. Thanks: Lenny from Apache Shiro project for the idea.
Search before asking
Question
I use shiro 2.0.0-alpha-2 with shiro 1 's hash Algorithm "SHA-256" , exception as below:
exception:
The text was updated successfully, but these errors were encountered: