Создание подписи в Java с существующим открытым ключом для JWT

#java #jwt #box-api #signature #box

#java #jwt #box-api #подпись #окно

Вопрос:

Мне снова нужна ваша помощь…

Я хочу получить доступ к Box API и авторизоваться с помощью JWT (веб-токен Json). Для этого мне нужно создать утверждение:
«Каждое утверждение 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));
  }
}
  

Комментарии:

1. Рассматривали ли вы возможность использования официального Java SDK для Box ? Он будет обрабатывать поток аутентификации JWT для вас. Если вы хотите написать это самостоятельно, вы можете проверить их реализацию JWT для вдохновения.

2. После того, как вы сгенерировали свою пару ключей, вам нужно как-то ее сохранить. Один PEM-файл для открытого ключа и один для закрытого ключа является распространенным способом его хранения. Однако, когда я попытался настроить код, подобный вашему, несколько недель назад, я в конечном итоге переключился с MD5 с RSA на HMAC-SHA256, потому что процесс чтения файла PEM в Java KeyPari был настолько утомительным и включал в себя так много библиотек!

Ответ №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