Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert encrypt/decrypt from Java to C# using bouncycastle

I'm trying to convert a couple of function from Java to c# using Portable.BouncyCastle and while there are plenty of example out there, I don't seem to be able to find one to match my requirements as most example seem to explain one specific encryption/decryption method while this function appears to be more generic. I could be wrong of course as I'm a complete newbie to this and don't have any experience in either BouncyCastle, Java or encryption, so please bear with me on this one.

The java function is:

public static byte[] Cipher(int mode, byte[] key, 
       byte[] data, string algorithm, AlgorithmParameterSpec spec)
{
  Cipher cipher = Cipher.getInstance(algorithm);
  SecretKeySpec keySpec = new SecretKeySpec(key, algorithm);

  if (spec != null)
     cipher.init(mode, keySpec, spec);
  else
     cipher.init(mode, keySpec);

   return cipher.doFinal(data);
}

I found some code from BouncyCasle where I can match most of the functionality from what I can see:

byte[] K = Hex.Decode("404142434445464748494a4b4c4d4e4f");
byte[] N = Hex.Decode("10111213141516");
byte[] P = Hex.Decode("68656c6c6f20776f726c642121");
byte[] C = Hex.Decode("39264f148b54c456035de0a531c8344f46db12b388");

KeyParameter key = ParameterUtilities.CreateKeyParameter("AES", K);

IBufferedCipher inCipher = CipherUtilities.
    GetCipher("AES/CCM/NoPadding");

inCipher.Init(true, new ParametersWithIV(key, N));

byte[] enc = inCipher.DoFinal(P);

1. SecretKeySpec:

    SecretKeySpec keySpec = new SecretKeySpec(key, algorithm);

How do I create this using BC? Is that the equivalent of the SecretKeySpec:

    KeyParameter key = ParameterUtilities.CreateKeyParameter("AES", K);

If it is, can I pass the "AES/CCM/NoPadding" instead of AES as it is done in Java?

2. spec parameter:

It passes parameters of type IvParameterSpec to the Cypher function when called from `Java` via the `AlgorithmParameterSpec spec` parameter:

Cipher(ENCRYPT_MODE, key, clearBytes,
                algorithm, 
                new IvParameterSpec(iv))

`BouncyCastle` does not have an overloaded function for `.Init` to allow me to pass the spec parameter as it does in `Java`, so how do I mimic this behaviour?

3. IvParameterSpec: You can see that when cypher is called from java, it passes the AlgorithmParameterSpec spec as new IvParameterSpec(iv) but with BouncyCastle, it seems to be expecting a key?

ParametersWithIV(key, N)

Will that difference have any impact on the encryption/decryption?

This is current my attempt at "converting" this function:

public static byte[] Cipher(bool isEncrypt, byte[] key, byte[] data, 
                            string algorithm, ICipherParameters spec)
    {
        IBufferedCipher cipher = CipherUtilities.GetCipher(algorithm);
        KeyParameter keySpec = ParameterUtilities.
           CreateKeyParameter(algorithm, key);

        cipher.Init(isEncrypt, new ParametersWithIV(keySpec, 
          keySpec.GetKey()));

        return cipher.DoFinal(data);
    }

As you can see I've changed the spec parameter to ICipherParameters spec but I don't know if this will work as when using Bouncy, it looks like that when I create a new ParametersWithIV, it needs a key and from the test sample I provided above, that key is created using KeyParameter key = ParameterUtilities.CreateKeyParameter("AES", K); so technically won't work when trying to call my Cipher function as I will have called this function yet. Should I change spec parameter to iv and pass a byte[] instead?

Apologies if there is confusion or if things are not explained correctly but as I said, I'm new to this and trying to understand it better while also converting. I hope most of it makes sense and you'll be able to help.

Many Thanks.

PS: Note that I'm not in a position to test these in Java yet, but I will hopefully have an environment set up correctly in the new few days which will hopefully help testing values between .net & java.

UPDATE 1

Passing AES/CCM/NoPadding to:

KeyParameter key = ParameterUtilities.CreateKeyParameter

Throws an error, so this partially answers one of my questions. Is there a function in BouncyCastle to determine the correct value that is required i.e. AES when AES/CCM/NoPadding is passed?

like image 285
Thierry Avatar asked Jan 17 '26 19:01

Thierry


1 Answers

Ended up using the code below as it appears to be working as expected but still annoyed I had to hardcode the AES as the key of IV parameter part. Ideally I would have liked this to have been based on my Algorithm. So, now I have a single function to encrypt and decrypt:

public static byte[] Cipher(bool forEncryption, byte[] key, 
 byte[] data, string algorithm, byte[] iv)
 {
    IBufferedCipher cipher = CipherUtilities.GetCipher(algorithm);
    KeyParameter keySpec = ParameterUtilities.CreateKeyParameter("AES", key);
    cipher.Init(forEncryption, new ParametersWithIV(keySpec, iv));
    return cipher.DoFinal(data);
 }

Hope this helps.

like image 79
Thierry Avatar answered Jan 20 '26 08:01

Thierry