繁体   English   中英

在Windows Phone 8.1上以C#加密并在Java中解密

[英]Encrypt on Windows Phone 8.1 in C# and decrypt in Java

C#在客户端,而Java代码在服务中使用。 Windows Phone对数据进行加密,而Java使用相同的对称密钥对数据进行解密。

以下是我的C#加密方法

public static string EncryptAesTest(string data, string password)
{
    SymmetricKeyAlgorithmProvider SAP = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesEcbPkcs7);
    CryptographicKey AES;
    HashAlgorithmProvider HAP = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512);
    Windows.Security.Cryptography.Core.CryptographicHash Hash_AES = HAP.CreateHash();

    string encrypted;

    try
    {

        byte[] hash = new byte[16];
        Hash_AES.Append(CryptographicBuffer.CreateFromByteArray(System.Convert.FromBase64String(password)));
        byte[] temp;
        CryptographicBuffer.CopyToByteArray(Hash_AES.GetValueAndReset(), out temp);
        Array.Copy(temp, 0, hash, 0, 16);
        Array.Copy(temp, 0, hash, 15, 16);
        AES = SAP.CreateSymmetricKey(CryptographicBuffer.CreateFromByteArray(hash));
        IBuffer Buffer = CryptographicBuffer.CreateFromByteArray(Encoding.UTF8.GetBytes(data));
        encrypted = CryptographicBuffer.EncodeToBase64String(CryptographicEngine.Encrypt(AES, Buffer, null));
        return encrypted;
    }
    catch
    {
        return "encryption error";
    }
}

下面是我的Java解密类

private SecretKeySpec secretKey;
public void setKey() {
    skey = "mykey";
    MessageDigest sha = null;
    try {
        key = skey.getBytes("UTF-8");
        logger.debug("Key length ====> " + key.length);
        sha = MessageDigest.getInstance("SHA-512");
        key = sha.digest(key);
        key = Arrays.copyOf(key, 16); // use only first 128 bit

        secretKey = new SecretKeySpec(key, "AES");

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
}
public String decrypt(String strToDecrypt) {
    Cipher cipher = null;
    try {
        cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");

        cipher.init(Cipher.DECRYPT_MODE, this.secretKey);
        setDecryptedString(new String(cipher.doFinal(Base64
                .decodeBase64(strToDecrypt))));

    } catch (Exception e) {
        System.out.println("Error while decrypting: " + e.toString());
    }
    return null;
}

密钥生成不完整。 出于某种原因,您的C#代码使用以下代码将键的最后一个字节设置为与第一个字节相同的值:

Array.Copy(temp, 0, hash, 0, 16);
Array.Copy(temp, 0, hash, 15, 16);

(据我了解,这可能会引发一些异常,因为如果从索引15开始,则无法将16个字节复制到16个字节的数组hash 。)

您可以在Java中执行相同(坏)的操作

public void setKey() {
    skey = "mykey";
    MessageDigest sha = null;
    try {
        key = skey.getBytes("UTF-8");
        logger.debug("Key length ====> " + key.length);
        sha = MessageDigest.getInstance("SHA-512");
        key = sha.digest(key);
        key = Arrays.copyOf(key, 16); // use only first 128 bit
        key[15] = key[0]; // added

        secretKey = new SecretKeySpec(key, "AES");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
}

注意事项:

  • ECB模式不提供语义安全性, 永远不要使用它 对于同一密钥下的每种加密,至少要使用带有随机IV的CBC模式。
  • 密码应多次哈希。 单个哈希值使攻击者可以轻松地将密码强行使用,因为这是快速的操作。 您应该使用基于密码的加密以及强大的密钥派生功能,例如PBKDF2(超过100,000次迭代),scrypt或bcrypt。 不要忘记使用随机盐。
  • 验证您的密文。 您可能想检测传输中密文的(恶意)操纵。 既可以使用GCM或EAX之类的身份验证模式,也可以通过在密文上运行MAC算法来使用“加密-然后-MAC”方案来完成此操作。 一个强大的MAC是HMAC-SHA256。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM