001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.security; 020 021import java.util.Random; 022 023import lucee.runtime.crypt.BinConverter; 024import lucee.runtime.crypt.BlowfishCBC; 025import lucee.runtime.crypt.BlowfishECB; 026import lucee.runtime.crypt.SHA1; 027 028/** 029 * support class for easy string encryption with the Blowfish algorithm, 030 * now in CBC mode with a SHA-1 key setup and correct padding 031 */ 032public final class SerialDecoder { 033 034 BlowfishCBC m_bfish; 035 036 037 038 // one random generator for all simple callers... 039 040 static Random m_rndGen; 041 042 043 044 // ...and created early 045 046 static { 047 048 m_rndGen = new Random(); 049 050 }; 051 052 053 054 055 056 057 058 /** 059 060 * constructor to set up a string as the key (oversized password will be cut) 061 062 * @param sPassword the password (treated as a real unicode array) 063 064 */ 065 066 public SerialDecoder(String sPassword) { 067 068 069 070 // hash down the password to a 160bit key 071 072 SHA1 hasher = new SHA1(); 073 074 hasher.update(sPassword); 075 076 hasher.finalize(); 077 078 079 080 // setup the encryptor (use a dummy IV) 081 082 m_bfish = new BlowfishCBC(hasher.getDigest(), 0); 083 084 hasher.clear(); 085 086 }; 087 088 /** 089 090 * decrypts a hexbin string (handling is case sensitive) 091 092 * @param sCipherText hexbin string to decrypt 093 094 * @return decrypted string (null equals an error) 095 096 */ 097 098 public String decrypt(String sCipherText) { 099 100 101 102 // get the number of estimated bytes in the string (cut off broken blocks) 103 104 int nLen = (sCipherText.length() >> 1) & ~7; 105 106 107 108 // does the given stuff make sense (at least the CBC IV)? 109 110 if (nLen < BlowfishECB.BLOCKSIZE) 111 112 return null; 113 114 115 116 // get the CBC IV 117 118 byte[] cbciv = new byte[BlowfishECB.BLOCKSIZE]; 119 120 int nNumOfBytes = BinConverter.binHexToBytes(sCipherText, 121 122 cbciv, 123 124 0, 125 126 0, 127 128 BlowfishECB.BLOCKSIZE); 129 130 if (nNumOfBytes < BlowfishECB.BLOCKSIZE) 131 132 return null; 133 134 // (got it) 135 136 m_bfish.setCBCIV(cbciv); 137 138 139 140 // something left to decrypt? 141 142 nLen -= BlowfishECB.BLOCKSIZE; 143 144 if (nLen == 0) 145 146 return ""; 147 148 149 150 // get all data bytes now 151 152 byte[] buf = new byte[nLen]; 153 154 nNumOfBytes = BinConverter.binHexToBytes(sCipherText, 155 156 buf, 157 158 BlowfishECB.BLOCKSIZE * 2, 159 160 0, 161 162 nLen); 163 164 165 166 // we cannot accept broken binhex sequences due to padding 167 168 // and decryption 169 170 if (nNumOfBytes < nLen) 171 172 return null; 173 174 175 176 // decrypt the buffer 177 178 m_bfish.decrypt(buf); 179 180 181 182 // get the last padding byte 183 184 int nPadByte = buf[buf.length - 1] & 0x0ff; 185 186 // ( try to get all information if the padding doesn't seem to be correct) 187 188 if ((nPadByte > 8) || (nPadByte < 0)) 189 190 nPadByte = 0; 191 192 193 194 // calculate the real size of this message 195 196 nNumOfBytes -= nPadByte; 197 198 if (nNumOfBytes < 0) 199 200 return ""; 201 202 203 204 // success 205 206 return BinConverter.byteArrayToUNCString(buf, 0, nNumOfBytes); 207 208 }; 209 210 211 212 213 214 /** 215 216 * destroys (clears) the encryption engine, 217 218 * after that the instance is not valid anymore 219 220 */ 221 222 public void destroy() { 223 224 m_bfish.cleanUp(); 225 226 }; 227 228}; 229 230