Search code examples
c#bouncycastle

Bouncy Castle PBEWITHSHA256AND256BITAES encryption in C#


I am trying to replicate this Java code in C#.

        BASE64Decoder dec = new BASE64Decoder();
    byte[] salt = null;
    try {
        salt = dec.decodeBuffer(saltStr);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    Security.insertProviderAt(new BouncyCastleProvider(), 1);
    String alg = "PBEWITHSHA256AND256BITAES-CBC-BC";
    int derivedKeyLength = 256;
    int iterations = 20000;
    KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations,
            derivedKeyLength);
    try {
        SecretKeyFactory f = SecretKeyFactory.getInstance(alg);
        byte[] result = f.generateSecret(spec).getEncoded();
        BASE64Encoder endecoder = new BASE64Encoder();
        System.out.println(endecoder.encode(result));
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (InvalidKeySpecException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

This is what I have so far, but it's failing. I am new to the Crypto world (so there may be an easier way to do this that I don't know) so any help would be appreciated. Thanks!

        var iterations = 20000;
        PbeParametersGenerator pGen = new Pkcs12ParametersGenerator(new Sha256Digest());
        pGen.Init(Encoding.ASCII.GetBytes(password), Convert.FromBase64String(salt), iterations);
        ICipherParameters par = pGen.GenerateDerivedParameters("AES256", 256);
        IBufferedCipher c = CipherUtilities.GetCipher("PBEWITHSHA256AND256BITAES-CBC-BC");
        Console.WriteLine(c.AlgorithmName);
        c.Init(true, par);
        byte[] enc = c.DoFinal(Convert.FromBase64String(salt));
        Console.WriteLine("The output is :");
        Console.WriteLine(Convert.ToBase64String(enc));

The issue is that the encrypted result is not the same in the Java and C# with the same password, the same salt, and the same number of iterations.

Update:

The problem was that the Java code (not written by me, is not doing the cipher encryption) it's only generating the key parameters. This code would give the same output as the Java code.

        var iterations = 20000;
        var sltBytes = Convert.FromBase64String(salt);
        byte[] byteSalt = Convert.FromBase64String(salt);
        byte[] pwdb = PbeParametersGenerator.Pkcs12PasswordToBytes(password.ToCharArray());
        PbeParametersGenerator pGen = new Pkcs12ParametersGenerator(new Sha256Digest());
        pGen.Init(pwdb, Convert.FromBase64String(salt), iterations);
        var par = (ParametersWithIV)pGen.GenerateDerivedParameters("AES256", 256, 128);
        var kpar = (KeyParameter)par.Parameters;
        byte[] by = kpar.GetKey();
        Console.WriteLine(Convert.ToBase64String(by));

Solution

  • Your call to GenerateDerivedParameters("AES256", 256) is specifying a different key length than the derivedKeyLength in Java.