001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.crypto; 029 030import org.opencms.configuration.CmsParameterConfiguration; 031import org.opencms.file.CmsObject; 032import org.opencms.main.CmsLog; 033 034import java.nio.charset.StandardCharsets; 035 036import javax.crypto.Cipher; 037import javax.crypto.SecretKey; 038import javax.crypto.spec.SecretKeySpec; 039 040import org.apache.commons.logging.Log; 041 042import org.bouncycastle.crypto.digests.SHA256Digest; 043import org.bouncycastle.crypto.generators.HKDFBytesGenerator; 044import org.bouncycastle.crypto.params.HKDFParameters; 045 046import com.google.common.io.BaseEncoding; 047 048/** 049 * Default text encryption class using AES, where the encryption key is generated from a string passed in as a parameter. 050 */ 051public class CmsAESTextEncryption implements I_CmsTextEncryption { 052 053 /** The name of the algorithm. */ 054 public static final String AES = "AES"; 055 056 /** URL parameter safe base64 encoder. */ 057 public static final BaseEncoding BASE64 = BaseEncoding.base64Url().withPadChar('.'); 058 059 /** The configuration parameter for configuring the secret. */ 060 public static final String PARAM_SECRET = "secret"; 061 062 /** Logger instance for this class. */ 063 private static final Log LOG = CmsLog.getLog(CmsAESTextEncryption.class); 064 065 /** The parameter configuration. */ 066 private CmsParameterConfiguration m_config = new CmsParameterConfiguration(); 067 068 /** The key used for encryption / decryption. */ 069 private SecretKey m_key; 070 071 /** The name under which this is registered. */ 072 private String m_name; 073 074 /** 075 * Default constructor (used when instantiated automatically during OpenCms configuration). 076 */ 077 public CmsAESTextEncryption() {} 078 079 /** 080 * Constructor used to manually, conveniently create a new encryption object with a given secret. 081 * 082 * <p>When using this constructor, it is not necessary to call initialize() to make the object usable. 083 * 084 * @param secret the secret used to generate the key 085 */ 086 public CmsAESTextEncryption(String secret) { 087 088 m_key = generateAESKey(secret); 089 } 090 091 /** 092 * Helper method for generating an AES key from a secret string. 093 * 094 * @param secret the secret string 095 * @return the AES key 096 */ 097 public static SecretKey generateAESKey(String secret) { 098 099 HKDFParameters params = HKDFParameters.defaultParameters(secret.getBytes(StandardCharsets.UTF_8)); 100 HKDFBytesGenerator keyGenerator = new HKDFBytesGenerator(new SHA256Digest()); 101 keyGenerator.init(params); 102 byte[] keyBytes = new byte[16]; 103 keyGenerator.generateBytes(keyBytes, 0, 16); 104 SecretKeySpec keySpec = new SecretKeySpec(keyBytes, AES); 105 return keySpec; 106 } 107 108 /** 109 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#addConfigurationParameter(java.lang.String, java.lang.String) 110 */ 111 public void addConfigurationParameter(String paramName, String paramValue) { 112 113 m_config.add(paramName, paramValue); 114 } 115 116 /** 117 * @see org.opencms.crypto.I_CmsTextEncryption#decrypt(java.lang.String) 118 */ 119 public String decrypt(String input) throws CmsEncryptionException { 120 121 byte[] encryptedBytes = BASE64.decode(input); 122 try { 123 Cipher cipher = Cipher.getInstance(AES); 124 cipher.init(Cipher.DECRYPT_MODE, m_key); 125 byte[] decData = cipher.doFinal(encryptedBytes); 126 String result = new String(decData, StandardCharsets.UTF_8); 127 return result; 128 } catch (Exception e) { 129 throw new CmsEncryptionException(e.getLocalizedMessage(), e); 130 } 131 } 132 133 /** 134 * @see org.opencms.crypto.I_CmsTextEncryption#encrypt(java.lang.String) 135 */ 136 public String encrypt(String input) throws CmsEncryptionException { 137 138 try { 139 Cipher cipher = Cipher.getInstance(AES); 140 cipher.init(Cipher.ENCRYPT_MODE, m_key); 141 byte[] encData = cipher.doFinal(input.getBytes(StandardCharsets.UTF_8)); 142 String lit = BASE64.encode(encData); 143 return lit; 144 } catch (Exception e) { 145 throw new CmsEncryptionException(e.getLocalizedMessage(), e); 146 } 147 } 148 149 /** 150 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#getConfiguration() 151 */ 152 public CmsParameterConfiguration getConfiguration() { 153 154 return m_config; 155 } 156 157 /** 158 * @see org.opencms.crypto.I_CmsTextEncryption#getName() 159 */ 160 public String getName() { 161 162 return m_name; 163 164 } 165 166 /** 167 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#initConfiguration() 168 */ 169 public void initConfiguration() { 170 171 // never called. 172 } 173 174 /** 175 * @see org.opencms.crypto.I_CmsTextEncryption#initialize(org.opencms.file.CmsObject) 176 */ 177 public void initialize(CmsObject cms) { 178 179 String secret = m_config.get(PARAM_SECRET); 180 if (secret == null) { 181 throw new IllegalArgumentException("Parameter 'secret' must be set for CmsAESTextEncryption!"); 182 } 183 m_key = generateAESKey(secret); 184 } 185 186 /** 187 * @see org.opencms.crypto.I_CmsTextEncryption#setName(java.lang.String) 188 */ 189 public void setName(String name) { 190 191 if (m_name != null) { 192 throw new IllegalStateException("Can't call setName twice!"); 193 } 194 m_name = name; 195 } 196 197}