5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Copyright (c) 2007 Sun Microsystems Inc. All Rights Reserved
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The contents of this file are subject to the terms
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * of the Common Development and Distribution License
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * (the License). You may not use this file except in
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * compliance with the License.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * You can obtain a copy of the License at
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * See the License for the specific language governing
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * permission and limitations under the License.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * When distributing Covered Code, include this CDDL
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Header Notice in each file and include the License file
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If applicable, add the following below the CDDL Header,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * with the fields enclosed by brackets [] replaced by
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * your own identifying information:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * $Id: JSSEncryption.java,v 1.3 2009/01/23 22:16:26 beomsuk Exp $
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.mozilla.jss.crypto.EncryptionAlgorithm;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport com.sun.identity.shared.configuration.SystemPropertiesManager;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * This class uses JSS symmetric algorithm for string encryption/decryption.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The encrypted string contains BASE64 Characters as specified
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * in RFC1521.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The format of the encoded byte before BASE64 encoding is
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * byte[0] = crypt version number. This version is 1.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * byte[1]=keyGenAlg
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * bype[2]=EncrytionAlg
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * byte[3-10]=IV for encryption/decryption
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The rest is the encoded bytes.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * This is initially intended to replace SessionID
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * encryption/decryption (xor). And is pulled to the DAI space at the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * last minutes. Since the requirement and restrictions are different,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * It needs adjustment later.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * for furtue "enhancement" (adopted form the old Password.java):
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * 1. Use an array of pins to be randomly picked. Add the index as a
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * prefix of the encrypted string.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Aravindan's thought:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * 1. From the password, generate the key multiple times, put the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * number of times as a prefix of the encrypted string.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * 2. Random generated a pwd and build a key from it. Put the pwd
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * encrypted somehow as a prefix of the encrypted string.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * 3. put pwd in a class and embeded in a jar file, so that it's not
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * in "plain text", somewhat.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The class can be replaced at installation time by taking a
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * pwd from user and dynamically created and replaced in the jar.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * (mzhao: And it should be able to be replaced by customer
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * periodically. However if it's used for password encryption. The
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * encrypted version of pwds should be changed simultaneously.)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * mzhao thought:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * 1. There is known problem in this framework that we need to store
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * the password securely in some way. Hardcoding it is not considered
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * secure, putting it in a file is not either.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * 2. Client Auth can be used for web based SSO.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Borrowed from CMS:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * 1. A storage cert can be created to encrypt/decrypt the pwd.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * 2. A password cache can be used to store all passwords, such as
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * puser, daiuser, amadmin password, and ssl password. A SSO
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * password is used to encryt them. When server restarts, this SSO
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * password must be asked.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * 3. A watchdog may be needed to auto restart the server.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @author mzhao
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @version $Revision: 1.3 $, $Date: 2009/01/23 22:16:26 $
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterpublic class JSSEncryption implements AMEncryption, ConfigurableKey {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static String DEFAULT_KEYGEN_ALG = "PBE_MD5_DES_CBC";
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static String DEFAULT_ENCYPTION_ALG = "DES_CBC_PAD";
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static Debug debug = Debug.getInstance("amJSS");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster static String method = "JSSEncryption.initialize";
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster CryptoManager cm = CryptoManager.getInstance();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /* if FIPS is enabled, configure only FIPS ciphersuites */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster "PBE_SHA1_DES3_CBC",
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster "PBE_MD2_DES_CBC",
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster "PBE_MD5_DES_CBC",
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster "PBE_SHA1_DES_CBC",
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster "PBE_SHA1_RC2_128_CBC",
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster "PBE_SHA1_RC2_40_CBC",
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster "PBE_SHA1_RC4_128",
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster "PBE_SHA1_RC4_40"};
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static int NUM_KEYGEN_ALG = KEYGEN_ALGS.length;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static final String[] ENCRYPTION_ALGS = {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster "DES3_CBC_PAD",
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster "DES_CBC_PAD",
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static int NUM_ENCRYPTION_ALG = ENCRYPTION_ALGS.length;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } catch (CryptoManager.NotInitializedException ex) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Default constructor
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // This crypto token has to support encryption algorithm
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // and all the key generation algorithms in KEYGEN_ALGS.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // CryptoManager returns "Internal Key Storage Token" at least.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster CryptoManager cm = CryptoManager.getInstance();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster Enumeration e = cm.getTokensSupportingAlgorithm(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster CryptoToken tok = (CryptoToken) e.nextElement();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster boolean foundToken = true;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (!tok.doesAlgorithm(getKeyGenAlg(KEYGEN_ALGS[i]))) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Sets password-based key to use
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public void setPassword(String password) throws Exception {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster initSymmetricKeysAndInitializationVectors(password);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private void initSymmetricKeysAndInitializationVectors(String password) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ivParamSpecs = new IVParameterSpec[NUM_KEYGEN_ALG];
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster byte salt[] = {0x01, 0x01, 0x01, 0x01, 0x01,0x01, 0x01, 0x01};
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster Password pass = new Password(password.toCharArray());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster PBEAlgorithm keyAlg = getKeyGenAlg(KEYGEN_ALGS[i]);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster KeyGenerator kg = mToken.getKeyGenerator(keyAlg);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster PBEKeyGenParams kgp = new PBEKeyGenParams(pass, salt, 5);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ivParamSpecs[i] = new IVParameterSpec(kg.generatePBE_IV());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.message("Created symKey successfully : " +
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.error("Failed creating symKey : " + KEYGEN_ALGS[i], e);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private SymmetricKey getSymmetricKey(int type) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private IVParameterSpec getIVParameterSpec(int type) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>Encrypt a String.</p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param clearText The string to be encoded.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return The encoded string.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>Decrypt a String.</p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param encoded The string to be decoded.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return The decoded string.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <p>Encrypt a String.</p>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param clearText The string to be encoded.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return The encoded string.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (clearText == null || clearText.length == 0)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster EncryptionAlgorithm encAlg = getEncryptionAlg(encAlgString);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster Cipher cipher = mToken.getCipherContext(encAlg);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // bug in JSS: msg in stdout.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //secureRandom.nextBytes(iv);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster IVParameterSpec ivSpec = getIVParameterSpec(i);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Decode an encoded string
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param encoded The encoded string.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return The decoded string.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster "In decode string: unsupported version:"+share[0]);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // get the alg from the string
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // get the encrypted data
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((int)type[1] < 0 && (int)type[1] >= NUM_ENCRYPTION_ALG){
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.error("In decode string: unsupported encryption bit:"
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster getEncryptionAlg(ENCRYPTION_ALGS[(int)type[1]]);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster Cipher cipher = mToken.getCipherContext(encAlg);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((int)type[0] < 0 && (int)type[0] >= NUM_KEYGEN_ALG){
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster "In decode string: unsupported keygen bit:"
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster SymmetricKey sk = getSymmetricKey((int)type[0]);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster IVParameterSpec ivSpec = getIVParameterSpec((int)type[0]);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.error("in decoding string " + encoded, e);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static byte[] addPrefix(byte type[], byte iv[], byte share[]) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static int getKeyGenByte(String algName) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // return the default
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static PBEAlgorithm getKeyGenAlg(String algName) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else if (algName.equals("PBE_MD2_DES_CBC")) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else if (algName.equals("PBE_MD5_DES_CBC")) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else if (algName.equals("PBE_SHA1_DES_CBC")) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else if (algName.equals("PBE_SHA1_RC2_128_CBC")) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else if (algName.equals("PBE_SHA1_RC2_40_CBC")) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else if (algName.equals("PBE_SHA1_RC4_128")) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else if (algName.equals("PBE_SHA1_RC4_40")) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.message("keyGen algorithm is not valid.");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static int getEncryptionByte(String algName) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.error("Encryption algorithm is not valid.");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // return the default
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static EncryptionAlgorithm getEncryptionAlg(String algName) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.message("Encryption algorithm is not valid.");