我们使用java-jwt编写了小型API。当我创建一个令牌并在Java代码中验证令牌时,它工作正常。
然后将公钥提供给客户端,我们开始使用生成的令牌调用其REST服务。客户端使用https://www.npmjs.com/package/jsonwebtoken验证令牌。他们回来说,令牌和公钥提供了jwt.io调试器中的无效签名。他们要求首先在jwt.io调试器中使其工作。我不明白它在Java代码中使用同一个公共时为什么在jwt.io中这样说。我错过了什么吗?
public void createPemFiles(String absoluteFilePath) throws Exception {
logger.log(Level.INFO, "Received request to create Key pair : " + absoluteFilePath);
PemWriter pemWriter = new PemWriter();
// create key pair
final KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");
generator.initialize(KEY_SIZE);
final KeyPair keyPair = generator.generateKeyPair();
// write private key
final RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
privateKeyPem = new File(absoluteFilePath);
pemWriter.writePrivateKey(privateKey, "RSA PRIVATE KEY", privateKeyPem.getAbsolutePath());
logger.log(Level.INFO, "Created private key : " + privateKeyPem.getAbsolutePath());
// write public key
publicKeyPem = new File(absoluteFilePath+".pub");
final RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
pemWriter.writePublicKey(publicKey, "RSA PUBLIC KEY", publicKeyPem.getAbsolutePath());
logger.log(Level.INFO, "Created public key : " + publicKeyPem.getAbsolutePath());
}
public String createJWTToken(String [] keyValues) {
final HashMap<String, Object> claims = new HashMap<String, Object>();
String [] nameValue;
for(String keyValue : keyValues) {
nameValue = keyValue.split("##");
claims.put(nameValue[0],nameValue[1]);
}
return JWTSIGNER.sign(claims, OPTIONS);
}
public String verifyJWTToken(String token) throws Exception{
logger.log(Level.DEBUG, "Received request for verify JWT token");
Map<String, Object> claims = JWTVERIFIER.verify(token);
String claimString = "";
String key = "";
String value = "";
for(Map.Entry<String, Object> entry : claims.entrySet()) {
key = entry.getKey();
value = (String) entry.getValue().toString();
claimString = claimString + key +":"+ value + "##";
}
claimString = replaceLast(claimString, "##", "");
logger.log(Level.DEBUG, "Successfully verified : "+claimString);
return claimString;
}
输入
iccid:4454788545885968585##
nonce:5e452610c9f9decd:-404fb717:157fd6fc54e:-7ffe##
timestamp:2016-10-25T16:16:36.036Z
创建令牌输出
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpY2NpZCI6IjQ0NTQ3ODg1NDU4ODU5Njg1ODUiLCJub25jZSI6IjVlNDUyNjEwYzlmOWRlY2Q6LTQwNGZiNzE3OjE1N2ZkNmZjNTRlOi03ZmZlIiwidGltZXN0YW1wIjoiMjAxNi0xMC0yNVQxNjoxNjozNi4wMzZaIn0.PlWVn1jlkvjRpw34-fsjJGQVVd74sFdg7SS2UgA4HUx4vBMYMA4b-Zzg5VxyzYkhzSsQqjKn7UBw04fXIwsmaP9A7Pc3-MjHjbmYT3Yv52qvH4yNy6X_M0z41UHuuLaWVQN3eck5BKIoO2cy4ihb8OOISkzF1Cf-Udx1GB-bVY4C4JtIvGpMflVW4hS9ZpWzKz26qlva7Y9KMEmvW24tviNcy8aVNyC55MS_KS_Ab7YWQ-MERRiNTCDIqUG7YVSN2Ap_SsNMab687GknQh78ibAowUdpLbGRU4N5EHZyG2lg-u-oL594fRA2anr-JunSxtpkI8-tKzR9NG5dt4F79Q
验证令牌输出
iccid:4454788545885968585##
nonce:5e452610c9f9decd:-404fb717:157fd6fc54e:-7ffe##
timestamp:2016-10-25T16:16:36.036Z
公钥
-----BEGIN RSA PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx58WGD/wRFnwe64sl/9V
KuNOQChYUy8GfhQU66M2XSnx/UpjPCqhGYRmpUXT+rQAamUDsarGt8Kbw1DtlvLT
p2UTvSWiCJNQzi53CRa6iDbk213Ps7zuAFhuXB7s0ZqdOZbeJnXFFM/wMJbM6kdB
yAdCwj8/kCKCjSt3Q0CLdxaToTucRJuO7/V4wbJIDMfLt3LPlry/PsHQAx0RKXco
TO1JsSGWg99dHBEqpxLMBtZyhyd8++PrMrtQ4pPVAmXoJODKY2NZkiLl3h4Ai48z
FhBNHsWQDTJKA8skb2JQER9i1a1/ip/cgkR6FG6G65DbhrMElcL0mgdst49PF26p
pwIDAQAB
-----END RSA PUBLIC KEY-----
答案 0 :(得分:5)
似乎jwt.io需要公钥文件(PKCS#8):
-----BEGIN PUBLIC KEY-----
BASE64 DATA
-----END PUBLIC KEY-----
而不是您传递的RSA公钥文件(PKCS#1):
-----BEGIN RSA PUBLIC KEY-----
BASE64 DATA
-----END RSA PUBLIC KEY-----
有趣的是,如果您手动编辑文件以仅用RSA PUBLIC KEY
标记替换PUBLIC KEY
标记,那么您将获得经过验证的签名。这很奇怪,因为BASE64数据根据格式会有所不同,但是,我没有查看细节,以了解如果有任何罪魁祸首,所以不要问我为什么,但是会工作的。