/* * JBoss, Home of Professional Open Source * Copyright 2016 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.wildfly.security.util; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; import org.junit.Assert; import org.junit.Test; /** * Tests for PasswordBasedEncryptionUtil class. * @author <a href="mailto:pskopek@redhat.com">Peter Skopek</a> */ public class PasswordBasedEncryptionUtilTest { private static final String clearText = "Červenavý střizlíček a štebotavá žlůva ďobali ve sťavnatých ocúnech."; private static final String DEFAULT_PICKETBOX_ALGORITHM = "PBEWithMD5AndDES"; private static final String DEFAULT_PICKETBOX_INITIAL_KEY_MATERIAL = "somearbitrarycrazystringthatdoesnotmatter"; /** * Test pair of encrypt/decrypt methods with Base32/Base64 encodings as input/output. * @throws GeneralSecurityException when something goes wrong */ @Test public void testEncryptEncode() throws GeneralSecurityException { String[] algorithms = {"PBEWithHmacSHA1andAES_128","PBEWithHmacSHA256AndAES_128","PBEWithMD5AndDES"}; Alphabet[] alphabets = { Alphabet.Base64Alphabet.STANDARD, Alphabet.Base64Alphabet.PICKETBOX_COMPATIBILITY, Alphabet.Base64Alphabet.BCRYPT, Alphabet.Base64Alphabet.MOD_CRYPT, Alphabet.Base64Alphabet.MOD_CRYPT_LE, Alphabet.Base32Alphabet.STANDARD, }; for(String algorithm : algorithms) { for (Alphabet alphabet: alphabets) { doEncryptEncode(algorithm, "WHOLE", alphabet); doEncryptEncode(algorithm, "IV", alphabet); } } } private void doEncryptEncode(String algorithm, String transferAlgParams, Alphabet alphabet) throws GeneralSecurityException { String params = String.format("[algorithm=%s, transferAlgParams=%s]", algorithm, transferAlgParams); PasswordBasedEncryptionUtil pbeUtil1 = new PasswordBasedEncryptionUtil.Builder() .alphabet(alphabet) .password("ThisIsStrangeInitialKey") .salt("SALTsalt") .iteration(234) .keyAlgorithm(algorithm) .encryptMode().build(); PasswordBasedEncryptionUtil.Builder builder2 = new PasswordBasedEncryptionUtil.Builder() .password("ThisIsStrangeInitialKey") .salt("SALTsalt") .iteration(234) .alphabet(alphabet) .keyAlgorithm(algorithm) .decryptMode(); if ("WHOLE".equals(transferAlgParams)) { builder2.algorithmParameters(pbeUtil1.getAlgorithmParameters()); } else if ("IV".equals(transferAlgParams)) { builder2.iv(pbeUtil1.getEncodedIV()); } PasswordBasedEncryptionUtil pbeUtil2 = builder2.build(); String encodedSecret = pbeUtil1.encryptAndEncode(clearText.toCharArray()); Assert.assertNotNull("encodedSecret is supposed to be not null (" + params + ")", encodedSecret); char[] decrypted = pbeUtil2.decodeAndDecrypt(encodedSecret); Assert.assertNotNull("decrypted is supposed to be not null (" + params + ")", decrypted); Assert.assertArrayEquals("clearText should be equal decrypted (" + params + ")", clearText.toCharArray(), decrypted); } /** * Test pair of encrypt/decrypt methods with PBKDF2 key generating algorithm. * @throws GeneralSecurityException when something goes wrong */ @Test public void testPBKDF() throws GeneralSecurityException { String keyAlgorithm = "PBKDF2WithHmacSHA1"; String transformation = "PBEWithHmacSHA256AndAES_128"; String parameters = transformation; PasswordBasedEncryptionUtil pbeUtil1 = new PasswordBasedEncryptionUtil.Builder() .password("ThisIsStrangeInitialKey") .salt("SALTsalt".getBytes(StandardCharsets.UTF_8)) .iteration(234) .keyAlgorithm(keyAlgorithm) .keyLength(256) .transformation(transformation) .parametersAlgorithm(parameters) .cipherIteration(516) .cipherSalt("frosty11".getBytes(StandardCharsets.UTF_8)) .encryptMode() .build(); PasswordBasedEncryptionUtil.Builder builder2 = new PasswordBasedEncryptionUtil.Builder() .password("ThisIsStrangeInitialKey".toCharArray()) .salt("SALTsalt") .iteration(234) .keyAlgorithm(keyAlgorithm) .keyLength(256) .transformation(transformation) .parametersAlgorithm(parameters) .cipherIteration(516) .cipherSalt("frosty11") .decryptMode(); builder2.iv(pbeUtil1.getEncodedIV()); PasswordBasedEncryptionUtil pbeUtil2 = builder2.build(); String encodedSecret = pbeUtil1.encryptAndEncode(clearText.toCharArray()); Assert.assertNotNull("encodedSecret is supposed to be not null", encodedSecret); char[] decrypted = pbeUtil2.decodeAndDecrypt(encodedSecret); Assert.assertNotNull("decrypted is supposed to be not null", decrypted); Assert.assertArrayEquals("clearText should be equal decrypted", clearText.toCharArray(), decrypted); } /** * Test to check if PicketBox compatibility mode can produce and consume strings from PicketBox encoding. * * @throws Exception when something goes wrong */ @Test public void testPicketBoxCompatibility() throws Exception { final String secret1 = "secret_password"; final String pbGenerated1 = "1GhfMaq4jSY0.kFFU3QG4T"; // secret_password;12345678;230 checkPb(secret1, "12345678", 230, pbGenerated1); final String secret2 = "super_secret"; final String pbGenerated2 = "088WUKotOwu7VOS8xRj.Rr"; // super_secret;ASDF1234;123 checkPb(secret2, "ASDF1234", 123, pbGenerated2); } private void checkPb(String secret, String salt, int iteration, String pbGenerated) throws GeneralSecurityException { PasswordBasedEncryptionUtil encryptUtil = new PasswordBasedEncryptionUtil.Builder() .picketBoxCompatibility() .salt(salt) .iteration(iteration) .encryptMode() .build(); PasswordBasedEncryptionUtil decryptUtil = new PasswordBasedEncryptionUtil.Builder() .picketBoxCompatibility() .salt(salt) .iteration(iteration) .decryptMode() .build(); String encrypted = encryptUtil.encryptAndEncode(secret.toCharArray()); String crossDecrypted = new String(decryptUtil.decodeAndDecrypt(pbGenerated)); String decrypted = new String(decryptUtil.decodeAndDecrypt(encrypted)); Assert.assertTrue("Elytron in PB compatible mode failed", decrypted.equals(secret)); Assert.assertTrue("PicketBox encrypted, Elytron decrypted in compatible mode, failed", crossDecrypted.equals(secret)); Assert.assertTrue("Elytron in compatible mode encrypted, PicketBox encrypted must be the same", pbGenerated.equals(encrypted)); } }