001    package railo.runtime.crypt;
002    
003    import railo.commons.lang.StringUtil;
004    
005    public final class CFMXCompat {
006    
007        private String m_Key;
008        private int m_LFSR_A = 0x13579bdf;
009        private int m_LFSR_B = 0x2468ace0;
010        private int m_LFSR_C = 0xfdb97531;
011        private int m_Mask_A = 0x80000062;
012        private int m_Mask_B = 0x40000020;
013        private int m_Mask_C = 0x10000002;
014        private int m_Rot0_A = 0x7fffffff;
015        private int m_Rot0_B = 0x3fffffff;
016        private int m_Rot0_C = 0xfffffff;
017        private int m_Rot1_A = 0x80000000;
018        private int m_Rot1_B = 0xc0000000;
019        private int m_Rot1_C = 0xf0000000;
020        
021    
022        public byte[] transformString(String key, byte inBytes[]) {
023            setKey(key);
024            int length = inBytes.length;
025            byte outBytes[] = new byte[length];
026            for(int i = 0; i < length; i++) {
027                outBytes[i] = transformByte(inBytes[i]);
028            }
029            return outBytes;
030        }
031    
032        private byte transformByte(byte target) {
033            byte crypto = 0;
034            int b = m_LFSR_B & 1;
035            int c = m_LFSR_C & 1;
036            for(int i = 0; i < 8; i++) {
037                if(0 != (m_LFSR_A & 1)) {
038                    m_LFSR_A = m_LFSR_A ^ m_Mask_A >>> 1 | m_Rot1_A;
039                    if(0 != (m_LFSR_B & 1)){
040                        m_LFSR_B = m_LFSR_B ^ m_Mask_B >>> 1 | m_Rot1_B;
041                        b = 1;
042                    } 
043                    else{
044                        m_LFSR_B = m_LFSR_B >>> 1 & m_Rot0_B;
045                        b = 0;
046                    }
047                } 
048                else{
049                    m_LFSR_A = m_LFSR_A >>> 1 & m_Rot0_A;
050                    if(0 != (m_LFSR_C & 1)) {
051                        m_LFSR_C = m_LFSR_C ^ m_Mask_C >>> 1 | m_Rot1_C;
052                        c = 1;
053                    } 
054                    else{
055                        m_LFSR_C = m_LFSR_C >>> 1 & m_Rot0_C;
056                        c = 0;
057                    }
058                }
059                crypto = (byte)(crypto << 1 | b ^ c);
060            }
061            target ^= crypto;
062            return target;
063        }
064    
065        private void setKey(String key) {
066            int i = 0;
067            m_Key = key;
068            if(StringUtil.isEmpty(key)) key = "Default Seed";
069            char Seed[] = new char[key.length() >= 12 ? key.length() : 12];
070            m_Key.getChars(0, m_Key.length(), Seed, 0);
071            int originalLength = m_Key.length();
072            for(i = 0; originalLength + i < 12; i++)
073                Seed[originalLength + i] = Seed[i];
074    
075            for(i = 0; i < 4; i++) {
076                m_LFSR_A = (m_LFSR_A <<= 8) | Seed[i + 4];
077                m_LFSR_B = (m_LFSR_B <<= 8) | Seed[i + 4];
078                m_LFSR_C = (m_LFSR_C <<= 8) | Seed[i + 4];
079            }
080            if(0 == m_LFSR_A)m_LFSR_A = 0x13579bdf;
081            if(0 == m_LFSR_B)m_LFSR_B = 0x2468ace0;
082            if(0 == m_LFSR_C)m_LFSR_C = 0xfdb97531;
083        }
084    }