Hello,
Through several articles, I would like present the cryptographic mechanisms, types of keys, certificate, types of algorithms …etc:
- PRESENTATION : Concepts of Cryptography (concepts, types of keys symmetric/asymmetric, …)
- The principles of SSL
- The principles of Signature and Certificate
- The principles of Hardware Security Module HSM
- Encoding with base64, base64url, rfc-4648
- Encryption with Blowfish (Anonymization)
- Encryption with AES/CBC, AES/EBC (Encryption of files)
- Encryption with PBEWithMD5AndDES (Encryption of files)
- Encryption with RSA (asymmetric keys private and public)
- KeyStore, JCEKS, SecretKey, PrivateKey, PublicKey, Certificate
- Example, Use of SecretKey, PrivateKey, PublicKey, CSV file (CryptoTools, GenericObfuscationFile)
Encryption with PBEWithMD5AndDES (Encryption of files)
- Presentation
The algorithms PBEWith are password based encryption. To perform password-based encryption, a random salt sequence in order to prevent dictionary attacks, and key (AES or DES) generated from a given password and salt are necessary.
There are several possible variations, but a common scheme is as follows:- append the password to the salt, and also append a counter, which will start at 1 in order to create a complex sequence;
- calculate a secure hash of the previous created;
- then repeat the process for some number of iterations, each time forming the new sequence to be hashed from the output of the previous hash, and appending the salt and incremented counter.
The PBEWithMD5AndDES combines all the benefits of slow, insecure 56-bit encryption (DES-CBC) with an insecure hash function (MD5).
However, there are others algorithms: PBEWithSHA1AndRC2_40, PBEWithMD5AndTripleDES …etc.
- Tools
As described in the post http://www.javablog.fr/javacrypto-encryption-list-providers-and-algo.html, we could find the available algorithm, tools (cipher, generator) in each reachable provider. In our case, we use the SunJCE Provider which is enough (http://javasearch.developpez.com/sun/j2se/1.6.0/technotes/guides/security/SunProviders.html#SunJCEProvider)
The following algorithms are available in the SunJCE provider:
[4] SunJCE v1.6: SunJCE Provider (implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, Diffie-Hellman, HMAC)
- AlgorithmParameters.PBEWithMD5AndDES -> com.sun.crypto.provider.PBEParameters
aliases: [OID.1.2.840.113549.1.5.3, 1.2.840.113549.1.5.3]
- Cipher.PBEWithMD5AndDES -> com.sun.crypto.provider.PBEWithMD5AndDESCipher
aliases: [OID.1.2.840.113549.1.5.3, 1.2.840.113549.1.5.3]
- SecretKeyFactory.PBEWithMD5AndDES -> com.sun.crypto.provider.PBEKeyFactory$PBEWithMD5AndDES
aliases: [OID.1.2.840.113549.1.5.3, 1.2.840.113549.1.5.3, PBE]
- Example : Encryption of data/file via the algorithme “PBEWithMD5AndDES”
Details:
* Encryption : PBEWithMD5AndDES AND [Base64 and replacing of ‘+’ by ‘-‘, ‘/’ by ‘_’ and removing the ‘=’ at the end]
* Decryption : [Base64 and replacing of ‘-‘ by ‘+’, ‘_’ by ‘/’ and adding at the end a ‘=’] AND PBEWithMD5AndDES
… Code for the generation of Complex Password due to Secret Key Value :private static final String ALGORITHM = "PBEWithMD5AndDES"; // Iteration count private static final int ITERATION_COUNT = 20; private static final String UNICODE_FORMAT = "UTF-8"; public static byte[] generateComplexPasswordOrSecretKeyValue() throws Exception { byte[] passwordOrKeyValue = RandomStringUtils.randomAscii(16).getBytes(UNICODE_FORMAT); KeySpec keySpec = new PBEKeySpec(new String(passwordOrKeyValue).toCharArray()); SecretKey secretKey = SecretKeyFactory.getInstance(ALGORITHM).generateSecret(keySpec); return secretKey.getEncoded(); }
… Code for the SALT creation via Secure Random Number Generator and an empty 8byte array:
public static byte[] generateSALT() throws Exception { byte[] saltValue = null; //saltValue = { (byte) 0xc8, (byte) 0x73, (byte) 0x61, (byte) 0x1d, (byte) 0x1a, (byte) 0xf2, (byte) 0xa8, (byte) 0x99, }; //saltValue = "HOJAvaLu".getBytes(UNICODE_FORMAT); { SecureRandom r = new SecureRandom(); byte[] newSeed = r.generateSeed(8); r.setSeed(newSeed); saltValue = new byte[8]; r.nextBytes(saltValue); } return saltValue; }
… Encryption/ciphering code :
char[] passwordOrKeyValue = ....; byte[] content = ....; byte[] salt = ....; SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM); // Create PBE parameter set with SALT and COUNTER PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, ITERATION_COUNT); // Create SecretKey PBEKeySpec pbeKeySpec = new PBEKeySpec(passwordOrKeyValue); SecretKey key = keyFactory.generateSecret(pbeKeySpec); // Create PBE Cipher Cipher pbeCipher = Cipher.getInstance(ALGORITHM); // Initialize PBE Cipher with key, PBE parameter set pbeCipher.init(Cipher.ENCRYPT_MODE, key, pbeParamSpec); byte[] encryptedContent = pbeCipher.doFinal(content); return base64Encode(encryptedContent).getBytes(UNICODE_FORMAT);
… Decryption/deciphering code :
char[] passwordOrKeyValue = ....; byte[] content = ....; byte[] salt = ....; SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM); // Create PBE parameter set with SALT and COUNTER PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, ITERATION_COUNT); // Create SecretKey PBEKeySpec pbeKeySpec = new PBEKeySpec(passwordOrKeyValue); SecretKey key = keyFactory.generateSecret(pbeKeySpec); // Create PBE Cipher Cipher pbeCipher = Cipher.getInstance(ALGORITHM); // Initialize PBE Cipher with key, PBE parameter set pbeCipher.init(Cipher.DECRYPT_MODE, key, pbeParamSpec); return pbeCipher.doFinal(base64Decode(new String(content)));
…here the main method with PBEWithMD5AndDES encryption and Base64 encoding:
public static void main(String[] args) { try{ byte[] passwordOrKeyValue = EncryptionPBEWithMD5AndDES.generateComplexPasswordOrSecretKeyValue(); System.out.println("Generation of complex password : "+new String(passwordOrKeyValue)); byte[] salt = EncryptionPBEWithMD5AndDES.generateSALT(); System.out.println("SALT used: "+new String(salt)); aEncryptFile(passwordOrKeyValue, salt); bDecryptFile(passwordOrKeyValue, salt); }catch(Throwable th){ th.printStackTrace(); } } public static void aEncryptFile(byte[] keyValue, byte[] salt) throws Exception { try{ File sourceFile = new File(System.getProperty("user.dir") + "/resources/pdf_with_text.pdf"); System.out.println("Size of source file (to encrypt): " + sourceFile.length()); byte[] content = Files.readAllBytes(sourceFile.toPath()); // byte[] encryptContent = EncryptionPBEWithMD5AndDES.encrypt(new String(keyValue).toCharArray(), content, salt); // File targetFile = new File(System.getProperty("user.dir") + "/resources/pdf_with_text_encrypted_pbe.pdf"); if(targetFile.exists()){ targetFile.delete(); } Files.write(targetFile.toPath(), encryptContent, StandardOpenOption.CREATE_NEW); System.out.println("Size of encrypted file : " + targetFile.length()); } catch(Exception e){ e.printStackTrace(); } } public static void bDecryptFile(byte[] keyValue, byte[] salt) throws Exception { try { byte[] encryptContent = Files.readAllBytes(new File(System.getProperty("user.dir") + "/resources/pdf_with_text_encrypted_pbe.pdf").toPath()); System.out.println("Size of encrypted file (to decrypt): " + encryptContent.length); byte[] decryptContent = EncryptionPBEWithMD5AndDES.decrypt(new String(keyValue).toCharArray(), encryptContent, salt); File targetFile = new File(System.getProperty("user.dir") + "/resources/pdf_with_text_decrypted_pbe.pdf"); if(targetFile.exists()){ targetFile.delete(); } Files.write(targetFile.toPath(), decryptContent, StandardOpenOption.CREATE_NEW); System.out.println("Size of decrypted file : " + targetFile.length()); }catch (Exception e){ e.printStackTrace(); } }
…here the outputs:
Generation of complex password : %/%\eTx{}E,SG)l:
SALT used: 5vëE“Î
Size of source file (to encrypt): 882
Size of encrypted file : 1214
Size of encrypted file (to decrypt): 1214
Size of decrypted file : 882
Note: the source file “/resources/pdf_with_text.pdf” and the file resulting of encryption/decryption “/resources/pdf_with_text_decrypted_pbe.pdf” are equals.
Sources : PBEWithMD5AndDES.zip
That’s all!!!
Huseyin OZVEREN