2011-01-04 2 views
4

Я изучаю разработку приложения на Java для операционной системы мобильных платформ.Шифрование и дешифрование строки с использованием Java equilavent C# CryptoStream

Я разработал приложение в C# WPF для среды Windows. Я использую криптопоток для шифрования и дешифрования строки, используя следующий код. приведенный ниже код - только шифрование

public string encrypt(string encryptionString) 
    { 
     byte[] clearTextBytes = Encoding.UTF8.GetBytes(encryptionString); 

     SymmetricAlgorithm rijn = SymmetricAlgorithm.Create(); 

     MemoryStream ms = new MemoryStream(); 
     byte[] rgbIV = Encoding.ASCII.GetBytes("ryojvlzmdalyglrj"); 
     byte[] key = Encoding.ASCII.GetBytes("hcxilkqbbhczfeultgbskdmaunivmfuo"); 
     CryptoStream cs = new CryptoStream(ms, rijn.CreateEncryptor(key, rgbIV), CryptoStreamMode.Write); 

     cs.Write(clearTextBytes, 0, clearTextBytes.Length); 

     cs.Close(); 

     return Convert.ToBase64String(ms.ToArray()); 
    } 

Зашифрованная строка хранится в онлайн-базе данных. Мне нужно, чтобы приложение java могло читать строку из базы данных и расшифровывать строку, используя те же ключи шифрования из приложения C#.

Благодарим за помощь.

+0

Какого алгоритма делает это использование? Режим? Перетяжка? Вам нужно будет знать эти вещи, чтобы расшифровать. – erickson

+0

Duplicate: http://stackoverflow.com/questions/4489942/equivalent-to-cryptostream-net-in-java –

+0

Я не рассматриваю это как дубликат, поскольку вышеупомянутый вопрос охватывает Visual Basic, где, когда я использую C# , однако может быть аналогичным, он отличается – Boardy

ответ

2

Возможно, вы захотите проверить javax.crypto.CipherInputStream и javax.crypto.CipherOutputStream.

http://download.oracle.com/javase/1.5.0/docs/api/javax/crypto/CipherInputStream.html http://download.oracle.com/javase/1.5.0/docs/api/javax/crypto/CipherOutputStream.html

Они используются почти точно так же, как ваш образец выше, хотя инициализация объектов Cipher может несколько отличаться.

+0

Один из них с этими классами состоит в том, что любые исключения, вызванные основным экземпляром Cipher, молчаливо проглатываются. В частности, «BadPaddingException», который очень полезен, позволяя вам знать, что у вас есть ошибка (или плохая клавиша), исчезает в Neverland. –

6

Лично мне нравится BouncyCastle для Java crypto. Этот код (используя легкий API BouncyCastle) следует сделать трюк:

String decrypt(byte[] cryptoBytes, byte[] key, byte[] iv) { 
    BlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine())); 
    cipher.init(false, new ParametersWithIV(new KeyParameter(key), iv)); 
    byte[] out = new byte[cipher.getOutputSize(cryptoBytes.length)]; 
    int offset = cipher.processBytes(cryptoBytes, 0, cryptoBytes.length, out, 0); 
    cipher.doFinal(out, offset); 
    return new String(out); 
} 

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

Похоже, что и .net SymmetricAlgorithm и BC PaddedBufferedBlockCipher по умолчанию для заполнения PKCS7, поэтому вы должны быть в порядке с использованием значений по умолчанию.

0

Я использую следующие для шифрования между .net и Java

В .net я использую:

/// <summary> 
    /// DES Encryption method - used to encryp password for the java. 
    /// </summary> 
    /// <param name="plainText"></param> 
    /// <returns></returns> 
    public string EncryptData(string plainText) 
    { 
     DES des = new DESCryptoServiceProvider(); 
     des.Mode = CipherMode.ECB; 
     des.Padding = PaddingMode.PKCS7; 

     des.Key = Encoding.UTF8.GetBytes(_secretPhrase.Substring(0, 8)); 
     des.IV = Encoding.UTF8.GetBytes(_secretPhrase.Substring(0, 8)); 

     byte[] bytes = Encoding.UTF8.GetBytes(plainText); 
     byte[] resultBytes = des.CreateEncryptor().TransformFinalBlock(bytes, 0, bytes.Length); 

     return Convert.ToBase64String(resultBytes); 
    } 

    /// <summary> 
    /// DES Decryption method - used the decrypt password encrypted in java 
    /// </summary> 
    /// <param name="encryptedText"></param> 
    /// <returns></returns> 
    public string DecryptData(string encryptedText) 
    { 
     DES des = new DESCryptoServiceProvider(); 
     des.Mode = CipherMode.ECB; 
     des.Padding = PaddingMode.PKCS7; 
     des.Key = Encoding.UTF8.GetBytes(_secretPhrase.Substring(0, 8)); 
     des.IV = System.Text.Encoding.UTF8.GetBytes(_secretPhrase.Substring(0, 8)); 

     byte[] bytes = Convert.FromBase64String(encryptedText); 
     byte[] resultBytes = des.CreateDecryptor().TransformFinalBlock(bytes, 0, bytes.Length); 

     return Encoding.UTF8.GetString(resultBytes); 
    } 

и в Java я использую:

общественного класса CryptoUtil {

public static final Logger LOG = Logger.getLogger(CryptoUtil.class); 

private Cipher cipher = null; 

private SecretKey key = null; 

// This variable holds a string based on which a unique key will be generated 
private static final String SECRET_PHRASE = "SECRET PHRASE GOES HERE"; 

// Charset will be used to convert between String and ByteArray 
private static final String CHARSET = "UTF8"; 

// The algorithm to be used for encryption/decryption DES(Data Encryption Standard) 
private static final String ALGORITHM = "DES"; 

public CryptoUtil() throws DDICryptoException { 
    try { 
     // generate a key from SecretKeyFactory 
     DESKeySpec keySpec = new DESKeySpec(SECRET_PHRASE.getBytes(CHARSET)); 
     SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM); 
     key = keyFactory.generateSecret(keySpec); 
     cipher = Cipher.getInstance(ALGORITHM); 
    } catch (Exception e) { 
     LOG.error(e); 
     throw new DDICryptoException(e); 
    } 
} 


/** 
* This method takes a plain text string and returns encrypted string using DES algorithm 
* @param plainText 
* @return String 
* @throws DDICryptoException 
*/ 
public String encrypt(String plainText) throws DDICryptoException { 
    String encryptedString = null; 
    try { 
     // initializes the cipher with a key. 
     cipher.init(Cipher.ENCRYPT_MODE, key); 

     byte[] plainTextAsUTF8 = plainText.getBytes(CHARSET); 

     // decrypts data in a single-part or multi-part operation 
     byte[] encryptedBytes = cipher.doFinal(plainTextAsUTF8); 

     encryptedString = new sun.misc.BASE64Encoder().encode(encryptedBytes); 
    } catch (Exception e) { 
     LOG.error(e); 
     throw new DDICryptoException(e); 

    } 
    return encryptedString; 

} 

/** 
* This method takes a plain text string and returns encrypted string using DES algorithm 
* @param encryptedString 
* @return 
* @throws DDICryptoException 
*/ 
public String decrypt(String encryptedString) throws DDICryptoException {  
    String decryptedString = null; 
    try { 
     byte[] decodedString = new sun.misc.BASE64Decoder().decodeBuffer(encryptedString); 

     // initializes the cipher with a key. 
     cipher.init(Cipher.DECRYPT_MODE, key); 

     // decrypts data in a single-part or multi-part operation 
     byte[] decryptedBytes = cipher.doFinal(decodedString); 
     decryptedString = new String(decryptedBytes, CHARSET); 
    } catch (Exception e) { 
     LOG.error(e); 
     throw new DDICryptoException(e); 
    } 
    return decryptedString; 
} 

+0

DES и ECB * shudder * – Qwerky

+0

Вы должны действительно переосмыслить свой подход. Здесь есть куча проблем: 1) DES сломан. 2) ЕЦБ не использует IV. 3) Если вы используете режим CBC, тогда IV должен быть nonce, т. Е. Вновь созданным случайным числом для каждого сообщения. Вы не можете повторно использовать IV, иначе вы подвергаете свое сообщение атакам статистического анализа (среди прочих). 4) В Java ваш 'SECRET_PHRASE' является статическим финальным строком, что означает, что он будет интернирован, что немного небезопасно (хотя для этого требуется справедливая работа). –

0

У меня есть способ решить проблему. Расшифровка теперь отлично работает. Использование следующего кода

String plainPassword = ""; 
      try 
      { 
       SecretKeySpec key = new SecretKeySpec("hcxilkqbbhczfeultgbskdmaunivmfuo".getBytes("US-ASCII"), "AES"); 

       IvParameterSpec iv = new IvParameterSpec("ryojvlzmdalyglrj".getBytes("US_ASCII")); 

       Cipher cipher = Cipher.getInsta 

nce("AES/CBC/PKCS7Padding"); 

      cipher.init(Cipher.DECRYPT_MODE, key, iv); 

      byte[] encoded = cipher.doFinal(Base64.decodeBase64(encryptedPassword.getBytes())); 
      plainPassword = new String(encoded); 
     } 
     catch (Exception ex) 
     { 
      Log.d("Decryption Error", ex.toString()); 
     } 

     return plainPassword; 

Проблема теперь в шифровании. Я использовал тот же код, кроме того, что изменил шифр из режима дешифрования в режим шифрования, но по какой-то причине, когда я распечатываю зашифрованную строку, он просто печатает груз мусора, который не похож на строку, которую создает C#. Ниже приведен код для шифрования

public String encrypt(String plainPasword) 
    { 
     String password = ""; 
     try 
     { 
      SecretKeySpec key = new SecretKeySpec("hcxilkqbbhczfeultgbskdmaunivmfuo".getBytes("US-ASCII"), "AES"); 

      IvParameterSpec iv = new IvParameterSpec("ryojvlzmdalyglrj".getBytes("US_ASCII")); 

      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); 

      cipher.init(Cipher.ENCRYPT_MODE, key, iv); 

      byte[] encoded = cipher.doFinal(plainPasword.getBytes()); 
      password = new String(encoded); 


     } 
     catch (Exception ex) 
     { 
      Log.d("Encryption Error", ex.toString()); 
     } 
     return password; 
    } 

Что-то не так с этим, я не могу его обработать.Спасибо

+1

Это будет проблемой: 'password = new String (encoded);'. «Закодированная» переменная является массивом необработанных байтов и, вероятно, содержит байты, которые не соответствуют символам, например. нулевые байты. Ваш код дешифрования предполагает, что шифрованный текст кодируется base64, поэтому вам нужно добавить его на свой шаг шифрования. В Apache commons (http://commons.apache.org/codec/) есть библиотека для этого в Java. –

0
 StringBuffer strbuf = new StringBuffer(buf.length * 2); 
     int i; 

     for (i = 0; i < buf.length; i++) { 
      if (((int) buf[i] & 0xff) < 0x10) { 
       strbuf.append("0"); 
      } 

      strbuf.append(Long.toString((int) buf[i] & 0xff, 16)); 
     } 

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

public String encrypt(String data) throws Exception{ 
    try { 
     Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 
     Key k = new SecretKeySpec(key.getBytes(), 0, key.length(), "AES"); 

     // Calculate ciphertext size. 
     int blocksize = 16; 
     int ciphertextLength = 0; 
     int remainder = data.getBytes().length % blocksize; 
     if (remainder == 0) { 
      ciphertextLength = data.getBytes().length + blocksize; 
     } else { 
      ciphertextLength = data.getBytes().length - remainder + blocksize; 
     } 


     cipher.init(Cipher.ENCRYPT_MODE, k); 
     byte[] buf = new byte[ciphertextLength]; 
     cipher.doFinal(data.getBytes(), 0, data.length(), buf, 0); 

     StringBuffer strbuf = new StringBuffer(buf.length * 2); 
     int i; 

     for (i = 0; i < buf.length; i++) { 
      if (((int) buf[i] & 0xff) < 0x10) { 
       strbuf.append("0"); 
      } 

      strbuf.append(Long.toString((int) buf[i] & 0xff, 16)); 
     } 
     return strbuf.toString(); 
    } catch (Exception e) { 
     Logger.logException(e); 
    } 
    return null; 
} 
0

См Ответ # 5 на Equivalent to CryptoStream .NET in Java?

Обязательно прочитайте комментарии в нижней части ...

KeySpec ks = new DESKeySpec("key12345".getBytes("UTF-8")); SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(ks);
IvParameterSpec iv = new IvParameterSpec( Hex.decodeHex("1234567890ABCDEF".toCharArray()));
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] decoded = cipher.doFinal(Base64.decodeBase64("B3xogi/Qfsc="));
System.out.println("Decoded: " + new String(decoded, "UTF-8"));

Надеется, что это помогает ...
JK

-1

Cemeron, Удобный код!

я наткнулся на интересную ситуацию, когда наш клиент дал IV такой же, как ключа.

Перепробовав различные комбинации, где я получаю плохое исключение обивки, решение, которое работало было

byte[] iv=new byte[8]; // assuming RC2 
System.arraycopy(key.getBytes(), 0, iv, 0, key.getBytes().length > iv.length ? key.getBytes().length); 

// Now decrypt and hopefully this should work 
Смежные вопросы