2014-12-02 41 views
0

我一直在面對我的鍵盤滾動,試圖讓C#加密類(https://gist.github.com/jbtule/4336842#file-aesthenhmac-cs)到java中。Java實現UTF8消息(C#和Java(Android)兼容性)的認證(HMAC)然後解密(AES)

我遇到的問題是從c#加密的消息不會在Java中解密,反之亦然。

的Java類進行加密和解密就好了(不過我懷疑它實際上做它安全地基於它不是用C#工作)

這裏的地穴類:

package com.hexninja.datacrypt.crypt; 

import org.spongycastle.crypto.BufferedBlockCipher; 
import org.spongycastle.crypto.CipherParameters; 
import org.spongycastle.crypto.engines.RijndaelEngine; 
import org.spongycastle.crypto.io.CipherOutputStream; 
import org.spongycastle.crypto.modes.CBCBlockCipher; 
import org.spongycastle.crypto.paddings.BlockCipherPadding; 
import org.spongycastle.crypto.paddings.PKCS7Padding; 
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher; 
import org.spongycastle.crypto.params.KeyParameter; 
import org.spongycastle.crypto.params.ParametersWithIV; 
import org.spongycastle.util.encoders.Base64; 

import java.io.ByteArrayOutputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.io.UnsupportedEncodingException; 
import java.nio.charset.Charset; 
import java.security.GeneralSecurityException; 
import java.security.InvalidKeyException; 
import java.security.NoSuchAlgorithmException; 
import java.security.SecureRandom; 
import java.security.Security; 
import java.util.Random; 

import javax.crypto.Mac; 
import javax.crypto.SecretKey; 
import javax.crypto.spec.SecretKeySpec; 

/** 
* Created by David on 11/26/2014. 
*/ 
public final class Crypt { 

// -- SpongyCastle, i choose you! 
// -- ok, so a lame pokemon reference. 
// -- but seriously, use this provider! 
static { 
    Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider()); 
} 

private static final Random random = new Random(); 

//Preconfigured Encryption Parameters 
public static final int BlockBitSize = 256; 
public static final int KeyBitSize = 256; 

//Preconfigured Password Key Derivation Parameters 
public static final int SaltBitSize = 64; 
public static final int Iterations = 3; 
public static final int MinPasswordLength = 4; 

private static final Charset UTF8 = Charset.forName("UTF-8"); 

/// <summary> 
/// Simple Encryption (AES) then Authentication (HMAC) of a UTF8 message 
/// using Keys derived from a Password (PBKDF2). 
/// </summary> 
/// <param name="secretMessage">The secret message.</param> 
/// <param name="password">The password.</param> 
/// <param name="nonSecretPayload">The non secret payload.</param> 
/// <returns> 
/// Encrypted Message 
/// </returns> 
/// <exception cref="System.ArgumentException">password</exception> 
/// <remarks> 
/// Significantly less secure than using random binary keys. 
/// Adds additional non secret payload for key generation parameters. 
/// </remarks> 
public static String SimpleEncryptWithPassword(String secretMessage, String password, byte[] nonSecretPayload) 
{ 
    //if (String.IsNullOrEmpty(secretMessage)) 
    if (secretMessage.isEmpty() || secretMessage == null) { 
     throw new IllegalArgumentException("Secret Message Required!"); 
    } 

    //var plainText = Encoding.UTF8.GetBytes(secretMessage); 
    //var cipherText = SimpleEncryptWithPassword(plainText, password, nonSecretPayload); 
    //return Convert.ToBase64String(cipherText); 


    byte[] plainText = null; 
    byte[] cipherText = null; 
    //byte[] plainText = Encoding.UTF8.GetBytes(secretMessage); 
    try { 
     plainText = secretMessage.getBytes("UTF-8"); 
     cipherText = SimpleEncryptWithPassword(plainText, password, nonSecretPayload); 
     //return Convert.ToBase64String(cipherText); 
    } 
    catch (UnsupportedEncodingException e) { 
     e.printStackTrace(); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } 

    if (cipherText != null) { 
    //return Base64.encodeToString(cipherText, Base64.DEFAULT); 
    return Base64.toBase64String(cipherText); 
    //return new String(Base64.encodeBase64(cipherText), UTF8); 
} 
else 
    return null; 



} 

/// <summary> 
/// Simple Authentication (HMAC) and then Descryption (AES) of a UTF8 Message 
/// using keys derived from a password (PBKDF2). 
/// </summary> 
/// <param name="encryptedMessage">The encrypted message.</param> 
/// <param name="password">The password.</param> 
/// <param name="nonSecretPayloadLength">Length of the non secret payload.</param> 
/// <returns> 
/// Decrypted Message 
/// </returns> 
/// <exception cref="System.ArgumentException">Encrypted Message Required!;encryptedMessage</exception> 
/// <remarks> 
/// Significantly less secure than using random binary keys. 
/// </remarks> 
public static String SimpleDecryptWithPassword(String encryptedMessage, String password, int nonSecretPayloadLength) throws GeneralSecurityException, UnsupportedEncodingException { 
    //if (String.IsNullOrWhiteSpace(encryptedMessage)) 
    if (encryptedMessage.isEmpty() || encryptedMessage == null) { 
     throw new IllegalArgumentException("Encrypted Message Required!"); 
    } 

    byte[] cipherText = Base64.decode(encryptedMessage); 
    byte[] plainText = SimpleDecryptWithPassword(cipherText, password, nonSecretPayloadLength); 
    //String s = new String(plainText, "ISO-8859-1"); 
    //byte[] stream = s.getBytes("ISO-8859-1"); 

    return new String(plainText, "UTF8"); 
    //return Base64.toBase64String(plainText); 
    //return plainText.toString(); 
} 

public static byte[] SimpleEncrypt(byte[] secretMessage, byte[] cryptKey, byte[] authKey, byte[] nonSecretPayload) 
    { 
     //User Error Checks 
     if (cryptKey == null || cryptKey.length != KeyBitSize/8) 
      throw new IllegalArgumentException("Key needs to be " + KeyBitSize + " bit!"); 

     if (authKey == null || authKey.length != KeyBitSize/8) 
      throw new IllegalArgumentException("Key needs to be " + KeyBitSize + " bit!"); 

     if (secretMessage == null || secretMessage.length < 1) 
      throw new IllegalArgumentException("Secret Message Required!"); 

     //non-secret payload optional 
     //nonSecretPayload = nonSecretPayload ?? new byte[] { }; 
     if (nonSecretPayload == null) { 
      nonSecretPayload = new byte[] { }; 
     } 

     byte[] cipherText = null; 
     //byte[] iv = null; 

     System.out.println("SimpleEncrypt stage 1"); 

    try { 

     System.out.println("SimpleEncrypt stage 2"); 

     //Grab IV from message 
     byte[] ivData = new byte[BlockBitSize/8]; 
     Random r = new Random(); // Note: no seed here, ie these values are truly random 
     r.nextBytes(ivData); 

     // Select encryption algorithm and padding : AES with CBC and PCKS#7 
     CipherParameters params = new ParametersWithIV(new KeyParameter(cryptKey), ivData); 
     BlockCipherPadding padding = new PKCS7Padding(); 
     BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new RijndaelEngine(256)), padding); 

     cipher.reset(); 
     cipher.init(true, params); // first param = encode/decode 

     // -- a wannabe using statement.. 
     // -- c# like memorystream 
     try (ByteArrayOutputStream cipherStream = new ByteArrayOutputStream()) { 
      // -- c# like CryptoStream 
      try (CipherOutputStream cryptoStream = new CipherOutputStream(cipherStream, cipher)) { 
       // -- binaryWriter like c# 
       try (DataOutputStream binaryWriter = new DataOutputStream(cryptoStream)) { 
        // -- Encrypt Data 
        binaryWriter.write(secretMessage); 
       } 
       cipherText = cipherStream.toByteArray(); 
      } 


     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     System.out.println("SimpleEncrypt stage 3"); 

     //Assemble encrypted message and add authentication 
     try { 
      System.out.println("SimpleEncrypt stage 4"); 
      Mac hmac = Mac.getInstance("HmacSHA256"); 
      System.out.println("authKey =" + Base64.toBase64String(authKey)); 
      SecretKey signingKey = new SecretKeySpec(authKey, "HMACSHA256"); 
      System.out.println("authKey=" + Base64.toBase64String(authKey)); 
      hmac.init(signingKey); 
      try (ByteArrayOutputStream encryptedStream = new ByteArrayOutputStream()) { 
       try (DataOutputStream binaryWriter = new DataOutputStream(encryptedStream)) { 
        //Prepend non-secret payload if any 
        binaryWriter.write(nonSecretPayload); 
        //Prepend IV 
        binaryWriter.write(ivData); 
        //Write Ciphertext 
        binaryWriter.write(cipherText); 
        binaryWriter.flush(); 


        System.out.println("computeByte=" + Base64.toBase64String(encryptedStream.toByteArray())); 

        //Authenticate all data 
        //var tag = hmac.ComputeHash(encryptedStream.ToArray()); 
        //hmac.init(secretKeySpecy); 
        byte[] tag = hmac.doFinal(encryptedStream.toByteArray()); 
        //System.out.println("tag text=" + tag.length); 
        System.out.println("tag=" + Base64.toBase64String(tag)); 
        //Postpend tag 
        binaryWriter.write(tag); 
       } 
       return encryptedStream.toByteArray(); 
      } 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } 


    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } catch (InvalidKeyException e) { 
     e.printStackTrace(); 
    } 

    return null; 


} 

public static byte[] SimpleDecrypt(byte[] encryptedMessage, byte[] cryptKey, byte[] authKey, int nonSecretPayloadLength) 
{ 

    //Basic Usage Error Checks 
    if (cryptKey == null || cryptKey.length != KeyBitSize/8) 
     throw new IllegalArgumentException("CryptKey needs to be " + KeyBitSize + " bit!"); 

    if (authKey == null || authKey.length != KeyBitSize/8) 
     throw new IllegalArgumentException("AuthKey needs to be " + KeyBitSize + " bit!"); 

    if (encryptedMessage == null || encryptedMessage.length == 0) 
     throw new IllegalArgumentException("Encrypted Message Required!"); 


    try { 
     // verify HMAC! 
     Mac hmac = Mac.getInstance("HmacSHA256"); 
     SecretKey signingKey = new SecretKeySpec(authKey, "HMACSHA256"); 
     hmac.init(signingKey); 

     System.out.println("authKey=" + Base64.toBase64String(authKey)); 


     // -- hmac is already 32 bytes.. I was expecting bits. (c# does bits) 
     //byte[] sentTag = new byte[sha256_HMAC.getMacLength()/8]; 
     byte[] sentTag = new byte[hmac.getMacLength()]; 




     byte[] computeByte = new byte[encryptedMessage.length - sentTag.length]; 
     System.arraycopy(encryptedMessage, 0, computeByte, 0, computeByte.length); 

     System.out.println("computeByte=" + Base64.toBase64String(computeByte)); 

     // -- fix for missing ComputeHash from c# 
     //MessageDigest m = MessageDigest.getInstance("HMACSHA256"); 
     //byte[] digest = m.digest(computeByte); 
     //String hashcode = new BigInteger(1,m.digest()).toString(16); 

     //System.out.println("hashcode=" + hashcode); 


     byte[] calcTag = hmac.doFinal(computeByte); 
     int ivLength = (BlockBitSize/8); 

     System.out.println("calcTag=" + Base64.toBase64String(calcTag)); 

     //if message length is to small just return null 
     if (encryptedMessage.length < sentTag.length + nonSecretPayloadLength + ivLength) 
      return null; 

     System.out.println("we are past encrypted Message length"); 

     //Grab Sent Tag 
     System.arraycopy(encryptedMessage, encryptedMessage.length - sentTag.length, sentTag, 0, sentTag.length); 


     System.out.println("sentTag=" + Base64.toBase64String(sentTag)); 

     //Compare Tag with constant time comparison 
     int compare = 0; 
     for (int i = 0; i < sentTag.length; i++) 
      compare |= sentTag[i]^calcTag[i]; 

     System.out.println("compare =" + compare); 

     //if message doesn't authenticate return null 
     if (compare != 0) 
      return null; 



     //Grab IV from message 
     byte[] iv = new byte[ivLength]; 
     System.arraycopy(encryptedMessage, nonSecretPayloadLength, iv, 0, iv.length); 

     System.out.println("iv=" + Base64.toBase64String(iv)); 

     //iv = ivSpec.getIV(); 
     CipherParameters params = new ParametersWithIV(new KeyParameter(cryptKey), iv); 
     BlockCipherPadding padding = new PKCS7Padding(); 
     BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new RijndaelEngine(256)), padding); 

     cipher.reset(); 
     cipher.init(false, params); 

     try (ByteArrayOutputStream plainTextStream = new ByteArrayOutputStream()) { 
      // -- c# like CryptoStream 
      try (CipherOutputStream decrypterStream = new CipherOutputStream(plainTextStream, cipher)) { 
       // -- binaryWriter like c# 
       try (DataOutputStream binaryWriter = new DataOutputStream(decrypterStream)) { 
        // -- Encrypt Data 
        //Decrypt Cipher Text from Message 
        binaryWriter.write(
          encryptedMessage, 
          nonSecretPayloadLength + iv.length, 
          encryptedMessage.length - nonSecretPayloadLength - iv.length - sentTag.length 
        ); 
       } 
       //Return Plain Text 
       //decrypterStream.flush(); 

      } finally { 
       return plainTextStream.toByteArray(); 
      } 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } catch (InvalidKeyException e) { 
     e.printStackTrace(); 
    } 

    return null; 
} 

public static byte[] SimpleEncryptWithPassword(byte[] secretMessage, String password, byte[] nonSecretPayload) throws NoSuchAlgorithmException { 
    if (nonSecretPayload == null) { 
     nonSecretPayload = new byte[] { }; 
    } 

    //User Error Checks 
    if (password.isEmpty() || password == null || password.length() < MinPasswordLength) { 
     throw new IllegalArgumentException("Must have a password of at least "+MinPasswordLength+" characters!"); 
    } 

    if (secretMessage == null || secretMessage.length == 0) 
     throw new IllegalArgumentException("Secret Message Required!"); 

    byte[] payload = new byte[((SaltBitSize/8) * 2) + nonSecretPayload.length]; 

    System.arraycopy(nonSecretPayload, 0, payload, 0, nonSecretPayload.length); 
    //Array.Copy(nonSecretPayload, payload, nonSecretPayload.Length); 
    int payloadIndex = nonSecretPayload.length; 

    byte[] cryptKey = null; 
    byte[] authKey = null; 

    try { 

     Random r = new SecureRandom(); 
     byte[] salt = new byte[SaltBitSize/8]; 
     r.nextBytes(salt); 


     Rfc2898DeriveBytes generator = new Rfc2898DeriveBytes(password, salt, Iterations); 
     //Generate Keys 
     cryptKey = generator.getBytes(KeyBitSize/8); 

     //Create Non Secret Payload 
     System.arraycopy(salt, 0, payload, payloadIndex, salt.length); 
     //System.arraycopy(nonSecretPayload, 0, payload, 0, nonSecretPayload.length); 
     payloadIndex += salt.length; 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } catch (InvalidKeyException e) { 
     e.printStackTrace(); 
    } catch (UnsupportedEncodingException e) { 
     e.printStackTrace(); 
    } 


    try { 
     Random r = new SecureRandom(); 
     byte[] salt = new byte[SaltBitSize/8]; 
     r.nextBytes(salt); 

     Rfc2898DeriveBytes generator = new Rfc2898DeriveBytes(password, salt, Iterations); 
     //Generate Keys 
     authKey = generator.getBytes(KeyBitSize/8); 

     //Create Non Secret Payload 
     System.arraycopy(salt, 0, payload, payloadIndex, salt.length); 
     //System.arraycopy(nonSecretPayload, 0, payload, 0, nonSecretPayload.length); 
     payloadIndex += salt.length; 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } catch (InvalidKeyException e) { 
     e.printStackTrace(); 
    } catch (UnsupportedEncodingException e) { 
     e.printStackTrace(); 
    } 

    System.out.println("cryptKey=" + Base64.toBase64String(cryptKey)); 
    System.out.println("authKey=" + Base64.toBase64String(authKey)); 

    return SimpleEncrypt(secretMessage, cryptKey, authKey, payload); 
} 

public static byte[] SimpleDecryptWithPassword(byte[] encryptedMessage, String password, int nonSecretPayloadLength) throws GeneralSecurityException { 
    //User Error Checks 
    if (password.isEmpty() || password == null || password.length() < MinPasswordLength) { 
     throw new IllegalArgumentException("Must have a password of at least "+MinPasswordLength+" characters!"); 
    } 

    if (encryptedMessage == null || encryptedMessage.length == 0) 
     throw new IllegalArgumentException("Encrypted Message Required!"); 

    byte[] cryptSalt = new byte[SaltBitSize/8]; 
    byte[] authSalt = new byte[SaltBitSize/8]; 

    //Grab Salt from Non-Secret Payload 
    System.arraycopy(encryptedMessage, nonSecretPayloadLength, cryptSalt, 0, cryptSalt.length); 
    System.arraycopy(encryptedMessage, nonSecretPayloadLength + cryptSalt.length, authSalt, 0, authSalt.length); 

    System.out.println("cryptSalt=" + Base64.toBase64String(cryptSalt)); 
    System.out.println("authSalt=" + Base64.toBase64String(authSalt)); 


    Rfc2898DeriveBytes generator = null; 
    try { 
     generator = new Rfc2898DeriveBytes(password, cryptSalt, Iterations); 
    } catch (UnsupportedEncodingException e) { 
     e.printStackTrace(); 
    } 
    byte[] cryptKey = generator.getBytes(KeyBitSize/8); 

    try { 
     generator = new Rfc2898DeriveBytes(password, authSalt, Iterations); 
    } catch (UnsupportedEncodingException e) { 
     e.printStackTrace(); 
    } 
    byte[] authKey = generator.getBytes(KeyBitSize/8); 

    //byte[] cryptKey = Rfc2898DeriveBytes(password, cryptSalt, Iterations); 
    //byte[] authKey = Rfc2898DeriveBytes(password, authSalt, Iterations); 

    System.out.println("cryptKey=" + Base64.toBase64String(cryptKey)); 
    System.out.println("authKey=" + Base64.toBase64String(authKey)); 

    return SimpleDecrypt(encryptedMessage, cryptKey, authKey, cryptSalt.length + authSalt.length + nonSecretPayloadLength); 
} 

/* 
private static byte[] Rfc2898DeriveBytes(String password, byte[] salt, int iterations) throws GeneralSecurityException { 

    // get raw key from password and salt 
    PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), salt, Iterations, SaltBitSize); 
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithSHA256And256BitAES-CBC-BC"); 
    SecretKeySpec secretKey = new SecretKeySpec(keyFactory.generateSecret(pbeKeySpec).getEncoded(), "HMACSHA256"); 
    byte[] rawKeyData = secretKey.getEncoded(); 

    return rawKeyData; 
} 
*/ 

} 

我知道其相當大的..這裏是Rfc2898DeriveBytes類

package com.hexninja.datacrypt.crypt; 

/** 
* Created by David on 12/2/2014. 
*/ 
import java.io.UnsupportedEncodingException; 
import java.security.InvalidKeyException; 
import java.security.NoSuchAlgorithmException; 
import javax.crypto.Mac; 
import javax.crypto.spec.SecretKeySpec; 

/** 
* RFC 2898 password derivation compatible with .NET Rfc2898DeriveBytes class. 
*/ 
public class Rfc2898DeriveBytes { 

private Mac _hmacSha1; 
private byte[] _salt; 
private int _iterationCount; 

private byte[] _buffer = new byte[20]; 
private int _bufferStartIndex = 0; 
private int _bufferEndIndex = 0; 
private int _block = 1; 


/** 
* Creates new instance. 
* @param password The password used to derive the key. 
* @param salt The key salt used to derive the key. 
* @param iterations The number of iterations for the operation. 
* @throws NoSuchAlgorithmException HmacSHA1 algorithm cannot be found. 
* @throws InvalidKeyException Salt must be 8 bytes or more. -or- Password cannot be null. 
*/ 
public Rfc2898DeriveBytes(byte[] password, byte[] salt, int iterations) throws NoSuchAlgorithmException, InvalidKeyException { 
    if ((salt == null) || (salt.length < 8)) { throw new InvalidKeyException("Salt must be 8 bytes or more."); } 
    if (password == null) { throw new InvalidKeyException("Password cannot be null."); } 
    this._salt = salt; 
    this._iterationCount = iterations; 
    this._hmacSha1 = Mac.getInstance("HMACSHA256"); 
    this._hmacSha1.init(new SecretKeySpec(password, "HMACSHA256")); 
} 

/** 
* Creates new instance. 
* @param password The password used to derive the key. 
* @param salt The key salt used to derive the key. 
* @param iterations The number of iterations for the operation. 
* @throws NoSuchAlgorithmException HmacSHA1 algorithm cannot be found. 
* @throws InvalidKeyException Salt must be 8 bytes or more. -or- Password cannot be null. 
* @throws UnsupportedEncodingException UTF-8 encoding is not supported. 
*/ 
public Rfc2898DeriveBytes(String password, byte[] salt, int iterations) throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException { 
    this(password.getBytes("UTF8"), salt, iterations); 
} 

/** 
* Creates new instance. 
* @param password The password used to derive the key. 
* @param salt The key salt used to derive the key. 
* @throws NoSuchAlgorithmException HmacSHA1 algorithm cannot be found. 
* @throws InvalidKeyException Salt must be 8 bytes or more. -or- Password cannot be null. 
* @throws UnsupportedEncodingException UTF-8 encoding is not supported. 
*/ 
public Rfc2898DeriveBytes(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException { 
    this(password, salt, 0x3e8); 
} 


/** 
* Returns a pseudo-random key from a password, salt and iteration count. 
* @param count Number of bytes to return. 
* @return Byte array. 
*/ 
public byte[] getBytes(int count) { 
    byte[] result = new byte[count]; 
    int resultOffset = 0; 
    int bufferCount = this._bufferEndIndex - this._bufferStartIndex; 

    if (bufferCount > 0) { //if there is some data in buffer 
     if (count < bufferCount) { //if there is enough data in buffer 
      System.arraycopy(this._buffer, this._bufferStartIndex, result, 0, count); 
      this._bufferStartIndex += count; 
      return result; 
     } 
     System.arraycopy(this._buffer, this._bufferStartIndex, result, 0, bufferCount); 
     this._bufferStartIndex = this._bufferEndIndex = 0; 
     resultOffset += bufferCount; 
    } 

    while (resultOffset < count) { 
     int needCount = count - resultOffset; 
     this._buffer = this.func(); 
     if (needCount > 20) { //we one (or more) additional passes 
      System.arraycopy(this._buffer, 0, result, resultOffset, 20); 
      resultOffset += 20; 
     } else { 
      System.arraycopy(this._buffer, 0, result, resultOffset, needCount); 
      this._bufferStartIndex = needCount; 
      this._bufferEndIndex = 20; 
      return result; 
     } 
    } 
    return result; 
} 


private byte[] func() { 
    this._hmacSha1.update(this._salt, 0, this._salt.length); 
    byte[] tempHash = this._hmacSha1.doFinal(getBytesFromInt(this._block)); 

    this._hmacSha1.reset(); 
    byte[] finalHash = tempHash; 
    for (int i = 2; 5i <= this._iterationCount; i++) { 
     tempHash = this._hmacSha1.doFinal(tempHash); 
     for (int j = 0; j < 20; j++) { 
      finalHash[j] = (byte)(finalHash[j]^tempHash[j]); 
     } 
    } 
    if (this._block == 2147483647) { 
     this._block = -2147483648; 
    } else { 
     this._block += 1; 
    } 

    return finalHash; 
} 

private static byte[] getBytesFromInt(int i) { 
    return new byte[] { (byte)(i >>> 24), (byte)(i >>> 16), (byte)(i >>> 8), (byte)i }; 
} 

} 

這裏是實現

String encryptedText = Crypt.SimpleEncryptWithPassword("My string to encrypt", "VeryHardPassword", null); 
System.out.println("encrypted text=" + encryptedText); 
System.out.println("decrypted text=" + Crypt.SimpleDecryptWithPassword(encryptedText, "VeryHardPassword", 0)); 
+0

哇,這是很多的代碼。請注意,PBKDF2(Rfc2898DeriveBytes)功能應該已經存在於Java中(儘管它只與ASCII字符兼容)。如果您已經驗證了密鑰是正確的,那麼看起來您正在Java中使用**塊的大小爲256位,而在jbtule的C#代碼中使用128位(即AES)。 – 2014-12-02 20:36:46

+0

我忘了提及我修改了一點c#實現(有deprication和其他東西)以及256位。 cryptKey和authKey是不同的(Java/C#),我認爲錯誤是在Rfc2898DeriveBytes中,所以至少現在我知道在哪裏看。 – FanaticNinja 2014-12-03 03:07:29

回答

0

這裏是解決方案:刪除Rfc2898DeriveBytes類..使用此功能DeriveBytes ..

private static byte[] Rfc2898DeriveBytes(String password, byte[] salt, int iterations) throws GeneralSecurityException { 

    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
    PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), salt, Iterations, 256); 
    Key secretKey = factory.generateSecret(pbeKeySpec); 
    byte[] rawKeyData = secretKey.getEncoded(); 
    return rawKeyData; 
} 

也有一些變化,隱窩類指Rfc2898DeriveBytes適用。

byte[] cryptKey = Rfc2898DeriveBytes(password, cryptSalt, Iterations); 
byte[] authKey = Rfc2898DeriveBytes(password, authSalt, Iterations); 

隨着這些變化,它會接受任何c#加密到java解密以及java加密到c#解密!

讓我開心:)