Android Question Cross Platform Encryption with .net?

Chris Lee

Member
Licensed User
Hi, I have versions of my app written in B4A,B4i and B4J.
I also have a web service written in .net.
All versions have to send encrypted data to the service, which needs to be decrypted within the service.
I need the ability to go the other way, and encrypt on the .net side and decrypt in B4X environments.

I began by looking at the obvious choice B4XEncryption.
However based on current information it appears that this will only support the three B4X environments.
That's fare enough, and I appreciate no real support can be given on the .net side.

I've been looking at the BouncyCastle.Crypto DLL on the .net side, but since I don't know exactly what the encryption routine does inside B4XEncryption it's going to be tough going.

I've got some .net samples, see below, but I've no idea if it would be feasible to use the .net Bouncy Castle Libraries.

If this isn't possible, does anyone have any suggestions on options that might be used in this scenario?


_encoding = Encoding.ASCII;
Pkcs7Padding pkcs = new Pkcs7Padding();
_padding = pkcs;

public string Encrypt(string plain, string key)
{
byte[] result = BouncyCastleCrypto(true, _encoding.GetBytes(plain), key);
return Convert.ToBase64String(result);
}

public string Decrypt(string cipher, string key)
{
byte[] result = BouncyCastleCrypto(false, Convert.FromBase64String(cipher), key);
return _encoding.GetString(result);
}
 

Erel

Administrator
Staff member
Licensed User
Upvote 0

Chris Lee

Member
Licensed User
Awesome Erel, compliments on your excellent support, I wish Oracle, Google and Microsoft were as responsive!

I decided to go from 'Possible' to 'Actual' and ported your java example to .net C#
I am using the BouncyCastle.Crypto .net library 1.8.1.0

I'm pleased to say it works perfectly! (both directions)
I will release it as a .net DLL including compiled version and source code in case others may find it useful, but for now, here is the main .net class:


B4X:
using System;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Modes;

namespace B4XEncryption
{
    public static class B4XCipher
    {
        public static byte[] Decrypt(byte[] Data, String Password)
        {

            byte[] salt = new byte[8];

            byte[] iv = new byte[16];

            Array.Copy(Data, 0, salt, 0, 8);

            Array.Copy(Data, 8, iv, 0, 16);

            Pkcs5S2ParametersGenerator pGen = new Pkcs5S2ParametersGenerator(new Sha1Digest());

            byte[] pkcs12PasswordBytes = System.Text.Encoding.UTF8.GetBytes(Password);

            pGen.Init(pkcs12PasswordBytes, salt, 1024);

            CbcBlockCipher aesCBC = new CbcBlockCipher(new AesEngine());

            ParametersWithIV aesCBCParams = new ParametersWithIV(pGen.GenerateDerivedParameters(128), iv);

            aesCBC.Init(false, aesCBCParams);

            PaddedBufferedBlockCipher aesCipher = new PaddedBufferedBlockCipher(aesCBC,
                new Pkcs7Padding());

            aesCipher.Init(false, (pGen.GenerateDerivedParameters(128)));

            byte[] plainTemp = new byte[aesCipher.GetOutputSize(Data.Length - 24)];

            int offset = aesCipher.ProcessBytes(Data, 24, Data.Length - 24, plainTemp, 0);

            int last = aesCipher.DoFinal(plainTemp, offset);

            byte[] plain = new byte[offset + last];

            Array.Copy(plainTemp, 0, plain, 0, plain.Length);

            return plain;
        }

        public static byte[] Encrypt(byte[] Data, String Password)
        {

            SecureRandom rnd = new SecureRandom();

            byte[] salt = new byte[8];

            rnd.NextBytes(salt);

            byte[] iv = new byte[16];

            rnd.NextBytes(iv);

            Pkcs5S2ParametersGenerator pGen = new Pkcs5S2ParametersGenerator(new Sha1Digest());

            byte[] pkcs12PasswordBytes = System.Text.Encoding.UTF8.GetBytes(Password);

            pGen.Init(pkcs12PasswordBytes, salt, 1024);

            CbcBlockCipher aesCBC = new CbcBlockCipher(new AesEngine());

            ParametersWithIV aesCBCParams = new ParametersWithIV(pGen.GenerateDerivedParameters(128), iv);

            aesCBC.Init(true, aesCBCParams);

            PaddedBufferedBlockCipher aesCipher = new PaddedBufferedBlockCipher(aesCBC,
                    new Pkcs7Padding());

            aesCipher.Init(true, (pGen.GenerateDerivedParameters(128)));

            byte[] plainTemp = new byte[aesCipher.GetOutputSize(Data.Length)];

            int offset = aesCipher.ProcessBytes(Data, 0, Data.Length, plainTemp, 0);

            int last = aesCipher.DoFinal(plainTemp, offset);

            byte[] plain = new byte[offset + last + 24];

            Array.Copy(salt, 0, plain, 0, 8);

            Array.Copy(iv, 0, plain, 8, 16);

            Array.Copy(plainTemp, 0, plain, 24, offset + last);

            return plain;

        }

    }



}
 
Upvote 0
Top