Как передать строку AES, зашифрованную через заголовок HTTP, используя javax.crypto - PullRequest
0 голосов
/ 10 мая 2018

В одном из наших внутренних программных продуктов мы внедряем новую конечную точку API, к которой внешние источники должны получать доступ через Интернет, а затем она должна быть каким-то образом защищена.

Так как нам не разрешено использовать библиотеку в качестве OAuth или открытых и закрытых ключей, мы выбрали javax.crypto AES, чтобы таким образом отобрать «токен авторизации» в каждом внешнем источнике:

...
Key aesKey = new SecretKeySpec("API-KEY".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] applicationIdEncrypted = cipher.doFinal(applicationId.getBytes());
...

token содержит пользовательский applicationId для идентификации на другой стороне, кто связывается с этой конечной точкой.

Поскольку мы должны выполнить HTTP-вызов, мы конвертируем applicationIdEncrypted в строку base64

String base64Encoded = Base64.getEncoder().encodeToString(applicationIdEncrypted);

НА ДРУГОЙ СТОРОНЕ

Мы получаем заголовок и декодируем его из base64

String base64Decoded = new String(Base64.getDecoder().decode(header));

Но при попытке выполнить последнюю операцию

Key aesKey = new SecretKeySpec("API-KEY".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, aesKey);

String headerDecoded = new String(cipher.doFinal(base64Decoded.getBytes())); //<- THIS

Мы получили javax.crypto.BadPaddingException: Given final block not properly padded

Оба base64Encoded и base64Decoded имеют одинаковое значение на обоих концах.

Попытка выполнить одну и ту же операцию в одном из концов (чтобы не использовать канал HTTP) не выдается никаких исключений -но, но new String(cipher.doFinal(base64Decoded.getBytes()));

возвращает другое headerDecoded

Искал байты applicationIdEncrypted и base64Decoded.getBytes(), и они немного отличаются:

applicationIdEncrypted

[-28, -103, 107, 70, -112, 121, 4, -14, -80, -114, -14, 92, -81, -13, -128, 97]

base64Decoded.getBytes ()

[-28, -103, 107, 70,   63, 121, 4, -14, -80, -114, -14, 92, -81, -13, -128, 97]

Я читал, что, возможно, переход от байтов к String может быть потерей информации (возможно?), Но я не могу понять, почему такого поведения, так как base64Encoded и base64Decoded имеют то же значение в обоих случаях и сценариях .

Как я могу добиться передачи "пользовательского токена авторизации", используя только библиотеки Java 1.7 javax.crypto?

EDIT

"API-KEY" - это что-то вроде 02E30E6BE24BF1EA

1 Ответ

0 голосов
/ 10 мая 2018

Как говорит @James K Polk, у меня была неразбериха с тысячами String конверсий, поэтому мне удалось сначала получить более чистый код для более полного кода.

НА КЛИЕНТЕ

Key aesKey = new SecretKeySpec("API-KEY".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, aesKey);

byte[] applicationIdEncrypted = cipher.doFinal(applicationId.getBytes());
byte[] base64Encoded = Base64.getEncoder().encode(applicationIdEncrypted);

String out = new String(base64Encoded);

, где out - единственное преобразование в String, и это полезная нагрузка заголовка HTTP.

НА ДРУГОЙ СТОРОНЕ

byte[] in = out.getBytes();
byte[] base64Decoded = Base64.getDecoder().decode(in);

Key aesKey = new SecretKeySpec("API-KEY".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, aesKey);
byte[] applicationIdDecrypted = cipher.doFinal(base64Decoded);

String applicationId= new String(applicationIdDecrypted);

У меня было ТОЛЬКО два преобразования в String: out (значение base64 заголовка) и applicationId.

Таким образом, у меня было то же значение applicationId.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...