pwfixed
pwfixed

Reputation: 53

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));

Upvotes: 1

Views: 1760

Answers (2)

EtherDragon
EtherDragon

Reputation: 2698

I think this is your problem:

Here you specify a derived key length of 128

int derivedKeyLength = 128;
...
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations,
        derivedKeyLength);

Here you specify a derived key length of 256

ICipherParameters par = pGen.GenerateDerivedParameters("AES256", 256);

Upvotes: 1

CassOnMars
CassOnMars

Reputation: 6181

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

Upvotes: 2

Related Questions