所以我试图从使用 PBKDF2 生成的密钥生成 JWT 令牌,并且代码在android中是这样的:
public SecretKey generateKey(String passphraseOrPin) throws NoSuchAlgorithmException, InvalidKeySpecException {
final int iterations = 5000;
// Generate a 256-bit key
final int outputKeyLength = 256;
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2withHmacSHA256");
KeySpec keySpec = new PBEKeySpec(getSha256Hash(passphraseOrPin).toCharArray(), salt.getBytes(), iterations, outputKeyLength);
SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);
return secretKey;
}
但是每当我尝试生成令牌时:
String jwtString = Jwts.builder().setSubject("sub").signWith(key, SignatureAlgorithm.HS256).compact();
我遇到了错误:
Process: com.android.gocontract, PID: 7434
java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.
at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:111)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: io.jsonwebtoken.security.InvalidKeyException: The signing key's algorithm 'PBKDF2WithHmacSHA256' does not equal a valid HmacSHA* algorithm name and cannot be used with HS256.
at io.jsonwebtoken.SignatureAlgorithm.assertValid(SignatureAlgorithm.java:358)
at io.jsonwebtoken.SignatureAlgorithm.assertValidSigningKey(SignatureAlgorithm.java:302)
at io.jsonwebtoken.impl.DefaultJwtBuilder.signWith(DefaultJwtBuilder.java:123)
at com.android.gocontract.Activity.LoginActivity$2.onNext(LoginActivity.java:192)
at com.android.gocontract.Activity.LoginActivity$2.onNext(LoginActivity.java:163)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeOnObserver.onNext(ObservableSubscribeOn.java:58)
at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:200)
at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:252)
at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:109)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2019-09-23 18:38:37.036 7434-7434/com.android.gocontract I/Process: Sending signal. PID: 7434 SIG: 9
生成Sha256的方法:
public String getSha256Hash(String password) {
try {
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e1) {
e1.printStackTrace();
}
digest.reset();
return bin2hex(digest.digest(password.getBytes()));
} catch (Exception ignored) {
return null;
}
}
jjwt 的版本:
api 'io.jsonwebtoken:jjwt-api:0.10.7'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.10.7'
runtimeOnly('io.jsonwebtoken:jjwt-orgjson:0.10.7') {
exclude group: 'org.json', module: 'json' //provided by Android natively
}
答案 0 :(得分:1)
解决方案::使用其他加密算法,或使用lib Spongy Castle。
有用的lib:Nimbus JOSE JWT Spongycastle,如果您需要将jwt与海绵城堡混合的帮助。
为什么它对您不起作用:这是您所使用设备的特殊性。有些设备支持带有HmacSHA256算法的PBKDF2,而另一些设备则不支持。
我如何得出这个结论: 首先,我认为这可能是一个简单的错字,但我在JJWT github中发现,尽管确实存在该问题,但该问题已得到解决。由于验证现在使用的是等号,因此拼写无关紧要。您可以在code中进行确认。
然后我认为它可能是android或java版本。但是我发现since java 8版本已经实现。
我认为它可能是android版本,但是它可以从API 26开始使用。
我还测试了您正在使用的代码,在这里工作得很好,因此不会出现任何这些问题。然后,我进行了很多研究,发现一些other questions的人在other libs和其他algorithms上存在相同的问题。
其他: k3v中有一段代码可能可以帮助您(使用海绵城堡):
PKCS5S2ParametersGenerator generator = new PKCS5S2ParametersGenerator(new SHA256Digest());
generator.init(PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(password), salt, iterations);
KeyParameter key = (KeyParameter)generator.generateDerivedMacParameters(keySizeInBits);