0

The C# is on the client end while Java code is used in a service. Windows phone encrypts the data while Java decrypts the data using the same symmetric key.

Below is my C# method for encryption

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";
    }
}

Below is my Java class for decryption

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;
}
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • Did you have a question? – khelwood Nov 20 '15 at 12:21
  • And does it work? If not, do you get any errors? – Thilo Nov 20 '15 at 12:21
  • Do not use ECB if your encrypting more than 1 block. – Alex K. Nov 20 '15 at 12:34
  • One uses pkcs5, the other pkcs7 – Alex K. Nov 20 '15 at 12:35
  • Looks similar to [this](http://stackoverflow.com/questions/11733424/how-use-aes-ecb-pkcs7padding-algorithm-in-windows-phone-7/11738873#11738873) question (windows phone 7 - AES) – Cleptus Nov 20 '15 at 12:43
  • 1
    Why did you create a new account? You could have used your old one. Since you've asked another question, you can delete the [old question](http://stackoverflow.com/questions/33824728/i-need-a-java-equivalent-of-my-c-sharp-aes-encryption) (using your other account). See also: [I accidentally created two accounts; how do I merge them?](http://stackoverflow.com/help/merging-accounts) – Artjom B. Nov 20 '15 at 16:01
  • @AlexK. PKCS#5 padding and PKCS#7 padding is the [same thing](http://crypto.stackexchange.com/q/9043/13022). – Artjom B. Nov 20 '15 at 16:04

1 Answers1

0

The key generation is not complete. For some reason, your C# code uses sets the last byte of the key to the same value as the first byte with the following code:

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

(To my understanding, this could should throw some exception, because you can't copy 16 bytes into the 16 byte array hash if you begin at index 15.)

You could do the same (bad) thing in 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();
    }
}

Things to consider:

  • ECB mode does not provide semantic security and it should never be used. Use at the very least CBC mode with a random IV for each encryption under the same key.
  • Passwords should be hashed multiple times. A single hash makes it easy for an attacker to brute-force the password, because this is operation is fast. You should use Password-based Encryption with a strong key derivation function like PBKDF2 (more than 100,000 iterations), scrypt or bcrypt. Don't forget to use a random salt.
  • Authenticate your ciphertexts. You would want to detect (malicious) manipulations of your ciphertexts in transit. This can be done either with an authenticated mode like GCM or EAX, or with an encrypt-then-MAC scheme by running a MAC algorithm over your ciphertexts. A strong MAC is HMAC-SHA256.
Artjom B.
  • 61,146
  • 24
  • 125
  • 222