【问题标题】:Creating signature in Java with existing public key for JWT使用 JWT 的现有公钥在 Java 中创建签名
【发布时间】:2017-03-02 11:14:36
【问题描述】:

我再次需要你的帮助...

我想访问 Box API 并使用 JWT(Json Web 令牌)进行授权。为此,我需要创建一个断言:
“每个 JWT 断言都由三个组件组成,即标头、声明和签名。
- 标头指定用于 JWT 签名的算法。
- 声明包含验证和提供正确令牌所需的信息。
- 签名用于验证应用程序的身份,并使用公钥进行验证。

编码和连接后,JWT 断言将如下所示: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9eyJpc3MiOiJ2Z3。 B2bWFvaDJjZ2ZjNGRuMzFnMWx0cmlhbmdlZCIsInN1YiI。 6IjE2ODczOTQzIiwiZXhwIjoxNDI5MDM3ODYwLCJqdGkiOiJ"

因此,我之前必须创建一个 RSA 密钥对,并且必须将公钥存放在 Box devolper 应用程序中。

现在,我不知道如何创建签名。 我找到了创建密钥对的解决方案,但由于我已经有了这个,我不知道如何修改代码。

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;

import sun.misc.BASE64Encoder;

public class MainClass {
  public static void main(String[] args) throws Exception {
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    kpg.initialize(1024);
    KeyPair keyPair = kpg.genKeyPair();

    byte[] data = "test".getBytes("UTF8");

    Signature sig = Signature.getInstance("MD5WithRSA");
    sig.initSign(keyPair.getPrivate());
    sig.update(data);
    byte[] signatureBytes = sig.sign();
    System.out.println("Singature:" + new  
           BASE64Encoder().encode(signatureBytes));

    sig.initVerify(keyPair.getPublic());
    sig.update(data);

    System.out.println(sig.verify(signatureBytes));
  }
}

【问题讨论】:

  • 你考虑过使用官方Java SDK for Box吗?它将为您处理 JWT 身份验证流程。如果您想自己编写,可以查看他们的JWT implementation 以获得灵感。
  • 生成密钥对后,需要以某种方式存储它。一个用于公钥的 PEM 文件和一个用于私钥的 PEM 文件是一种常用的存储方式。但是,当我几周前尝试设置与您类似的代码时,我最终从带有 RSA 的 MD5 切换到了 HMAC-SHA256,因为将 PEM 文件读取到 Java KeyPari 的过程非常繁琐,并且包含了很多库!

标签: java jwt box-api signature box


【解决方案1】:

Box Api 说

RSA 密钥对必须是 PEM 格式

因此,您需要将公钥导出到 PEM。使用此代码(java8)

 public static String exportPublicKeyAsPem(PublicKey publicKey) throws Exception {
    StringWriter sw = new StringWriter();

    sw.write("-----BEGIN PUBLIC KEY-----\n");
    sw.write(Base64.getEncoder().encodeToString(publicKey.getEncoded()));
    sw.write("\n-----END PUBLIC KEY-----\n");

    return sw.toString();
 }

可以通过这种方式创建签名的 JWT 令牌(您也可以使用库)

public static String signJWT (String header, String payload, PrivateKey privateKey) throws Exception{
    String token = 
            Base64.getUrlEncoder().encodeToString(header.getBytes())
            + "."
            +Base64.getUrlEncoder().encodeToString(payload.getBytes());

    Signature sig = Signature.getInstance("SHA256WithRSA");
    sig.initSign(privateKey);
    sig.update(token.getBytes());
    byte[] signature = sig.sign();

    return token + "." + Base64.getUrlEncoder().encodeToString(signature);
}

使用代码:

public final static void main(String argv[]) throws Exception{

    String header = "{\"alg\": \"RS256\",\"typ\": \"JWT\"}";
    String payload = "{\"sub\": \"1234567890\",\"name\": \"John Doe\"}";

    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    kpg.initialize(1024);
    KeyPair keyPair = kpg.genKeyPair();

    String publicKeyPem = exportPublicKeyAsPem(keyPair.getPublic());
    String signedToken = signJWT (header, payload, keyPair.getPrivate());

    System.out.println(publicKeyPem);
    System.out.println(signedToken);
}

最后,您需要存储密钥对并在使用前加载。我建议您使用 openssl 作为BoxApi documentation says 预生成密钥对

【讨论】:

    猜你喜欢
    • 2018-05-22
    • 2022-08-06
    • 2016-04-17
    • 2018-01-06
    • 2017-11-22
    • 2016-10-09
    • 1970-01-01
    • 2018-11-14
    • 2021-01-05
    相关资源
    最近更新 更多