Security - Generating Auth-Key for users using Base64? - java

I'm creating a website on which each new user created (that's what I'm doing for now) will have a auth-key generated which is in Base64 encoding. The auth-key is important as almost all actions performed will require the auth-key of the user. The problem started when I read this article on Base64-Padding and created a few users with more or less the same unique-name (the encryption is done using the unique-name and LocalDateTime at which the user is created). I saw that the keys generated are all very similar to one-another. And then I went through a few more resources and found it is extremely easy to decode it.
Ever since I've been wondering what are the security flaws that I'm facing if I use Base64 encoding? How bad is it? How vulnerable the website will be etc.?
Apart from the above questions I want to know when should I be using Base64 encoding and when I should not? Also what should I use if not Base64?
Note: I'm generating auth-key in Java and the encryption is in AES.
Thank you.

In security, use of Base64 is not to encrypt a string you want to keep secret, it is used to encode it.
In Basic Authentication, for example, the intent of the encoding is to encode non-HTTP-compatible characters that may be in a user name, password, or token into those that are HTTP-compatible.
Encoding does not provide any confidentiality, for that you need to encrypt the string.
Think of the encryption as the security bit, and the encoding is the making string play nice with HTTP.
A common approach at generating a token is to first encrypt it, and then encode it.

As the first line of the article you gave tells :
Base64 is a group of similar binary-to-text encoding schemes that
represent binary data in an ASCII string format by translating it into
a radix-64 representation.
As Base64 encoding can be reversed very easily (it has been designed for this) it would be easily to break through your authentication. You shouldn't consider using Base64 encoding or any cipher encryption for your purpose but instead an hash algorithm like MD5, SHA or other because they are, theoretically, non-reversible and unique. Here is an example for MD5 :
public byte[] digestAuthKey(String login, Date d) {
MessageDigest md = MessageDigest.getInstance("MD5");
String key = login + SALT + d.getTime();
return md.digest(key.getBytes());
}
The SALT contant is a randomly generated string that enhanced the security making it harder to break.
To convert the byte array to string see this post

Related

When i turn an java String into an md5 Hash, how can i decrypt it? [duplicate]

This question already has answers here:
How to reverse MD5 to get the original string? [duplicate]
(2 answers)
Closed 2 years ago.
I am looking into md5 hashing in java with the MessageDigest Class, lets say I do that
public void givenPassword_whenHashingUsingCommons_thenVerifying() {
String hash = "35454B055CC325EA1AF2126E27707052";
String password = "ILoveJava";
String md5Hex = DigestUtils
.md5Hex(password).toUpperCase();
assertThat(md5Hex.equals(hash)).isTrue();
}
So i did convert my password String into an md5 hash, lets say my recipient now wants the String not as hash, but as an normal String ( The Hash is just for transmission ), how can i convert the md5 hash String back to an "normal" Text String?
There is no way to convert a hash (MD5 or SHA1 or SHA2....) into the original string.
The purpose of a hashing function is a one-way translation. There is no coming back.
The MD5 hash function is an outdated cryptographic function that generates fixed length hashes of an input data. The how and whys is beyond the scope of this answer. I urge you to visit detailed texts on these online.
Please also remember that if you are using the MD5 for cryptographic and sensitive reasons, please learn about more secure recommended hashing as SHA256 etc..
For more details, please refer to this introductory text.
The reason that we hash passwords in particular is because it's one way and this is good for security reasons. Imagine a bad actor got access to your database, we wouldn't want them to be able to look up the password and log in as the user. By storing the hashed password, we can perform the same hashing algorithm on the password on login and compare it with the database value in the database for a successful login.
Even this has its issues. When bad actors gain access to a compromised database, they can generate "rainbow tables" to get from the hashed value to the password. Using common hashing algorithms and software such as hashcat they build up a database of common passwords, dictionary words etc. then match the hash value to the plain text string. This is why when storing passwords, we also use salting, which can be easily researched, Google "salting and hashing".
I see another answer which states that "The purpose of the hashing function is a one way translation". I think this is an over simplification. A hashing algorithm returns a message digest. It's a fixed length alphanumeric message which, as uniquely as possibly, represents the input. One the most important properties of a hashing algorithm is the uniqueness of the message and that it differs significantly from that of similar inputs. Here's an example using MD5:
String: aaaaaaaaaa
Hash: e09c80c42fda55f9d992e59ca6b3307d
String: aaaaaaaaab
Hash: ba05a43d3b98a72379fdc90a1e28ecaf

Can a hashed password using BCrypt in Java be recognised by Python?

I'm planning to hash user passwords using bcrypt, and to store these hashed passwords in a database.
The server that handles user account creation, and inserts the hashed password to the database is written in Java.
Another server that needs to access user information (including the hashed passwords) is written in Python.
I was planning to use jBCrypt for the Java side, but before I do that I want to make sure that I'll by able to recognise/use these hashed passwords from the Python side.
How I understand things, this should be no problem as long as the Python BCrypt implementation is the same as the Java implementation.
So, can I use the passwords hashed using jBCrypt from Python? How?
Thanks in advance!
The best way to know is to actually try it.
Assuming both implementations are correct, they should be compatible, as long as you take care to re-encode data as necessary.
Typically, a hash is stored in memory either as a byte array of the raw hash, or as a ASCII hexadecimal representation. The best way to know what encoding it's using is actually printing it to the console: if it looks like garbage, it'll be a raw byte array; if it prints a hexadecimal string (0-9 and a-f), it's ascii encoded hexadecimal.
Salt will probably be stored like the hash. The number of rounds is a integer. It's up to you to store all this data in a common format. If you need to convert a ascii hex string to a byte array (actually, a string) in python, you can use string.encode:
>>> 'hello world'.encode('hex')
'68656c6c6f20776f726c64'
>>> '68656c6c6f20776f726c64'.decode('hex')
'hello world'
For a bcrypt implementation in python, you may want to try py-bcrypt

Understanding hashing passwords in Java by MessageDigest

I'm creating a simple web application and want to store hashed passwords into a database. I need the hash function for the authentication token too (concatenating the user name and the date and send them with their hash to the client as the token).
I've found that MessageDigest Java class can help me with this. Here is one link.
The basic idea goes like this:
public String digestString (String stringToHash) throws NoSuchAlgorithmException {
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
byte[] stringBytes = stringToHash.getBytes();
byte[] stringDigest = sha256.digest(stringBytes);
return new String(stringDigest);
}
What I don't get is:
In this code, how can I set the hash key? I need to be sure that the same key will be used in the verification process. How can I do that if I don't set the key?
BTW: I know I should add a salt (256 bytes in this case) to the hashed text before hashing it.
A hash uses no key. It's just a one-way algorithm. You give it something to digest, and it returns a hash. What it guarantees is that it's extremely hard to find the original input or any other input that leads to the same hash.
Your algorithm has two basic problems (besides the lack of salting):
it uses String.getBytes(), which relied on the default platform encoding, and thus differs from platform to platform. You should specify an encoding such as UTF-8.
it uses new String(byte[]), which has the same problem as above + an additional one: all the sequence of bytes are not valid character. To transform a purely binary byte array into a String, use a base64 encoding algorithm. apache commons codes has one.

Symmetric Encryption between .NET and Java

I am using a 3rd party platform to create a landing page, it is a business requirement that I use this particular platform.
On their page I can encrypt data and send it to my server through a request parameter when calling a resource on my site. This is done through an AES Symmetric Encryption.
I need to specify a password, salt (which must be a hex value) and an initialization vector (but be 16 characters).
Their backend is a .NET platform. I know this because if I specify an IV longer than it expects the underlying exception is:
System.Security.Cryptography.CryptographicException: Specified initialization vector (IV) does not match the block size for this algorithm.
Source: mscorlib
So for example, on their end I specify:
EncryptSymmetric("Hello World","AES","P4ssw0rD","00010203040506070809", "000102030405060708090A0B0C0D0E0F")
Where the inputs are: plain text, algorithm, pass phrase, salt, and IV respectively.
I get the value: eg/t9NIMnxmh412jTGCCeQ==
If I try and decrypt this on my end using the JCE or the BouncyCastle provider I get (same algo,pass phrase, salt & IV, with 1000 iterations): 2rrRdHwpKGRenw8HKG1dsA== which is completely different.
I have looked at many different Java examples online on how to decrypt AES. One such demo is the following: http://blogs.msdn.com/b/dotnetinterop/archive/2005/01/24/java-and-net-aes-crypto-interop.aspx
How can I decrypt a AES Symmetric Encryption that uses a pass phrase, salt and IV, which was generated by the .NET framework on a Java platform?
I don't necessarily need to be able to decrypt the contents of the encryption string if I can generate the same signature on the java side and compare (if it turns out what is really being generated here is a hash).
I'm using JDK 1.5 in production so I need to use 1.5 to do this.
As a side note, a lot of the example in Java need to specify an repetition count on the java side, but not on the .NET side. Is there a standard number of iterations I need to specify on the java side which matches the default .NET output.
It all depends on how the different parts/arguments of the encryption are used.
AES is used to encrypt bytes. So you need to convert the string to a byte array. So you need to know the encoding used to convert the string. (UTF7, UTF8, ...).
The key in AES has some fixed sizes. So you need to know, how to come from a passphrase to an AES key with the correct bitsize.
Since you provide both salt and IV, I suppose the salt is not the IV. There is no standard way to handle the Salt in .Net. As far as I remember a salt is mainly used to protect against rainbow tables and hashes. The need of a Salt in AES is unknown to me.
Maybe the passphrase is hashed (you did not provide the method for that) with the salt to get an AES key.
The IV is no secret. The easiest method is to prepend the encrypted data with the IV. Seen the length of the encrypted data, this is not the case.
I don't think your unfamiliarity of .Net is the problem here. You need to know what decisions the implementer of the encryption made, to come from your parameters to the encrypted string.
As far as I can see, it is the iteration count which is causing the issue. With all things the same (salt,IV,iterations), the .Net implementation generates the same output as the Java implementation. I think you may need to ask the 3rd party what iterations they are using

Bouncycastle PBEWITHSHA256AND256BITAES-CBC-BC Javascript implementation

I've tried but failed to encode a string in Javascript to decode on a java server. We'd like to use the bouncycastle algorithm PBEWITHSHA256AND256BITAES-CBC-BC to decode serverside.
I've tried using crypto.js to do the encoding using the following code:
var encrypted = Crypto.AES.encrypt("it was Professor Plum in the library with the candlestick",
key,
{ mode: new Crypto.mode.CBC });
var encryptedString = Crypto.util.bytesToHex(Crypto.charenc.Binary.stringToBytes(crypted));
However this doesn't decode correctly on the server, my guess is its something to do with the SHA256 but I can't work out what it would be digesting & can't find any documentation. Does anyone know how to perform the encryption in javascript?
You need to do everything the same at both ends. You need the same key. You need the same mode (CBC) you need the same padding (use PKCS7) and you need the same IV.
Check that the actual key you are using is the same at both ends by displaying the hex, after you have run the passphrase through SHA-256. Check the hex for the IVs as well. Don't use any defaults, but explicitly pick the mode and padding to use.
If you think that it is the PBE/SHA-256 that is going wrong then you might want to look at how your text passphrase is being turned into bytes. Again, check the hex at both sides before it is passed to SHA-256. Converting text to bytes is a common source of errors. You need to be very sure what stringToBytes() is doing and that whatever you are using on the Java side is doing exactly the same.

Categories