1 // Copyright (C) 2004, Brian Enigma <enigma at netninja.com>
2 // This file is part of MagicCodes.
3 //
4 // MagicCodes is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // MagicCodes is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Foobar; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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 // Base64 encoding yields a String that is 33% longer than the byte array
98 int charCount = ( ( in.length * 4 ) / 3 ) + 4;
99
100 // New lines will also be needed for every 76 charactesr, so allocate a
101 // StringBuffer that is long enough to hold the full result without
102 // having to expand later
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 // Build the 24 bit byte triplet from the input data
110 byteTriplet = in[ byteArrayIndex++ ];
111 // Each input byte contributes 8 bits to the triplet
112 byteTriplet <<= 8;
113 byteTriplet |= in[ byteArrayIndex++ ];
114 byteTriplet <<= 8;
115 byteTriplet |= in[ byteArrayIndex++ ];
116
117 // Look at the lowest order six bits and remember them
118 byte b4 = (byte)( SIX_BIT_MASK & byteTriplet );
119 // Move the byte triplet to get the next 6 bit value
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 // Add the Base64 encoded character to the result String
128 result.append( mapByteToChar( b1 ) );
129 result.append( mapByteToChar( b2 ) );
130 result.append( mapByteToChar( b3 ) );
131 result.append( mapByteToChar( b4 ) );
132
133 // There are 57 bytes for every 76 characters, so wrap the line when needed
134 if ( byteArrayIndex % 57 == 0 ) {
135 result.append( "\n" );
136 }
137 }
138
139 // Check if we have one byte left over
140 if ( byteArrayIndex == byteArrayLength - 1 ) {
141 // Convert our one byte to an int
142 byteTriplet = in[ byteArrayIndex++ ];
143 // Right pad the second 6 bit value with zeros
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 // Add "==" to the output to make it a multiple of 4 Base64 characters
154 result.append( "==" );
155 }
156
157 // Check if we have two byte left over
158 if ( byteArrayIndex == byteArrayLength - 2 ) {
159 // Convert our two bytes to an int
160 byteTriplet = in[ byteArrayIndex++ ];
161 byteTriplet <<= 8;
162 byteTriplet |= in[ byteArrayIndex++ ];
163 // Right pad the third 6 bit value with zeros
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 // Add "==" to the output to make it a multiple of 4 Base64 characters
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 }
This page was automatically generated by Maven