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 * Helper method for generating an AES key from a secret string. 076 * 077 * @param secret the secret string 078 * @return the AES key 079 */ 080 public static SecretKey generateAESKey(String secret) { 081 082 HKDFParameters params = HKDFParameters.defaultParameters(secret.getBytes(StandardCharsets.UTF_8)); 083 HKDFBytesGenerator keyGenerator = new HKDFBytesGenerator(new SHA256Digest()); 084 keyGenerator.init(params); 085 byte[] keyBytes = new byte[16]; 086 keyGenerator.generateBytes(keyBytes, 0, 16); 087 SecretKeySpec keySpec = new SecretKeySpec(keyBytes, AES); 088 return keySpec; 089 } 090 091 /** 092 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#addConfigurationParameter(java.lang.String, java.lang.String) 093 */ 094 public void addConfigurationParameter(String paramName, String paramValue) { 095 096 m_config.add(paramName, paramValue); 097 } 098 099 /** 100 * @see org.opencms.crypto.I_CmsTextEncryption#decrypt(java.lang.String) 101 */ 102 public String decrypt(String input) throws CmsEncryptionException { 103 104 byte[] encryptedBytes = BASE64.decode(input); 105 try { 106 Cipher cipher = Cipher.getInstance(AES); 107 cipher.init(Cipher.DECRYPT_MODE, m_key); 108 byte[] decData = cipher.doFinal(encryptedBytes); 109 String result = new String(decData, StandardCharsets.UTF_8); 110 return result; 111 } catch (Exception e) { 112 throw new CmsEncryptionException(e.getLocalizedMessage(), e); 113 } 114 } 115 116 /** 117 * @see org.opencms.crypto.I_CmsTextEncryption#encrypt(java.lang.String) 118 */ 119 public String encrypt(String input) throws CmsEncryptionException { 120 121 try { 122 Cipher cipher = Cipher.getInstance(AES); 123 cipher.init(Cipher.ENCRYPT_MODE, m_key); 124 byte[] encData = cipher.doFinal(input.getBytes(StandardCharsets.UTF_8)); 125 String lit = BASE64.encode(encData); 126 return lit; 127 } catch (Exception e) { 128 throw new CmsEncryptionException(e.getLocalizedMessage(), e); 129 } 130 } 131 132 /** 133 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#getConfiguration() 134 */ 135 public CmsParameterConfiguration getConfiguration() { 136 137 return m_config; 138 } 139 140 /** 141 * @see org.opencms.crypto.I_CmsTextEncryption#getName() 142 */ 143 public String getName() { 144 145 return m_name; 146 147 } 148 149 /** 150 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#initConfiguration() 151 */ 152 public void initConfiguration() { 153 154 // never called. 155 } 156 157 /** 158 * @see org.opencms.crypto.I_CmsTextEncryption#initialize(org.opencms.file.CmsObject) 159 */ 160 public void initialize(CmsObject cms) { 161 162 String secret = m_config.get(PARAM_SECRET); 163 if (secret == null) { 164 throw new IllegalArgumentException("Parameter 'secret' must be set for CmsAESTextEncryption!"); 165 } 166 m_key = generateAESKey(secret); 167 } 168 169 /** 170 * @see org.opencms.crypto.I_CmsTextEncryption#setName(java.lang.String) 171 */ 172 public void setName(String name) { 173 174 if (m_name != null) { 175 throw new IllegalStateException("Can't call setName twice!"); 176 } 177 m_name = name; 178 } 179 180}