簡體   English   中英

驗證(HMAC)的Java實現,然后是UTF8消息的解密(AES)的Java實現(C#和Java(Android)兼容性)

[英]Java implementation of Authentication (HMAC) and then Descryption (AES) of a UTF8 Message (C# and Java (Android) Compatibility)

我整周都在面對鍵盤問題,試圖將C#加密類( https://gist.github.com/jbtule/4336842#file-aesthenhmac-cs )轉換為Java。

我遇到的問題是從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));

這里是解決方案:刪除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;
}

如果適用,在crypt類中還會引用Rfc2898DeriveBytes進行一些更改。

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

通過這些更改,它將接受對Java解密的所有c#加密以及對c#解密的java加密!

讓我開心 :)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM