Нужен пример - расшифровка строки в Java с использованием Microsoft Crypto API
Прежде всего, я не программист на Java. Я ищу пример решения этой проблемы, потому что у меня есть Java-разработчик, который не имеет большого опыта работы с шифрованием. Все, что мы нашли в Интернете, относится к шифрованию веб-страниц и работе с хранилищем ключей MS. Мы просто хотим работать с одной строкой из PowerBuilder (PB) и иметь возможность расшифровывать ее на Java. Ограничение здесь - библиотека MS. Из-за определенных ограничений, мы застряли с использованием этого метода шифрования, так что именно сторона Java справляется с тем, что на него бросается.
У меня есть программа PB версии 10.2, которая должна вызвать эту утилиту Java и передать ей имя пользователя и пароль. Мы пытаемся зашифровать пароль как строку, дружественную к командной строке, так как именно так PB сделает вызов Java-приложения.
В PB я использую следующий объект: http://www.topwizprogramming.com/freecode_crypto.html
То, что делает код, - это обертка криптографического API Microsoft, найденного в advapi32.dll. Функции, которые он использует:
CryptAcquireContext http://msdn.microsoft.com/en-us/library/aa379886(VS.85).aspx
CryptCreateHash http://msdn.microsoft.com/en-us/library/aa379908(VS.85).aspx
CryptHashData http://msdn.microsoft.com/en-us/library/aa380202(VS.85).aspx
CryptDeriveKey http://msdn.microsoft.com/en-us/library/aa379916(VS.85).aspx
CryptEncrypt http://msdn.microsoft.com/en-us/library/aa379924(VS.85).aspx
Он использует Microsoft Strong Cryptographic Provider и PROV_RSA_FULL. Код принимает данные, которые должны быть зашифрованы, преобразует их в большой двоичный объект, который затем передается в функции шифрования. Там он получает контекст, создает хеш-объект из контекста, хеширует пароль, получает ключ сеанса из хэша, затем вызывает шифрование / дешифрование. И последнее, что он возвращает возвращенный BLOB и преобразует его в строку под набором символов ANSI.
Существует целый ряд констант, которые, на первый взгляд, я понимаю, откуда берутся некоторые, а другие - не очень: Константа String KEY_CONTAINER = "MyKeyContainer" Константа ULong PROV_RSA_FULL = 1 Константа ULong CALG_MD5 = 32771 Константа ULong CALG_RC4 = 26625 CYT Константа ULong = CALG_RYCLT = UT ULong CRYPT_NEWKEYSET = 8 Константа ULong ERROR_MORE_DATA = 234
Независимо от того, делается ли это в 1.5 с использованием чего-то вроде BouncyCastle или 1.6 с крипто-интерфейсом Sun для MS, мне все равно, мы просто жаждем увидеть эту работу и честно над головой.
Эй, мне нужно зашифровать строку и сохранить ее в файле, а затем мне нужно снова прочитать файл и расшифровать ту же строку обратно. Но я не хочу шифровать весь файл. Как только я получил требуемое зашифрованное значение, сохраненное в файле, мне нужно преобразовать это одно в исходную строку. Можете ли вы помочь мне с примером кода.
1 ответ
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class Decrypt
{
public static void main(String... argv)
throws Exception
{
byte[] password = "password".getBytes("UTF-8");
byte[] ciphertext = { -68, -112, 66, 78, 85, 50, 22, -63,
16, 24, -45, 4, -116, -14, 88, 34,
-85, 116, 105, 59, 45, -126 };
byte[] plaintext = decrypt(password, ciphertext);
System.out.println(new String(plaintext, "UTF-8"));
}
public static byte[] decrypt(byte[] password, byte[] ciphertext)
throws GeneralSecurityException
{
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] hash = digest.digest(password);
Cipher rc4 = Cipher.getInstance("RC4");
rc4.init(Cipher.DECRYPT_MODE, new SecretKeySpec(hash, "RC4"));
return rc4.doFinal(ciphertext);
}
}
NB:
Это "шифрование" ужасно. RC4 - это ключевой потоковый шифр. Никогда не используйте один и тот же ключ шифрования потока ключей для более чем одного сообщения! Использование одного и того же пароля для нескольких сообщений упрощает восстановление простого текста и ключа с использованием нескольких зашифрованных текстов. Учитывая слабость MD5, они, вероятно, тоже могут восстановить пароль. Этих недостатков достаточно, чтобы поставить под угрозу хороший потоковый шифр, но RC4, как и MD5, имеет свои собственные уязвимости и не рекомендуется для новых приложений.
Я уверен, что вы все это знали и ограничены каким-то устаревшим приложением, но если другие люди видят этот ответ, им нужно понимать, что "крипто" библиотека PowerBuilder, которую вы вынуждены использовать, некомпетентно реализована.
Поскольку ввод и вывод шифра всегда "двоичный", обычно используется кодировка текста, например Base-64 или Base-85, когда зашифрованный текст должен проходить через тексто-ориентированный канал (например, командную строку). Если возможно, можете ли вы Base-64 кодировать зашифрованный текст перед вызовом утилиты Java? Это защитит вас от любых проблем с кодировкой символов.