View Javadoc
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