Common encryption algorithm between Java and C#

Asked

Viewed 4,153 times

24

Problem

I am creating a Web Service in C# to be consumed by an Android application (Java), among other information I would like to pass the user credências to login offline on the app. But these beliefs would like to send encrypted (C#), and save them in the application, and at the time of login in the application I want to encrypt the password informed by the user in the entry, with the same encryption algorithm used in C#, to compare it with the credential saved in the app.

Passwords will not be changed in the application, being possible only in the legacy system where the Web Service query. And all the strategy to keep this data synchronized (application offline and legacy system) is already implemented.

Doubt

I don’t understand encryption algorithms very well, to the point of knowing how they work internally, for example: I don’t know if C# md5 has the same internal functioning as Java md5, IE, if always with the same input they will have the same output, whether in Java or C#.

So I’d like to know if there’s any encryption algorithm, common to the two technologies, that I can reliably use in my case?

  • 3

    Not with the intention of answering the question, but to give a general idea, I recommend reading: http://answall.com/questions/2402/comort-hash-hash-de-passwords-safe. As for the functions used, implementations for various languages are common. Storing some bcrypt output in the offline version, for example, would solve. MD5, on the other hand, will not help you much.

3 answers

16

From what I understand are your questions:

  1. Yes, the "encryption mechanisms" are the same, ie: implemented the same algorithm with the same initialization parameters, the obtained result should be the same = identical outputs.

  2. MD5 isn’t exactly encryption, it’s a hash: takes an input of any size and turns it into an output of a fixed size. And it’s irreversible: from the output produced you can’t (or shouldn’t be able to) tell which was the input.

  3. The MD5 output of a Java library should be the same as that of a C# library that should be the same as that of a Perl program. EXE calculating a MD5 hash.

And if I understand, you want to have a C# application on a server that checks the user’s password, this ? And you want your Java application to store the same password on the device (mobile?) and the user to enter the password to enter the application, this ? For example. , if user is logged in, type the password and it is validated on the server, if user is offline, enter the password and is validated in the application ?

If so, then: (what I think is the best approach)

  1. offline: In the first use or installation, the password is typed by the user, your java application hashes it (using bcrypt or scrypt or pbkdf2, MD5 is no longer indicated for a while) and stores it on the device. The next time the user logs in offline, the application hashes again and compares if the hash saved is the same as the hash just calculated, and authorizes or not the user.

  2. online: all the same as step 1, only it is saved on the server and not on the device. Remember that it is an internet access with an "open" password, that is, on Plain text, and anyone who intercepts the communication could see the password. Use communication encryption mechanisms (Https, etc).

  3. sync of the password offline - online : along with the password store a value of when was the last time the password was changed. When the app is in online mode, send the password hash and date to the server: if the device password is the latest, update the server password.

  4. password exchange: every time the user changes the online password, the application changes the offline password (calculates the hash and saves it offline), and this completes step 3. Every time you switch offline, item 3 will make it synchronized with the server at the first access.

And most importantly, learn how to securely store the password on your device. Even if it is stored in hash form, it can always be possible for an attacker to try to change this hash to a hash he knows (i.e., he will hash a password he knows, so he will know the password). Each operating system (Android, Ios) has mechanisms to restrict this type of access, learn how to use them.

  • Do you consider it convenient, to use [tag:md5], as a hash for that purpose, or is there something more interesting?

  • Oops, I was editing the question at the same time :). MD5 is considered weak (as it is very easy/fast to calculate millions/billions of MD5 hashes). Go with bcrypt or scrypt or pbkdf2, and see the link that Bacco put there in the comment of your question

  • Yes, it was simultaneity problem. hehe. I read the @Acco link thread, and it’s a very good alias, I’ll study the algorithms cited, and as for restricting access to stored password, the [tag:android] has a major problem which is root access to the device, where the attacker would have access, to the application’s files and database. And I don’t know how to act to prevent it?

  • It is inevitable. If an attacker has access to hardware (computer, cell phone, etc), he has it all. You can make it difficult, not prevent. If you use strong hashes (like pbkdf2) with salt, it will have the hash, and it will take zillions of years to break. But if your password is weak (type 123456), you don’t have the technology to solve it. If it install a keylogger on mobile and user enter password, also it does not have what you can do. If he films user by entering password, idem :). Inevitable this.

  • Good placement, "You can make it difficult", That’s the whole idea. Among the techniques you mentioned in the answer, there is some that you indicate to me and that there is already implementation in both [tag:java] and [tag:c#], and that is reasonably safe and easy to implement. Since in my case (for now), a security, even if not very strong is enough. (something is better than nothing, ^^)

  • Pbkdf2 to c#: http://www.shawnmclean.com/blog/2012/04/simplecrypto-net-a-pbkdf2-hashing-wrapper-for-net-framework/ and java http://bouncycastle.org/ . I haven’t checked if the parameters are the same, IE, if you can set the number of iterations, the salt...

  • For those who edited: sorry, I gave a rollback because the issue left the question full of links to tags here from Stackoverflow. The purpose of tags is only to make it easier to search for questions. I think links in the answers would only be good if they went to sites that explain something better (e.g.: link in "encryption" to a website that explains what encryption is)

  • Thanks for the help, it was very useful, posted my solution

  • 1

    @Fernando: you can mark how you accept your answer (since it is what solved even the problem). Thank you for accepting mine, I earn points with this, but I can lose them and you accept the best answer (your :) )

Show 4 more comments

7


Well after analyzing the options pointed out by you, I implemented my solution using Pbkdf2 which was the following:

In C#, I followed this example thus getting my implementation:

// este retorna em bytes (byte[])
public static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes)
{
    Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt);
    pbkdf2.IterationCount = iterations;
    return pbkdf2.GetBytes(outputBytes);
}

// Esse retorna em Base64 (que é o que uso no fim)
public static string PBKDF2ToBase64(string password, byte[] salt, int iterations, int outputBytes)
{
    return Convert.ToBase64String(PBKDF2(password, salt, iterations, outputBytes));
}

In Java, I followed this and this example thus getting my implementation:

private static final int KEYLENGTH_MULTIPLIER = 8;
// este retorna em bytes (byte[])
public static byte[] PBKDF2(String password, byte[] salt, int iterations,
        int outputBytes) throws NoSuchAlgorithmException,
        InvalidKeySpecException {
    KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations,
            outputBytes * KEYLENGTH_MULTIPLIER);
    SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    return f.generateSecret(spec).getEncoded();
}

// Esse retorna em Base64 (que é o que uso no fim)
public static String PBKDF2ToBase64(String password, byte[] salt, int iterations,
        int outputBytes){
    try {
        return new String(Base64.encodeBase64(PBKDF2(password, salt, iterations, outputBytes)), "UTF-8");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (InvalidKeySpecException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return null;
}

The library I’m using to convert to Base64 in Java is that one, and in Android the method encodeBase64String, does not work and I made an adaptation with the method encodeBase64 in accordance with that one suggestion.

Apparently everything is working perfectly, both in C#, as in Java (Android), if you notice any improvement, she is welcome. Thank you all for your help.


Explanation of parameters:

The parameters salt, iterations, outputBytes are settings parameters of the Hash method, and can be used as secret keys of your application.

Where:

  1. salt: Or salt in Portuguese
  2. iterations: Number of iterations to calculate the hash, the higher the hash processing time;
  3. outputBytes: Amount of hash output bytes;

Example of use:

C#:

private int LengthOutputBytes = 32;
private byte[] Salt = new byte[] { 0x20, 0x23, 0x65, 0x46, 0x43, 0x24, 0x55, 0x23, 0x31, 0x33, 0x32, 0x34, 0x72, 0x18, 0x67, 0x68 };
private int HashIterations = 10;
private string password = "123";

string hash = PBKDF2ToBase64(password, Salt, HashIterations, LengthOutputBytes);

Java:

private byte[] SALT = { 0x20, 0x23, 0x65, 0x46, 0x43, 0x24,
        0x55, 0x23, 0x31, 0x33, 0x32, 0x34, 0x72, 0x18, 0x67, 0x68 };
private int ITERATIONS = 10;
private int OUTPUTBYTES = 32;
private String password = "123";

String hash = PBKDF2ToBase64(password, SALT, ITERATIONS, OUTPUTBYTES);

4

Cryptographic processes like MD-5, AES, Base64, etc, work equally independently of the language that implements them. I have a project in C#. NET that can remedy, I believe, your problems in implementing an encryption using C#. You can access it here.

Just compile the project and use the DLL.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.