/**
* Title: Base64
* Description: encoder et decode en base64
* class base64
*
* @author Isaac Mekueko
* @version 1.0
*/
public final class Base64 {
static private final byte PADDING = ( byte ) '=';
static private final int SIGN = -128;
static private byte [] Encodebase64Alphabet = new byte[64];
static private byte [] alphaDecode =new byte[256];
static {
for(int i=0;i<=25;i++)
Encodebase64Alphabet[i] = (byte)('A'+i);
for(int i=26,j=0;i<=51;i++,j++)
Encodebase64Alphabet[i] = (byte)('a'+j);
for(int i=52,j=0;i<=61;i++,j++)
Encodebase64Alphabet[i] = (byte)('0'+j);
Encodebase64Alphabet[62] = (byte)('+');
Encodebase64Alphabet[63] = (byte)('/');
// decode
for(int i=0;i<256;i++)
alphaDecode[i] = -1;
for(int i='A',j=0;i<='Z';i++,j++)
alphaDecode[i] = (byte)j;
for(int i='a',j=26;i<='z';i++,j++)
alphaDecode[i] = (byte)j;
for(int i='0',j=52;i<='9';i++,j++)
alphaDecode[i] = (byte)j;
alphaDecode['+'] = 62;
alphaDecode['/'] = 63;
}
/*****************************************
* encode array byte from 0-255 to base64
* @param array byte
* @return array byte
*****************************************/
static public byte [] encode (byte [] DataByte) {
int numberDataBit = DataByte.length * 8;
int numberDataBitMODULO24 = numberDataBit % 24;
int numberDataBitBY24 = numberDataBit / 24;
byte []EncodeData = null;
if(numberDataBitMODULO24 == 0) EncodeData=new byte[numberDataBitBY24 * 4];
else EncodeData = new byte[(numberDataBitBY24+1) * 4];
byte Rshift2_b1,High_b2,Rshift6_b3,b1,b2,b3 ,e2,e3,e4 ;
int IndexDataByte,IndexEncodeData,i;
for( i=0;i<numberDataBitBY24;i++) {
IndexDataByte = 3 * i;
IndexEncodeData = 4 * i;
b1=DataByte[IndexDataByte];
b2=DataByte[IndexDataByte + 1];
b3=DataByte[IndexDataByte + 2];
Rshift2_b1 = ((b1&SIGN)==0) ? (byte)(b1>>2) : (byte)(b1>>>2);
High_b2 = ((b2&SIGN)==0) ? (byte)(b2>>4) : (byte)(b2>>>4);
Rshift6_b3 = ((b2&SIGN)==0) ? (byte)(b3>>6) : (byte)(b3>>>6);
e2 = (byte)(((b1&0x3)<<4)|High_b2);
e3 = (byte)(((b2&0xF)<<2)|Rshift6_b3);
e4 = (byte)(b3&0x3F);
EncodeData[IndexEncodeData] = Encodebase64Alphabet[Rshift2_b1];
EncodeData[IndexEncodeData+1] = Encodebase64Alphabet[e2];
EncodeData[IndexEncodeData+2] = Encodebase64Alphabet[e3];
EncodeData[IndexEncodeData+3] = Encodebase64Alphabet[e4];
}
IndexDataByte = 3 * i;
IndexEncodeData = 4 * i;
if(numberDataBitMODULO24 == 16) {
b1 = DataByte[IndexDataByte];
b2 = DataByte[IndexDataByte + 1];
Rshift2_b1 = ((b1&SIGN)==0) ? (byte)(b1>>2) : (byte)(b1>>>2);
High_b2 = ((b2&SIGN)==0) ? (byte)(b2>>4) : (byte)(b2>>>4);
e2 = (byte)(((b1&0x3)<<4)|High_b2);
e3 = (byte)((b2&0xF)<<2);
e4 = PADDING;
EncodeData[IndexEncodeData]= Encodebase64Alphabet[Rshift2_b1];
EncodeData[IndexEncodeData+1]=Encodebase64Alphabet[e2];
EncodeData[IndexEncodeData+2]=Encodebase64Alphabet[e3];
EncodeData[IndexEncodeData+3]=e4;
} else
if(numberDataBitMODULO24 == 8) {
b1=DataByte[IndexDataByte];
Rshift2_b1 = ((b1&SIGN)==0) ? (byte)(b1>>2) : (byte)(b1>>>2);
e2 = (byte)((b1&0x3)<<4);
e3 = PADDING;
e4 = PADDING;
EncodeData[IndexEncodeData] = Encodebase64Alphabet[Rshift2_b1];
EncodeData[IndexEncodeData+1] = Encodebase64Alphabet[e2];
EncodeData[IndexEncodeData+2] = e3;
EncodeData[IndexEncodeData+3] = e4;
}
return EncodeData;
}
/**************************************
* encode string from 0-255 to base64
* @param string
* @return String
**************************************/
static public String encode(String str) {
return new String(encode(str.getBytes()));
}
/**********************************************
* decode array byte from base64 to char 0-255
* @param array byte
* @return array byte
*********************************************/
public static byte[] decode(byte []DataByte) {
if(!isByteInBase64(DataByte)) return null;
int numberDataBit = DataByte.length * 6;
int numberGroup_3bit = numberDataBit / 24;
byte []DecodeData = null;
byte b1,b2,b3,b4,d1,d2,d3,ch1,ch2,ch3,ch4;
ch3 = DataByte[DataByte.length-2];
ch4 = DataByte[DataByte.length-1];
if(ch3!=PADDING && ch4!=PADDING)
DecodeData=new byte[numberGroup_3bit*3];
else if(ch3==PADDING)
DecodeData=new byte[(numberGroup_3bit*3)-2];
else if(ch4==PADDING)
DecodeData=new byte[(numberGroup_3bit*3)-1];
int decodeIndex,encodeIndex;
for(int i=0; i<numberGroup_3bit; i++) {
decodeIndex = 3 * i;
encodeIndex = 4 * i;
ch1 = DataByte[encodeIndex];
ch2 = DataByte[encodeIndex+1];
ch3 = DataByte[encodeIndex+2];
ch4 = DataByte[encodeIndex+3];
b1 = alphaDecode[ch1];
b2 = alphaDecode[ch2];
b3 = alphaDecode[ch3];
b4 = alphaDecode[ch4];
if(ch3!=PADDING&&ch4!=PADDING) {
d1 = (byte)((b1<<2)|(b2>>>4));
d2 = (byte)((b2<<4)|(b3>>2));
d3 = (byte)((b3<<6)|b4);
DecodeData[decodeIndex] = d1;
DecodeData[decodeIndex+1] = d2;
DecodeData[decodeIndex+2] = d3;
} else
if(ch3==PADDING) {// 1 char
d1 = (byte)((b1<<2)|(b2>>>4));
DecodeData[decodeIndex] = d1;
}
else
if(ch4==PADDING) { // 2char
d1 = (byte)((b1<<2)|(b2>>>4));
d2 = (byte)((b2<<4)|(b3>>2));
DecodeData[decodeIndex] = d1;
DecodeData[decodeIndex+1] = d2;
}
}
return DecodeData;
}
/**
* decode base64 string into characters from 0-255
* @param string
* return string
**/
public static String decode(String str) {
return new String(decode(str.getBytes()));
}
/**
* check if the byte belong to The Base64 Alphabet
* @param octet
* @return bolean value
**/
private static boolean isByteInBase64(byte octet) {
if(octet==PADDING||alphaDecode[octet]!=-1)
return true;
else
return false;
}
private static boolean isByteInBase64(byte []arraybyte) {
int len=arraybyte.length;
for(int i=0;i<len;i++) {
if(!isByteInBase64(arraybyte[i]))
return false;
}
return true;
}
}