Question:
I'm developing a Java program and at one point I want it to encrypt a word before saving it to a database. Right now it encodes me with Base64 from the Apache commons library.
Is there some type of encryption that allows me to keep the data more secure than my current method and that also uses a word to encrypt? (I know that Base64 is not a type of encryption as such)
Answer:
To begin with, Base64
is an encoding that is not intended to protect your data, because it is completely reversible. Base64
is nothing more than another representation of a byte string, like a hex string (Base16). Without any secrets you can calculate the original data from a Base64
string.
If you simply want to save the password as a hash that prevents the password from being deduced from the saved data, you can use a java.security.MessageDigest
( Available algorithms ). Example:
// elige por ejemplo entre los algoritmos disponibles
// en este caso un 48 byte sha-384
MessageDigest md = MessageDigest.getInstance("SHA-384");
byte[] digest = md.digest(passwd.getBytes("UTF-8"));
// luego puedes guardar los byte o transformarlos en otro formato como hexString etc.
No secret word is used for that.
If you want to encrypt with secrecy
You can use the javax.crypto
library for keyword encryption. In this example the AES algorithm is used, clave
is the keyword and iv
the initialization vector (as seed).
More information about AES
found here .
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
public class MiCipher {
public static SecureRandom sr = new SecureRandom();
public static String encriptar(String clave, byte[] iv, String value) {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
SecretKeySpec sks = new SecretKeySpec(clave.getBytes("UTF-8"), "AES");
cipher.init(Cipher.ENCRYPT_MODE, sks, new IvParameterSpec(iv));
byte[] encriptado = cipher.doFinal(value.getBytes());
return DatatypeConverter.printBase64Binary(encriptado);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String decriptar(String clave, byte[] iv, String encriptado) {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
SecretKeySpec sks = new SecretKeySpec(clave.getBytes("UTF-8"), "AES");
cipher.init(Cipher.DECRYPT_MODE, sks, new IvParameterSpec(iv));
byte[] dec = cipher.doFinal(DatatypeConverter.parseBase64Binary(encriptado));
return new String(dec);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static void main(String[] args) {
String clave = "FooBar1234567890"; // 128 bit
byte[] iv = new byte[16];
sr.nextBytes(iv);
String encriptado = encriptar(clave, iv, "Demasiados Secretos!");
System.out.println(String.format("encriptado: %s", encriptado));
System.out.println(decriptar(clave, iv, encriptado));
}
}
end of TLDR;
About cryptography and clarification of terms
1) What is the cryptographic value of Base64
encoding?
None. As an encoding, Base64 is a bidirectional function that represents a string of data in 6-bit segments by the characters [A-Za-z0-9] plus two that depend on the implementation. In this case (xsd: base64Binary) the other two characters are +
and /
, while =
indicates the end of the string.
The encoding is used here, because after encrypting the original string we receive a result as a string of bytes that could contain unrepresentable characters. The base 64 allows us to incorporate the encrypted data in xml documents, mail or, for example, text fields in a database.
2) What then can I use to encrypt data with secrets?
In the example above I showed how to use AES
, a symmetric algorithm (as opposed to for example RSA, which is asymmetric). AES
uses figures of 128, 192 or 256bit and is already in 128bit considered very secure (sufficiently secure for the NSA). Like all cryptographic algorithms, there is always the possibility of decrypting data, but AES
is generally considered invulnerable to less brute force attacks (testing keys until encryption works).
3) What is the difference between symmetric and asymmetric algorithms?
Symmetric algorithms (such as AES
, DES
or Blowfish
) use a single key (a secret) to encrypt and decrypt a string of data. Thus, both parties have to have the key and in the event that the key is compromised, the number loses its use.
Asymmetric algorithms (like RSA
) otherwise use two secrets, usually named the public secret and the private secret. To decrypt a data string encrypted with one of the secrets, the other secret needs to be used.
4) What then is a hash and what is it used for in the security context?
A hash is a one-way function that calculates a value of defined size from a string of variable size. A hash is an abstract representation of a particular piece of data, and it doesn't necessarily have to be "perfect" (meaning that no two different pieces of data have the same hash ). When storing passwords in databases there is good practice to save them in the form of a hash , in the ideal case longer than the typical password. The security benefit is only that in the event that an attacker gains access to the passwords, it becomes difficult for him to guess the password that results in the hash calculation.
5) Where are the different methods applied and how are they combined?
Asymmetric encryption is much more expensive in computational context than symmetric encryption. The problem with symmetric encryption, however, is the dispatch of the key from the source to the destination, because in the case that the key is discovered by an attacker, the encryption is broken.
With asymmetric encryption, the public key can be made publicly accessible while the private key is kept out of reach, this allows a transmission to be initiated to the machine from any source that cannot be decrypted by third parties.
This is why asymmetric encryption is used to transmit the key for symmetric encryption afterwards, which handles the heavy lifting of encrypting useful data that needs to be transferred securely.
Saving passwords as hash as already mentioned protects the password from being read from, for example, databases that were compromised, but to protect the password against "man-in-the-middle" attacks in which an attacker observes the transmissions between origin and destination, it is necessary to use again an asymmetric encryption.
6) What is the initialization vector and why is it created randomly?
The initialization vector is used to avoid some attack vectors on the cipher. An initialization vector should not be used to encrypt / decrypt two different data strings, or patterns are provided that make it easy to break the cipher. In the case of a block cipher that iterates over the blocks, it serves as the initial block, and therefore has the same size as a data block.