Creating signature in Java with existing public key for JWT

时间:2016-10-20 12:36:49

标签: java jwt box-api signature box

I need your help once again...

I want to access the Box API and authorize using a JWT (Json Web Token). To do so, I need to create a Assertion:
"Every JWT assertion is composed of three components, the header, the claims, and the signature.
- The header specifies the algorithm used for the JWT signature.
- The claims contain the information necessary to authenticate and provide the correct token.
- The signature is used to verify the identify of the application and is verified using the public key.

Once encoded and concatenated, the JWT assertion will look like this: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9eyJpc3MiOiJ2Z3. B2bWFvaDJjZ2ZjNGRuMzFnMWx0cmlhbmdlZCIsInN1YiI. 6IjE2ODczOTQzIiwiZXhwIjoxNDI5MDM3ODYwLCJqdGkiOiJ"

So, an RSA Keypair I had to create before and had to deposit the public key in the Box devolper application.

Now, I don't know how to create the signature. I found a solution with creating the Keypair, but since I already have this, I don't know how to modify the code.

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));
  }
}

1 个答案:

答案 0 :(得分: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

预生成密钥对