1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.ninjasoft.magiccodes.plugins;
18
19
20 /***
21 * Encodes data as BASE64
22 * @author enigma
23 */
24 public class Base64Encoder implements Plugin {
25 public String getName() {
26 return "BASE-64 Encoder";
27 }
28
29 public String getDescription() {
30 return "Encodes data as BASE-64 text";
31 }
32
33 public boolean usesKey() {
34 return false;
35 }
36
37 public boolean isInformational() {
38 return false;
39 }
40
41 /***
42 * Byte value that maps to 'a' in Base64 encoding
43 */
44 final static int LOWER_CASE_A_VALUE = 26;
45
46 /***
47 * Byte value that maps to '0' in Base64 encoding
48 */
49 final static int ZERO_VALUE = 52;
50
51 /***
52 * Byte value that maps to '+' in Base64 encoding
53 */
54 final static int PLUS_VALUE = 62;
55
56 /***
57 * Byte value that maps to '/' in Base64 encoding
58 */
59 final static int SLASH_VALUE = 63;
60
61 /***
62 * Bit mask for one character worth of bits in Base64 encoding.
63 * Equivalent to binary value 111111b.
64 */
65 private final static int SIX_BIT_MASK = 63;
66
67 /***
68 * Convert a byte between 0 and 63 to its Base64 character equivalent
69 * @param b Byte value to be converted
70 * @return Base64 char value
71 */
72 private char mapByteToChar( byte b ) {
73 if ( b < LOWER_CASE_A_VALUE ) {
74 return (char)( 'A' + b );
75 }
76
77 if ( b < ZERO_VALUE ) {
78 return (char)( 'a' + ( b - LOWER_CASE_A_VALUE ) );
79 }
80
81 if ( b < PLUS_VALUE ) {
82 return (char)( '0' + ( b - ZERO_VALUE ) );
83 }
84
85 if ( b == PLUS_VALUE ) {
86 return '+';
87 }
88
89 if ( b == SLASH_VALUE ) {
90 return '/';
91 }
92
93 throw new IllegalArgumentException( "Byte " + new Integer( b ) + " is not a valid Base64 value" );
94 }
95
96 public int[] doAction(int[] in, int[] key) {
97
98 int charCount = ( ( in.length * 4 ) / 3 ) + 4;
99
100
101
102
103 StringBuffer result = new StringBuffer( ( charCount * 77 ) / 76 );
104
105 int byteArrayLength = in.length;
106 int byteArrayIndex = 0;
107 int byteTriplet = 0;
108 while ( byteArrayIndex < byteArrayLength - 2 ) {
109
110 byteTriplet = in[ byteArrayIndex++ ];
111
112 byteTriplet <<= 8;
113 byteTriplet |= in[ byteArrayIndex++ ];
114 byteTriplet <<= 8;
115 byteTriplet |= in[ byteArrayIndex++ ];
116
117
118 byte b4 = (byte)( SIX_BIT_MASK & byteTriplet );
119
120 byteTriplet >>= 6;
121 byte b3 = (byte)( SIX_BIT_MASK & byteTriplet );
122 byteTriplet >>= 6;
123 byte b2 = (byte)( SIX_BIT_MASK & byteTriplet );
124 byteTriplet >>= 6;
125 byte b1 = (byte)( SIX_BIT_MASK & byteTriplet );
126
127
128 result.append( mapByteToChar( b1 ) );
129 result.append( mapByteToChar( b2 ) );
130 result.append( mapByteToChar( b3 ) );
131 result.append( mapByteToChar( b4 ) );
132
133
134 if ( byteArrayIndex % 57 == 0 ) {
135 result.append( "\n" );
136 }
137 }
138
139
140 if ( byteArrayIndex == byteArrayLength - 1 ) {
141
142 byteTriplet = in[ byteArrayIndex++ ];
143
144 byteTriplet <<= 4;
145
146 byte b2 = (byte)( SIX_BIT_MASK & byteTriplet );
147 byteTriplet >>= 6;
148 byte b1 = (byte)( SIX_BIT_MASK & byteTriplet );
149
150 result.append( mapByteToChar( b1 ) );
151 result.append( mapByteToChar( b2 ) );
152
153
154 result.append( "==" );
155 }
156
157
158 if ( byteArrayIndex == byteArrayLength - 2 ) {
159
160 byteTriplet = in[ byteArrayIndex++ ];
161 byteTriplet <<= 8;
162 byteTriplet |= in[ byteArrayIndex++ ];
163
164 byteTriplet <<= 2;
165
166 byte b3 = (byte)( SIX_BIT_MASK & byteTriplet );
167 byteTriplet >>= 6;
168 byte b2 = (byte)( SIX_BIT_MASK & byteTriplet );
169 byteTriplet >>= 6;
170 byte b1 = (byte)( SIX_BIT_MASK & byteTriplet );
171
172 result.append( mapByteToChar( b1 ) );
173 result.append( mapByteToChar( b2 ) );
174 result.append( mapByteToChar( b3 ) );
175
176
177 result.append( "=" );
178 }
179 int resultArray[] = new int[result.length()];
180 for (int i=0; i<resultArray.length; i++)
181 resultArray[i] = result.charAt(i);
182 return resultArray;
183 }
184
185 }