Нужен пример - расшифровка строки в Java с использованием Microsoft Crypto API - PullRequest
0 голосов
/ 18 марта 2009

Прежде всего, я не программист на 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 и PROV_RSA_FULL. Код принимает данные, которые должны быть зашифрованы, преобразует их в большой двоичный объект, который затем передается в функции шифрования. Там он получает контекст, создает хеш-объект из контекста, хеширует пароль, получает ключ сеанса из хэша, а затем вызывает шифрование / дешифрование. И наконец, он возвращает возвращенный большой двоичный объект и преобразует его в строку с набором символов ANSI.

Существует целый ряд констант, которые, на первый взгляд, я понимаю, откуда одни берутся, а другие не так много: Константа String KEY_CONTAINER = "MyKeyContainer" Константа ULong PROV_RSA_FULL = 1 Константа ULong CALG_MD5 = 32771 Константа ULong CALG_RC4 = 26625 Константа ULong ENCRYPT_ALGORITHM = CALG_RC4 Константа ULong CRYPT_NEWKEYSET = 8 Константа ULong ERROR_MORE_DATA = 234

Независимо от того, делается ли это в версии 1.5 с использованием чего-то вроде BouncyCastle или 1.6 с криптоинтерфейсом Sun для MS, мне все равно, мы просто жаждем увидеть эту работу и честно над головой.


Эй, мне нужно зашифровать строку и сохранить ее в файле, а затем мне нужно снова прочитать файл и расшифровать ту же строку обратно. Но я не хочу шифровать весь файл. Как только я получил требуемое зашифрованное значение, сохраненное в файле, мне нужно преобразовать это одно в исходную строку. Не могли бы вы помочь мне с примером кода.

1 Ответ

4 голосов
/ 18 марта 2009
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);
  }

}

N.B:.

Это "шифрование" ужасно. RC4 - это ключевой потоковый шифр. Никогда не используйте один и тот же ключ шифрования потока ключей для более чем одного сообщения! Использование одного и того же пароля для нескольких сообщений упрощает восстановление простого текста и ключа с учетом нескольких зашифрованных текстов. Учитывая слабость MD5, они, вероятно, тоже могут восстановить пароль. Этих недостатков достаточно, чтобы поставить под угрозу хороший потоковый шифр, но RC4, как и MD5, имеет свои собственные уязвимости и не рекомендуется для новых приложений.

Я уверен, что вы все это знали и ограничены каким-либо устаревшим приложением, но если другие люди увидят этот ответ, им нужно понять, что крипто-библиотека PowerBuilder, которую вы вынуждены использовать, некомпетентно реализована. 1010 *


Поскольку ввод и вывод шифра всегда "двоичный", обычно используется кодировка текста, например Base-64 или Base-85, когда зашифрованный текст должен проходить через тексто-ориентированный канал (например, командную строку). Если возможно, можете ли вы Base-64 кодировать зашифрованный текст перед вызовом утилиты Java? Это защитит вас от любых проблем с кодировкой символов.

...