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.crypt; 020 021import lucee.commons.lang.StringUtil; 022 023public final class CFMXCompat { 024 025 public static final String ALGORITHM_NAME = "cfmx_compat"; 026 027 028 private String m_Key; 029 private int m_LFSR_A = 0x13579bdf; 030 private int m_LFSR_B = 0x2468ace0; 031 private int m_LFSR_C = 0xfdb97531; 032 private int m_Mask_A = 0x80000062; 033 private int m_Mask_B = 0x40000020; 034 private int m_Mask_C = 0x10000002; 035 private int m_Rot0_A = 0x7fffffff; 036 private int m_Rot0_B = 0x3fffffff; 037 private int m_Rot0_C = 0xfffffff; 038 private int m_Rot1_A = 0x80000000; 039 private int m_Rot1_B = 0xc0000000; 040 private int m_Rot1_C = 0xf0000000; 041 042 043 public byte[] transformString(String key, byte inBytes[]) { 044 setKey(key); 045 int length = inBytes.length; 046 byte outBytes[] = new byte[length]; 047 for(int i = 0; i < length; i++) { 048 outBytes[i] = transformByte(inBytes[i]); 049 } 050 return outBytes; 051 } 052 053 private byte transformByte(byte target) { 054 byte crypto = 0; 055 int b = m_LFSR_B & 1; 056 int c = m_LFSR_C & 1; 057 for(int i = 0; i < 8; i++) { 058 if(0 != (m_LFSR_A & 1)) { 059 m_LFSR_A = m_LFSR_A ^ m_Mask_A >>> 1 | m_Rot1_A; 060 if(0 != (m_LFSR_B & 1)){ 061 m_LFSR_B = m_LFSR_B ^ m_Mask_B >>> 1 | m_Rot1_B; 062 b = 1; 063 } 064 else{ 065 m_LFSR_B = m_LFSR_B >>> 1 & m_Rot0_B; 066 b = 0; 067 } 068 } 069 else{ 070 m_LFSR_A = m_LFSR_A >>> 1 & m_Rot0_A; 071 if(0 != (m_LFSR_C & 1)) { 072 m_LFSR_C = m_LFSR_C ^ m_Mask_C >>> 1 | m_Rot1_C; 073 c = 1; 074 } 075 else{ 076 m_LFSR_C = m_LFSR_C >>> 1 & m_Rot0_C; 077 c = 0; 078 } 079 } 080 crypto = (byte)(crypto << 1 | b ^ c); 081 } 082 target ^= crypto; 083 return target; 084 } 085 086 private void setKey(String key) { 087 int i = 0; 088 m_Key = key; 089 if(StringUtil.isEmpty(key)) key = "Default Seed"; 090 char Seed[] = new char[key.length() >= 12 ? key.length() : 12]; 091 m_Key.getChars(0, m_Key.length(), Seed, 0); 092 int originalLength = m_Key.length(); 093 for(i = 0; originalLength + i < 12; i++) 094 Seed[originalLength + i] = Seed[i]; 095 096 for(i = 0; i < 4; i++) { 097 m_LFSR_A = (m_LFSR_A <<= 8) | Seed[i + 4]; 098 m_LFSR_B = (m_LFSR_B <<= 8) | Seed[i + 4]; 099 m_LFSR_C = (m_LFSR_C <<= 8) | Seed[i + 4]; 100 } 101 if(0 == m_LFSR_A)m_LFSR_A = 0x13579bdf; 102 if(0 == m_LFSR_B)m_LFSR_B = 0x2468ace0; 103 if(0 == m_LFSR_C)m_LFSR_C = 0xfdb97531; 104 } 105 106 107 /** 108 * returns true if the passed value is empty or is CFMX_COMPAT 109 */ 110 public static boolean isCfmxCompat( String algorithm ) { 111 112 if ( StringUtil.isEmpty( algorithm, true ) ) 113 return true; 114 115 return algorithm.equalsIgnoreCase( CFMXCompat.ALGORITHM_NAME ); 116 } 117}