PHP crypt(pass, salt) alternative in Java - Blowfish algorithm - java

I'm using on php server function crypt like this:
$hash = crypt($password, '$2y$10$' . $salt);
It makes hash of password by Blowfish method.
I'm looking for java equivalent for crypt password.
I found this code, but I don't know where add $salt. More above:
String key = "abcd";
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(cipher.ENCRYPT_MODE, keySpec);
return DatatypeConverter.printBase64Binary(cipher.doFinal(key.getBytes()));
Thank's for every idea or answer.

Not an answer to your question but maybe it helps:
There is the Apache Commons Codec library that contains a Linux crypt(3) compatible function for at least des,md5,sha256 and sha512 based crypt() algorithms in case you don't really need blowfish but just something stronger than the traditional DES based hashes (use sha512 then):
http://svn.apache.org/viewvc/commons/proper/codec/trunk/src/main/java/org/apache/commons/codec/digest/Md5Crypt.java?view=markup
And there's other source code that implements the Blowfish algorithm but it's in C:
http://doxygen.postgresql.org/crypt-blowfish_8c_source.html
As you can see crypt() uses algorithms that are only based on those encryption ciphers but pipes the input several thousant times through them to get a nice hash value.

Now I did found some java implementations of crypt(3) with blowfish:
http://www.mindrot.org/projects/jBCrypt/ (last update 2010)
and
http://docs.spring.io/spring-security/site/docs/3.2.3.RELEASE/apidocs/org/springframework/security/crypto/bcrypt/BCrypt.html

Related

Unable to decrypt csv file using symmetric key java

I am provided two files encrypted_key.enc and encrypted_data.csv.enc. I need to use my private key to decrypt the encrypted_key.enc to get a symmetric key and then use that symmetric key to decrypt the encrypted_data.csv.enc file.
On the terminal, the following commands get the job done:
openssl rsautl -decrypt -ssl -inkey my_private_key -in encrypted_key.enc -out key
openssl aes-256-cbc -d -in encrypted_data.csv.enc -out secret.txt -pass file:key
My goal is to perform the java equivalent of the two commands. I was able to successfully decrypt the first file and retrieve the symmetric key.
Now I'm unable to use that symmetric key to decrypt the csv file. My issue arises in the decipher.init(Cipher.DECRYPT_MODE, keySpec); I receive the following stacktrace
Exception in thread "main" java.security.InvalidKeyException: Illegal key size or default parameters
I'm unclear on what exactly I'm missing from the decryption process. I've tried changing the cipher provider but that didn't help. Other posts have posted solutions using an IVParameterSpec but my decryption case doesn't seem to need it or I'm confused on where to put it.
File file = new File("my_private_key");
PrivateKey pk = getPrivateKey(file);
// Decrypt secret key
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, pk);
File skFile = new File("encrypted_key.enc");
FileInputStream fileInputStream = new FileInputStream(skFile);
byte[] decodedBytes = IOUtils.toByteArray(fileInputStream);
byte[] original = cipher.doFinal(decodedBytes);
String decodedOriginal = new String(Base64.encodeBase64(original));
System.out.println(decodedOriginal);
// Use the secret key for decrypting file
File csvFile =
new File(
"encrypted_data.csv.enc");
FileInputStream csvIS = new FileInputStream(csvFile);
Cipher decipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(original, "AES");
decipher.init(Cipher.DECRYPT_MODE, keySpec);
byte[] csvOriginal = decipher.doFinal(IOUtils.toByteArray(csvIS));
String csvContents = new String(csvOriginal);
System.out.println(csvContents);
Before Java 1.8 (I think, somewhere around there) you are limited by the Java Unlimited Strength Policy for key sizes above 128-bits. This is the most likely cause of the exception you are getting.
Unfortunately this won't fix your code. openssl with the pass flag uses an insecure KDF named EVP_BytesToKey(). Java doesn't natively support this KDF. You don't want to use it anyway since it is insecure. Update the upstream code to use a better KDF like PBKDF2. There is native support for this in Java.
Further, you're using CBC mode in openssl and ECB mode in Java. And you aren't specifying an IV in openssl. I get the impression you didn't write the Java code yourself. You might benefit from taking the time to learn and research what is actually happening in your code and in the commands you are executing and you might be better equipped to solve the problem.

Port Java AES ECB encryption into UWP compatible C# Code

I am very new in the field of cryptography and have been stuck on this problem for two days.
I have a java code for AES/ECB encryption and I want my uwp app to use the same encryption technique but whatever I've tried so far gives different encryption results.
There are many answers on stackoverflow suggesting to use RijndaelManaged class, but this class is not available for UWP.
Here's java snippet
public string encrypt(String input, string key) {
SecretKeySpec skey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skey);
crypted = cipher.doFinal(input.getBytes("UTF-8"));
return Base64.encodeToString(crypted,Base64.NO_WRAP);
}
You need to use this answer to see how to encrypt/decrypt. However, you need a different (ECB so insecure) algorithm. So instead of the given CBC cipher mode you need to use AesEcbPkcs7 from the SymmetricAlgorithmNames.
Notes:
PKCS#7 is the same as PKCS#5 as used in the Java code, more info here;
you of course don't need to use an IV for ECB mode, so strip that out;
the UTF-8 encoding and base 64 decoding I'll leave out, it should be easy to do these encodings in any language/environment (the Convert and UTF8Encoding classes seem to be available for UWP apps).

Explanation to understand AES encryption code

I am creating a project to encrypt and decrypt a file. I have these two algorithms that work fine:
public static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
public static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static byte[] getRaw(String password_) throws Exception {
byte[] keyStart = password_.getBytes();
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
sr.setSeed(keyStart);
kgen.init(128, sr);
SecretKey skey = kgen.generateKey();
byte[] key = skey.getEncoded();
return key;
}
Now I need to explain how it works. Does it use a private key? Where is the key storage? Can anyone help me?
Note: see owlstead's answer for an excellent description of the flaws in your code example
Your encrypt() and decrypt() operations are performing AES encryption and decryption respectively, using Java's JCE libraries. A JCE provider will be selected to perform the actual cryptography - the provider chosen will be the first in the list of providers that offers an implementation of AES. You have defined the algorithm as only "AES", so the mode of operation and padding will be chosen by the provider. If you want to control this, use the form "AES/mode/padding" (see the docs for valid choices)
The getRaw method derives an AES key from a password. The raw bytes of the password provide the seed for a random number generator. The random number generator is then used to generate sufficient key material for a 128-bit AES key. A different password will produce a different seed, which should produce a different stream of random bytes and thus a different key. I suspect this approach is weakened by the lack of entropy present in most people's passwords, leading to a reduced key space and easier attacks.
There is no key storage in your example code. JCE keys are normally persisted using a KeyStore object and the storage mechanism is provider-dependent.
The above piece of code is a bunch of crap. Unfortunately it is frequently used as a code snippet for Android related code (Android code uses the same API as Java, so there is no need for an Android specific example, andt unfortunately it specifically fails on Android).
I'll explain the issues:
Using a SecureRandom as Password Based Key Derivation Function (PBKDF) is completely idiotic. The underlying implementation of the SecureRandom implementation may change. Furthermore, it is not specified by the SecureRandom that calling setSeed() as the first method will replace the seed; it may actually add the seed to the current state - and this is what certain newer android versions do.
Cipher.getInstance("AES") actually uses the provider defaults instead of specifying the mode of operation and padding mode for the given cipher. By default the Sun provider will use ECB mode which is not suitable for encrypting most data.
String.getBytes() - which is used for the password - returns the platform default encoding. Different platforms may have different default encodings. This means that different platforms will generate different keys.
Above code does not add a message authentication code (MAC or HMAC). This may lead to an attacker changing random ciphertext blocks, which leads to random plain text blocks. This may lead to loss of confidentiality as well if padding Oracle attacks apply.
It seems to me that you are a beginner in cryptography. Please use a higher level standard such as RNCryptor compatible code, or use a standard such as Cryptographic Message Syntax (CMS).

Decrypt Blowfish in Java (Generating a secret key in program)

My professor gave us a decryption assignment in which we were given a list of "encrypted" phrases and told to decrypt them. One of them is in blowfish. Me and one of my classmates have tried all the possible keys that he might use. Thus I was going to make a program in Java that would go through all possible keys decrypt the string and then write the decrypted message out to a file. Only problem is all the online tutorials that i can find on writing blowfish in Java have this interface SecretKey being read in from a file.
My question is how do you generate a SecretKey in a program?
This might help you:
byte[] key = getKey();
Cipher cipher = Cipher.getInstance("Blowfish");
SecretKeySpec keySpec = new SecretKeySpec(key, "Blowfish");
cipher.init(Cipher.DECRYPT_MODE, keySpec);
Here's the API you want to use. http://download.oracle.com/javase/6/docs/api/javax/crypto/spec/SecretKeySpec.html#SecretKeySpec%28byte%5b%5d,%20java.lang.String%29
Use a SecretKeySpec to generate a SecretKey using SecretKeyFactory.generate().

Duplicate Oracle DES encrypting in Java

I recently asked a question about Oracle Encryption. Along the way to finding a solution for myself I decided to move the encryption (well, obfuscation) to the application side for certain tasks.
My problem is that the database is already encrypting data a certain way and I need Java code to duplicate that functionality, so that text encrypted by one system can be decrypted by the other and vice versa.
I want the encryption to be compatible with what the DB was already doing but couldn't find the documentation that describes exactly what Oracle is doing. How do I replicate this in Java?
dbms_obfuscation_toolkit.DESEncrypt(
input_string => v_string,
key_string => key_string,
encrypted_string => encrypted_string );
RETURN UTL_RAW.CAST_TO_RAW(encrypted_string);
No matter what I try, it seems as if the Java DES encryption is different than Oracle's.
I found this works:
KeySpec ks = new DESKeySpec(new byte[] {'s','e','c','r','e','t','!','!'});
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
SecretKey sk = skf.generateSecret(ks);
Cipher c = Cipher.getInstance("DES/CBC/NoPadding");
IvParameterSpec ips = new IvParameterSpec(new byte[] {0,0,0,0,0,0,0,0});
c.init(Cipher.ENCRYPT, sk, ips);
// or
c.init(Cipher.DECRYPT, sk, ips);
The missing piece was the Initialization Vector (ips) which must be 8 zeros. When you use null in Java you get something different.
Using Java in the database would have been another approach that would (should!) have guarenteed that the code (and hence results) would be identical.

Categories

Resources