Javacard error when trying to create RSA 2048 key pair - javacard

I'm developing a piece of code in which I need to create an RSA key pair.
My java card is an FM1280-ID006 card which has written in its information sheet that It supports java card 2.2.2 specification. When I try to create an RSA key pair
KeyPair(KeyPair.ALG_RSA,KeyBuilder.LENGTH_RSA_2048)
and install it on the card above, nothing unusual happens and I'm done successfully (90 00).
but as I call the method genKeyPair(), something happens in the card which I do not understand why. I use GPShell as below:
send_apdu -sc 1 -APDU 8000000000 // initialize
Command --> 8000000000
Wrapped command --> 8000000000
send_APDU() returns 0x8010002F (A communications error with the smart card has been detected. Retry the operation.)
It is worthy to mention that this problem on key pair creation does not happen when creating a 1024 key pair
KeyPair(KeyPair.ALG_RSA,KeyBuilder.LENGTH_RSA_1024)
and it is successfully created and used by RSA cipher and so on as:
send_apdu -sc 1 -APDU 8000000000 // initialize
Command --> 8000000000
Wrapped command --> 8000000000
Response <-- 9000
send_APDU() returns 0x80209000 (9000: Success. No error.)
command time: 3432 ms
Does my card support KeyPair 2048 as the information sheet says supporting javacard 2.2.2?
Appendix 1: Java Code:
package net.sourceforge.globalplatform.jc.hasincard;
import javacard.framework.*;
import javacard.security.*;
import javacardx.crypto.*;
import java.security.acl.Owner;
import java.util.Random;
public class HasinCardApplet extends Applet {
final static byte APPLET_CLA = (byte)0x80;
final static byte INITIALIZE = (byte)0x00;
final static byte INSERT_MESSAGE = (byte)0x01;
final static byte CHECK_MESSAGE = (byte)0x02;
final static byte GET_HASH = (byte)0x03;
final static byte GET_SIGN = (byte)0x04;
final static byte VERIFY_SIGN = (byte)0x05;
final static byte VERIFY_PIN = (byte)0x06;
final static byte CHANGE_PIN = (byte)0x07;
final static byte UNLOCK_PIN = (byte)0x08;
final static byte TEST = (byte)0x09;
final static short SW_MESSAGE_NOT_INSERTED = (short)0x6300;
final static short SW_KEY_IS_INITIALIZED = (short)0x6301;
final static short SW_HASH_NOT_SET = (short)0x6302;
final static short SW_SIGN_NOT_SET = (short)0x6303;
final static short SW_CARD_IS_LOCKED = (short)0x6304;
final static short SW_VERIFICATION_FAILED = (short)0x6305;
final static short SW_PIN_VERIFICATION_REQUIRED = (short)0x6306;
final static short SW_NEW_PIN_TOO_LONG = (short)0x6307;
final static short SW_NEW_PIN_TOO_SHORT = (short)0x6308;
final static short SW_PUK_VERIFICATION_REJECTED = (short)0x6309;
final static short SW_PUK_VERIFICATION_FAILED = (short)0x630A;
final static byte PIN_TRY_LIMIT = (byte)3;
final static byte MAX_PIN_SIZE = (byte)16;
final static byte MIN_PIN_SIZE = (byte)4;
final static byte PUK_LEN = (byte)16;
final static byte PUK_TRY_LIMIT = (byte)3;
private static byte[] Message;
private static byte[] Hash;
private static byte[] Sign;
private short message_len = 0;
private short hash_len = 0;
private short sign_len = 0;
private static boolean key_initialization_flag = false;
private static boolean insert_message_flag = false;
private static boolean hash_set_flag = false;
private static boolean sign_set_flag = false;
MessageDigest mDigest;
KeyPair rsaKey;
Cipher rsaCipher;
OwnerPIN userPin;
RandomData rnd;
byte[] PUK;
boolean init_flag;
byte puk_try_count;
private HasinCardApplet (byte[] bArray,short bOffset,byte bLength)
{
Message = new byte[512];
Hash = new byte[512];
Sign = new byte[512];
userPin = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);
rsaKey = new KeyPair(KeyPair.ALG_RSA,KeyBuilder.LENGTH_RSA_2048);
rsaCipher = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
mDigest = MessageDigest.getInstance(MessageDigest.ALG_SHA_256,false);
rnd = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
PUK = new byte[PUK_LEN];
generate_random(PUK, (byte) 16);
init_flag = false;
puk_try_count = (byte) 0;
byte[] InstParam = new byte[(byte)64];
byte iLen = bArray[bOffset];
bOffset = (short) (bOffset+iLen+1);
byte cLen = bArray[bOffset];
bOffset = (short) (bOffset+cLen+1);
byte aLen = bArray[bOffset];
Util.arrayCopy(bArray,(short) (bOffset +1),InstParam,(short)0,(short)aLen);
byte CPassLen = InstParam[0];
byte IPassLen = InstParam[CPassLen+1];
userPin.update(InstParam,(short)1,CPassLen);
register();
}
public static void install(byte[] bArray, short bOffset, byte bLength)
{
new HasinCardApplet(bArray, bOffset, bLength);
}
public boolean select()
{
Util.arrayFillNonAtomic(Message, (short) 0, (short)512, (byte) 0x00);
Util.arrayFillNonAtomic(Hash, (short) 0, (short)512, (byte) 0x00);
Util.arrayFillNonAtomic(Sign, (short) 0, (short)512, (byte) 0x00);
return true;
}
public void deselect()
{
}
public void process(APDU apdu)
{
if (selectingApplet())
{
if(!init_flag) {
send_puk(apdu);
}
return;
}
byte[] buffer = apdu.getBuffer();
if (buffer[ISO7816.OFFSET_CLA] == APPLET_CLA) {
switch (buffer[ISO7816.OFFSET_INS]) {
case VERIFY_PIN:
verify_pin(apdu);
break;
case CHANGE_PIN:
change_pin(apdu);
break;
case UNLOCK_PIN:
unlock_pin(apdu);
break;
case INITIALIZE:
initialize();
break;
case INSERT_MESSAGE:
insert_message(apdu);
break;
case CHECK_MESSAGE:
check_message(apdu);
break;
case GET_HASH:
hash_message();
get_hash(apdu);
break;
case GET_SIGN:
hash_message();
sign_message();
get_sign(apdu);
break;
case VERIFY_SIGN:
verify_sign(apdu);
break;
case TEST:
test(apdu);
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
} else {
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
}
}
private void initialize() {
if ( ! userPin.isValidated() )
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
if(key_initialization_flag) {
ISOException.throwIt(SW_KEY_IS_INITIALIZED);
}
rsaKey.genKeyPair();
key_initialization_flag = true;
init_flag = true;
}
private void insert_message(APDU apdu) {
byte[] buffer = apdu.getBuffer();
if ( ! userPin.isValidated() )
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
if(buffer[ISO7816.OFFSET_P1] == (byte) 0x01) {
// reset Message
message_len = 0;
}
short LC = apdu.setIncomingAndReceive();
Util.arrayCopy(buffer, (short) (ISO7816.OFFSET_CDATA), Message, message_len, LC);
message_len = (short) (message_len + LC);
insert_message_flag = true;
}
private void check_message(APDU apdu) {
byte[] buffer = apdu.getBuffer();
if ( ! userPin.isValidated() )
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
if(insert_message_flag) {
apdu.setIncomingAndReceive();
Util.arrayCopy(Message, (short) 0, buffer, (short) 0, message_len);
apdu.setOutgoingAndSend((short) 0, message_len);
} else {
ISOException.throwIt(SW_MESSAGE_NOT_INSERTED);
}
}
private void hash_message() {
if ( ! userPin.isValidated() )
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
if(insert_message_flag) {
mDigest.reset();
hash_len = mDigest.doFinal(Message, (short) 0, message_len, Hash, (short) 0);
hash_set_flag = true;
} else {
ISOException.throwIt(SW_MESSAGE_NOT_INSERTED);
}
}
private void sign_message() {
if ( ! userPin.isValidated() )
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
if(insert_message_flag) {
rsaCipher.init(rsaKey.getPrivate(), Cipher.MODE_ENCRYPT);
sign_len = rsaCipher.doFinal(Hash, (short) 0, hash_len, Sign, (short) 0);
sign_set_flag = true;
} else {
ISOException.throwIt(SW_MESSAGE_NOT_INSERTED);
}
}
private void get_hash(APDU apdu) {
if ( ! userPin.isValidated() )
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
if(hash_set_flag) {
byte[] buffer = apdu.getBuffer();
Util.arrayCopy(Hash, (short) 0, buffer, (short) 0, hash_len);
apdu.setOutgoingAndSend((short) 0, hash_len);
} else {
ISOException.throwIt(SW_HASH_NOT_SET);
}
}
private void get_sign(APDU apdu) {
if ( ! userPin.isValidated() )
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
if(sign_set_flag) {
byte[] buffer = apdu.getBuffer();
Util.arrayCopy(Sign, (short) 0, buffer, (short) 0, sign_len);
apdu.setOutgoingAndSend((short) 0, sign_len);
} else {
ISOException.throwIt(SW_SIGN_NOT_SET);
}
}
private void verify_sign(APDU apdu) {
byte[] buffer = apdu.getBuffer();
if ( ! userPin.isValidated() )
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
apdu.setIncomingAndReceive();
rsaCipher.init(rsaKey.getPublic(), Cipher.MODE_DECRYPT);
short LC = rsaCipher.doFinal(Sign, (short) 0, sign_len, buffer, (short)0);
apdu.setOutgoingAndSend((short)0,LC);
}
private void verify_pin(APDU apdu) {
byte[] buffer = apdu.getBuffer();
if(userPin.getTriesRemaining() == (byte)0)
ISOException.throwIt(SW_CARD_IS_LOCKED);
short LC = (byte)(apdu.setIncomingAndReceive());
if ( userPin.check(buffer, ISO7816.OFFSET_CDATA, (byte)LC) == false )
ISOException.throwIt(SW_VERIFICATION_FAILED);
}
private void change_pin(APDU apdu) {
byte[] buffer = apdu.getBuffer();
if(userPin.getTriesRemaining() == (byte)0)
ISOException.throwIt(SW_CARD_IS_LOCKED);
if ( ! userPin.isValidated() )
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
short LC = (byte)(apdu.setIncomingAndReceive());
if(LC > MAX_PIN_SIZE)
ISOException.throwIt(SW_NEW_PIN_TOO_LONG);
if(LC < MIN_PIN_SIZE)
ISOException.throwIt(SW_NEW_PIN_TOO_SHORT);
userPin.update(buffer, (short) ISO7816.OFFSET_CDATA, (byte)LC);
}
private void unlock_pin(APDU apdu){
if(puk_try_count >= PUK_TRY_LIMIT){
ISOException.throwIt(SW_PUK_VERIFICATION_REJECTED);
}
byte[] buffer = apdu.getBuffer();
apdu.setIncomingAndReceive();
if (Util.arrayCompare(PUK, (short) 0, buffer, (short) (ISO7816.OFFSET_CDATA), (short) PUK_LEN) == 0) {
userPin.resetAndUnblock();
puk_try_count = (byte) 0;
return;
} else {
puk_try_count = (byte)(puk_try_count + (byte)1);
ISOException.throwIt(SW_PUK_VERIFICATION_FAILED);
}
}
private void generate_random(byte[] buffer,byte len){
rnd.generateData(buffer, (short) 0, (short) len);
}
private void send_puk(APDU apdu){
apdu.setIncomingAndReceive();
byte[] buffer = apdu.getBuffer();
Util.arrayCopy(PUK,(short)0,buffer,(short)0,(short)PUK_LEN);
apdu.setOutgoingAndSend((short) 0, (short) PUK_LEN);
}
}
Appendix 2: GPShell 1.4.4 APDUs:
mode_211
enable_trace
establish_context
enable_trace
enable_timer
card_connect
command time: 15 ms
select -AID E0E1E2E3E4E501
Command --> 00A4040007E0E1E2E3E4E501
Wrapped command --> 00A4040007E0E1E2E3E4E501
Response <-- 26759506800664A82A242E481CD645C59000
command time: 78 ms
send_apdu -sc 1 -APDU 80060000083132333400000000 // verify userPin
Command --> 80060000083132333400000000
Wrapped command --> 80060000083132333400000000
Response <-- 9000
send_APDU() returns 0x80209000 (9000: Success. No error.)
command time: 16 ms
send_apdu -sc 1 -APDU 8000000000 // initialize
Command --> 8000000000
Wrapped command --> 8000000000
send_APDU() returns 0x8010002F (A communications error with the smart card has been detected. Retry the operation.)

Related

Bluetooth LE with Android Studio: Write Characteristic with buttons

I am new to Android and Bluetooth and suffering with this problem.
I want to write on a specific characteristic if two buttons are touched.
If I touch the first button a number between 0-9 should be count with +1. With the other button the number should be decrease with -1.
As a fundament i use the BluetootleGatt Example App from Google.
In the DeviceControlActivity i changed the following code:
private final ExpandableListView.OnChildClickListener servicesListClickListner =
new ExpandableListView.OnChildClickListener() {
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
int childPosition, long id) {
if (mGattCharacteristics != null) {
final BluetoothGattCharacteristic characteristic =
mGattCharacteristics.get(groupPosition).get(childPosition);
final int charaProp = characteristic.getProperties(); //The properties contain a bit mask of property flags indicating
//the features of this characteristic.
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
// If there is an active notification on a characteristic, clear
// it first so it doesn't update the data field on the user interface.
if (mNotifyCharacteristic != null) {
mBluetoothLeService.setCharacteristicNotification(
mNotifyCharacteristic, false);
mNotifyCharacteristic = null;
}
mBluetoothLeService.readCharacteristic(characteristic);
}
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY ) > 0) {
mNotifyCharacteristic = characteristic;
mBluetoothLeService.setCharacteristicNotification(
characteristic, true);
}
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
characteristic.setWriteType(BluetoothGattCharacteristic.PERMISSION_WRITE);
addListenerOnButton();
}
return true;
}
return false;
}
};
Here is my addListenerOnButton() for the two buttons:
public void addListenerOnButton() {
mArrowUp = (ImageButton) findViewById(R.id.arrow_up);
mArrowUp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
mBluetoothLeService.writeCharacteristicUp();
}
});
mArrowDown = (ImageButton) findViewById(R.id.arrow_down);
mArrowDown.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
mBluetoothLeService.writeCharacteristicDown();
}
});
}
They will call the two writeCharacteristic Methods in the BluetoothLeService-Class. For example i post here only the writeCharacteristicUp()-Method:
public boolean writeCharacteristicUp() {
//check mBluetoothGatt is available
if (mBluetoothGatt == null) {
Log.e(TAG, "lost connection");
return false;
}
BluetoothGattService Service = mBluetoothGatt.getService(UUID_DO_LOGGER_TEST);
if (Service == null) {
Log.e(TAG, "service not found!");
return false;
}
BluetoothGattCharacteristic charac = Service
.getCharacteristic(UUID_TEST_NUMBER);
if (charac == null) {
Log.e(TAG, "char not found!");
return false;
}
byte[] value0 = new byte[1];
value0[0] = (byte) 0; //Constant of 0 for comparison later
byte[] value1 = new byte[1];
value1[0] = (byte) 1; //Constant of 1 for comparison later
byte[] value2 = new byte[1];
value2[0] = (byte) 2; //Constant of 1 for comparison later
byte[] value3 = new byte[1];
value3[0] = (byte) 3; //Constant of 1 for comparison later
byte[] value4 = new byte[1];
value4[0] = (byte) 4; //Constant of 1 for comparison later
byte[] value5 = new byte[1];
value5[0] = (byte) 5; //Constant of 1 for comparison later
byte[] value6 = new byte[1];
value6[0] = (byte) 6; //Constant of 1 for comparison later
byte[] value7 = new byte[1];
value7[0] = (byte) 7; //Constant of 1 for comparison later
byte[] value8 = new byte[1];
value8[0] = (byte) 8; //Constant of 1 for comparison later
byte[] value9 = new byte[1];
value9[0] = (byte) 9; //Constant of 1 for comparison later
byte[] actualvalue = charac.getValue();
if (actualvalue == value0) {
charac.setValue(value1);
}
if (actualvalue == value1) {
charac.setValue(value2);
}
if (actualvalue == value2) {
charac.setValue(value3);
}
if (actualvalue == value3) {
charac.setValue(value4);
}
if (actualvalue == value4) {
charac.setValue(value5);
}
if (actualvalue == value5) {
charac.setValue(value6);
}
if (actualvalue == value6) {
charac.setValue(value7);
}
if (actualvalue == value7) {
charac.setValue(value8);
}
if (actualvalue == value8) {
charac.setValue(value9);
}
if (actualvalue == value9) {
charac.setValue(value0);
}
// charac.setValue(value0);
// byte[] actualvaluenew1 = charac.getValue();
boolean status = mBluetoothGatt.writeCharacteristic(charac);
// byte[] actualvaluenew2 = charac.getValue();
return status;
}
The problem is that the
boolean status = mBluetoothGatt.writeCharacteristic(charac)
does not work, the status will be false. And so the actual value is not displayed on the Screen in the corresponding TextView. Why?
Also i found out that the if-grinds are not working because charac.setValue(value0) is only working outside the if-grinds?
I would suggest you press and hold control key and click to BluetoothGatt#writeCharacteristic(ch) function in your code. Then Android Studio will view BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic characteristic) function:
public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
&& (characteristic.getProperties() &
BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false;
if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
if (mService == null || mClientIf == 0 || characteristic.getValue() == null) return false;
BluetoothGattService service = characteristic.getService();
if (service == null) return false;
BluetoothDevice device = service.getDevice();
if (device == null) return false;
synchronized(mDeviceBusy) {
if (mDeviceBusy) return false;
mDeviceBusy = true;
}
try {
mService.writeCharacteristic(mClientIf, device.getAddress(),
service.getType(), service.getInstanceId(),
new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
new ParcelUuid(characteristic.getUuid()),
characteristic.getWriteType(), AUTHENTICATION_NONE,
characteristic.getValue());
} catch (RemoteException e) {
Log.e(TAG,"",e);
mDeviceBusy = false;
return false;
}
return true;
}
Put a breakpoint inside the method and do debugging. Here are the possible reasons why you get false based on the source code:
The remote BLE device does not have Write or Write with No Response access
Either your service is null or the characteristic value you set is null
Your device is already doing another BLE process with the remote device
In my opinion, most probably the 2nd item is the reason.

Sending signature data in response APDU - Java Card

I would like to sign some data (the MESSAGE byte array) on my Java Card and then return the signature in a response APDU. My code works fine (or at least I think it does and it returns 9000) without the line apdu.sendBytes(BAS, sSignLen), but when I uncomment it I get an unknown error (0xC000002B (Unknown error.)).
When I try to send other data in a response APDU it works flawlessly.
apdu.setIncomingAndReceive();
Util.arrayCopyNonAtomic(MESSAGE, (short) 0, buffer, (short) 0, (short) MESSAGE.length);
apdu.setOutgoingAndSend((short) 0, (short) MESSAGE.length);
Here is my code. What am I doing wrong or missing? Thank you!
public class TestApplet extends Applet {
...
private final static byte SIGN = (byte) 0x01;
...
private final static byte[] MESSAGE = new byte[] { 'M', 'e', 's', 's', 'a', 'g', 'e' };
final static short BAS = 0;
public void process(APDU apdu) {
if (this.selectingApplet())
return;
byte buffer[] = apdu.getBuffer();
...
switch (buffer[ISO7816.OFFSET_INS]) {
case SIGN:
try {
ECDSAKeyPair = Secp256k1Domain.getKeyPairParameter();
ECDSAKeyPair.genKeyPair();
ECDSAPublicKey = (ECPublicKey) ECDSAKeyPair.getPublic();
ECDSAPrivateKey = (ECPrivateKey) ECDSAKeyPair.getPrivate();
ECDSASignature = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);
short signLen = 0;
byte[] signatureArray = new byte[70];
ECDSASignature.init(ECDSAPrivateKey, Signature.MODE_SIGN);
signLen = ECDSASignature.sign(MESSAGE, BAS, (short) MESSAGE.length, signatureArray, BAS);
apdu.setIncomingAndReceive();
Util.arrayCopyNonAtomic(signatureArray, (short) 0, buffer, (short) 0, (short) signatureArray.length);
apdu.setOutgoingAndSend((short) 0, (short) signatureArray.length);
} catch (CryptoException c) {
short reason = c.getReason();
ISOException.throwIt((short) ((short) (0x9C00) | reason));
}
break;
...
return;
}
}
It's probably that signLen is larger than the Ne value (incorrectly called Le in the JavaCard specifications). You are also abusing the Le value to mean (short) MESSAGE.length by the way. Ne indicates the maximum number of bytes that are expected to be send back.

Getting {byte[0]} as output while convert stream to Byte

Hi I want to convert Stream to Byte and for this I am using the below code for converting.
void photoChooserTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
var imageSrc = new BitmapImage();
imageSrc.SetSource(e.ChosenPhoto);
imgUploadedInsurance.Source = imageSrc;
_BitmapImage.SetSource(e.ChosenPhoto);
image = Converter.StreamToByte(e.ChosenPhoto);
}
}
Below method is used for converting which is returning 0 byte
public static byte[] StreamToByte(Stream input)
{
//byte[] buffer = new byte[16 * 1024];
byte[] buffer = new byte[input.Length];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
// input.CopyTo(ms);
return ms.ToArray();
}
}
You souldn't return ms.ToArray(), but buffer. Here's my version of the method that will work:
public static byte[] StreamToByte(Stream input)
{
byte[] buffer = new byte[input.Length];
input.Read(buffer, 0, buffer.Length);
return buffer;
}

How to Install safari extension using setup project?

i have a working safari extension and i able to install it manually by dragging it on safari web browser. i want to know how can i install it programmatically.
i have done this for firefox, chrome and IE.
in firefox just copy your .xpi file to this folder ("C:\Users\admin\AppData\Roaming\Mozilla\Firefox\Profiles\xxx.default\extensions") in windows 7 and your extension will get installed.
and in chrome you have to write these registry keys
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Google\Chrome\Extensions\dlilbimladfdhkfbbcbjjnbleakbogef]
"version"="3.6"
"path"="C:\\extension.crx"
but in safari when i copy my .safariextz file to this folder "C:\Users\admin\AppData\Local\Apple Computer\Safari\Extensions" than extension not get installed.
can anybody guide me how can i do this.
In the folder:
~\Users\\AppData\Local\Apple Computer\Safari\Extensions
there is a file named Extensions.plist you will also need to add an entry for your extension in this file.
Extension.plist in "~\Users\AppData\Local\Apple Computer\Safari\Extensions" folder is a binary file. for read and add an entry we can use this class.
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace PlistCS
{
public static class Plist
{
private static List<int> offsetTable = new List<int>();
private static List<byte> objectTable = new List<byte>();
private static int refCount;
private static int objRefSize;
private static int offsetByteSize;
private static long offsetTableOffset;
#region Public Functions
public static object readPlist(string path)
{
using (FileStream f = new FileStream(path, FileMode.Open, FileAccess.Read))
{
return readPlist(f);
}
}
public static object readPlistSource(string source)
{
return readPlist(System.Text.Encoding.UTF8.GetBytes(source));
}
public static object readPlist(byte[] data)
{
return readPlist(new MemoryStream(data));
}
public static plistType getPlistType(Stream stream)
{
byte[] magicHeader = new byte[8];
stream.Read(magicHeader, 0, 8);
if (BitConverter.ToInt64(magicHeader, 0) == 3472403351741427810)
{
return plistType.Binary;
}
else
{
return plistType.Xml;
}
}
public static object readPlist(Stream stream, plistType type = plistType.Auto)
{
if (type == plistType.Auto)
{
type = getPlistType(stream);
stream.Seek(0, SeekOrigin.Begin);
}
if (type == plistType.Binary)
{
using (BinaryReader reader = new BinaryReader(stream))
{
byte[] data = reader.ReadBytes((int)reader.BaseStream.Length);
return readBinary(data);
}
}
else
{
using (BinaryReader reader = new BinaryReader(stream))
{
byte[] data = reader.ReadBytes((int)reader.BaseStream.Length);
return readBinary(data);
}
}
}
public static void writeBinary(object value, string path)
{
using (BinaryWriter writer = new BinaryWriter(new FileStream(path, FileMode.Create)))
{
writer.Write(writeBinary(value));
}
}
public static void writeBinary(object value, Stream stream)
{
using (BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write(writeBinary(value));
}
}
public static byte[] writeBinary(object value)
{
offsetTable.Clear();
objectTable.Clear();
refCount = 0;
objRefSize = 0;
offsetByteSize = 0;
offsetTableOffset = 0;
//Do not count the root node, subtract by 1
int totalRefs = countObject(value) - 1;
refCount = totalRefs;
objRefSize = RegulateNullBytes(BitConverter.GetBytes(refCount)).Length;
composeBinary(value);
writeBinaryString("bplist00", false);
offsetTableOffset = (long)objectTable.Count;
offsetTable.Add(objectTable.Count - 8);
offsetByteSize = RegulateNullBytes(BitConverter.GetBytes(offsetTable[offsetTable.Count - 1])).Length;
List<byte> offsetBytes = new List<byte>();
offsetTable.Reverse();
for (int i = 0; i < offsetTable.Count; i++)
{
offsetTable[i] = objectTable.Count - offsetTable[i];
byte[] buffer = RegulateNullBytes(BitConverter.GetBytes(offsetTable[i]), offsetByteSize);
Array.Reverse(buffer);
offsetBytes.AddRange(buffer);
}
objectTable.AddRange(offsetBytes);
objectTable.AddRange(new byte[6]);
objectTable.Add(Convert.ToByte(offsetByteSize));
objectTable.Add(Convert.ToByte(objRefSize));
var a = BitConverter.GetBytes((long)totalRefs + 1);
Array.Reverse(a);
objectTable.AddRange(a);
objectTable.AddRange(BitConverter.GetBytes((long)0));
a = BitConverter.GetBytes(offsetTableOffset);
Array.Reverse(a);
objectTable.AddRange(a);
return objectTable.ToArray();
}
#endregion
#region Private Functions
private static object readBinary(byte[] data)
{
offsetTable.Clear();
List<byte> offsetTableBytes = new List<byte>();
objectTable.Clear();
refCount = 0;
objRefSize = 0;
offsetByteSize = 0;
offsetTableOffset = 0;
List<byte> bList = new List<byte>(data);
List<byte> trailer = bList.GetRange(bList.Count - 32, 32);
parseTrailer(trailer);
objectTable = bList.GetRange(0, (int)offsetTableOffset);
offsetTableBytes = bList.GetRange((int)offsetTableOffset, bList.Count - (int)offsetTableOffset - 32);
parseOffsetTable(offsetTableBytes);
return parseBinary(0);
}
private static int countObject(object value)
{
int count = 0;
switch (value.GetType().ToString())
{
case "System.Collections.Generic.Dictionary`2[System.String,System.Object]":
Dictionary<string, object> dict = (Dictionary<string, object>)value;
foreach (string key in dict.Keys)
{
count += countObject(dict[key]);
}
count += dict.Keys.Count;
count++;
break;
case "System.Collections.Generic.List`1[System.Object]":
List<object> list = (List<object>)value;
foreach (object obj in list)
{
count += countObject(obj);
}
count++;
break;
default:
count++;
break;
}
return count;
}
private static byte[] writeBinaryDictionary(Dictionary<string, object> dictionary)
{
List<byte> buffer = new List<byte>();
List<byte> header = new List<byte>();
List<int> refs = new List<int>();
for (int i = dictionary.Count - 1; i >= 0; i--)
{
var o = new object[dictionary.Count];
dictionary.Values.CopyTo(o, 0);
composeBinary(o[i]);
offsetTable.Add(objectTable.Count);
refs.Add(refCount);
refCount--;
}
for (int i = dictionary.Count - 1; i >= 0; i--)
{
var o = new string[dictionary.Count];
dictionary.Keys.CopyTo(o, 0);
composeBinary(o[i]);//);
offsetTable.Add(objectTable.Count);
refs.Add(refCount);
refCount--;
}
if (dictionary.Count < 15)
{
header.Add(Convert.ToByte(0xD0 | Convert.ToByte(dictionary.Count)));
}
else
{
header.Add(0xD0 | 0xf);
header.AddRange(writeBinaryInteger(dictionary.Count, false));
}
foreach (int val in refs)
{
byte[] refBuffer = RegulateNullBytes(BitConverter.GetBytes(val), objRefSize);
Array.Reverse(refBuffer);
buffer.InsertRange(0, refBuffer);
}
buffer.InsertRange(0, header);
objectTable.InsertRange(0, buffer);
return buffer.ToArray();
}
private static byte[] composeBinaryArray(List<object> objects)
{
List<byte> buffer = new List<byte>();
List<byte> header = new List<byte>();
List<int> refs = new List<int>();
for (int i = objects.Count - 1; i >= 0; i--)
{
composeBinary(objects[i]);
offsetTable.Add(objectTable.Count);
refs.Add(refCount);
refCount--;
}
if (objects.Count < 15)
{
header.Add(Convert.ToByte(0xA0 | Convert.ToByte(objects.Count)));
}
else
{
header.Add(0xA0 | 0xf);
header.AddRange(writeBinaryInteger(objects.Count, false));
}
foreach (int val in refs)
{
byte[] refBuffer = RegulateNullBytes(BitConverter.GetBytes(val), objRefSize);
Array.Reverse(refBuffer);
buffer.InsertRange(0, refBuffer);
}
buffer.InsertRange(0, header);
objectTable.InsertRange(0, buffer);
return buffer.ToArray();
}
private static byte[] composeBinary(object obj)
{
byte[] value;
switch (obj.GetType().ToString())
{
case "System.Collections.Generic.Dictionary`2[System.String,System.Object]":
value = writeBinaryDictionary((Dictionary<string, object>)obj);
return value;
case "System.Collections.Generic.List`1[System.Object]":
value = composeBinaryArray((List<object>)obj);
return value;
case "System.Byte[]":
value = writeBinaryByteArray((byte[])obj);
return value;
case "System.Double":
value = writeBinaryDouble((double)obj);
return value;
case "System.Int32":
value = writeBinaryInteger((int)obj, true);
return value;
case "System.String":
value = writeBinaryString((string)obj, true);
return value;
case "System.DateTime":
value = writeBinaryDate((DateTime)obj);
return value;
case "System.Boolean":
value = writeBinaryBool((bool)obj);
return value;
default:
return new byte[0];
}
}
public static byte[] writeBinaryDate(DateTime obj)
{
List<byte> buffer = new List<byte>(RegulateNullBytes(BitConverter.GetBytes(PlistDateConverter.ConvertToAppleTimeStamp(obj)), 8));
buffer.Reverse();
buffer.Insert(0, 0x33);
objectTable.InsertRange(0, buffer);
return buffer.ToArray();
}
public static byte[] writeBinaryBool(bool obj)
{
List<byte> buffer = new List<byte>(new byte[1] { (bool)obj ? (byte)9 : (byte)8 });
objectTable.InsertRange(0, buffer);
return buffer.ToArray();
}
private static byte[] writeBinaryInteger(int value, bool write)
{
List<byte> buffer = new List<byte>(BitConverter.GetBytes((long)value));
buffer = new List<byte>(RegulateNullBytes(buffer.ToArray()));
while (buffer.Count != Math.Pow(2, Math.Log(buffer.Count) / Math.Log(2)))
buffer.Add(0);
int header = 0x10 | (int)(Math.Log(buffer.Count) / Math.Log(2));
buffer.Reverse();
buffer.Insert(0, Convert.ToByte(header));
if (write)
objectTable.InsertRange(0, buffer);
return buffer.ToArray();
}
private static byte[] writeBinaryDouble(double value)
{
List<byte> buffer = new List<byte>(RegulateNullBytes(BitConverter.GetBytes(value), 4));
while (buffer.Count != Math.Pow(2, Math.Log(buffer.Count) / Math.Log(2)))
buffer.Add(0);
int header = 0x20 | (int)(Math.Log(buffer.Count) / Math.Log(2));
buffer.Reverse();
buffer.Insert(0, Convert.ToByte(header));
objectTable.InsertRange(0, buffer);
return buffer.ToArray();
}
private static byte[] writeBinaryByteArray(byte[] value)
{
List<byte> buffer = new List<byte>(value);
List<byte> header = new List<byte>();
if (value.Length < 15)
{
header.Add(Convert.ToByte(0x40 | Convert.ToByte(value.Length)));
}
else
{
header.Add(0x40 | 0xf);
header.AddRange(writeBinaryInteger(buffer.Count, false));
}
buffer.InsertRange(0, header);
objectTable.InsertRange(0, buffer);
return buffer.ToArray();
}
private static byte[] writeBinaryString(string value, bool head)
{
List<byte> buffer = new List<byte>();
List<byte> header = new List<byte>();
foreach (char chr in value.ToCharArray())
buffer.Add(Convert.ToByte(chr));
if (head)
{
if (value.Length < 15)
{
header.Add(Convert.ToByte(0x50 | Convert.ToByte(value.Length)));
}
else
{
header.Add(0x50 | 0xf);
header.AddRange(writeBinaryInteger(buffer.Count, false));
}
}
buffer.InsertRange(0, header);
objectTable.InsertRange(0, buffer);
return buffer.ToArray();
}
private static byte[] RegulateNullBytes(byte[] value)
{
return RegulateNullBytes(value, 1);
}
private static byte[] RegulateNullBytes(byte[] value, int minBytes)
{
Array.Reverse(value);
List<byte> bytes = new List<byte>(value);
for (int i = 0; i < bytes.Count; i++)
{
if (bytes[i] == 0 && bytes.Count > minBytes)
{
bytes.Remove(bytes[i]);
i--;
}
else
break;
}
if (bytes.Count < minBytes)
{
int dist = minBytes - bytes.Count;
for (int i = 0; i < dist; i++)
bytes.Insert(0, 0);
}
value = bytes.ToArray();
Array.Reverse(value);
return value;
}
private static void parseTrailer(List<byte> trailer)
{
offsetByteSize = BitConverter.ToInt32(RegulateNullBytes(trailer.GetRange(6, 1).ToArray(), 4), 0);
objRefSize = BitConverter.ToInt32(RegulateNullBytes(trailer.GetRange(7, 1).ToArray(), 4), 0);
byte[] refCountBytes = trailer.GetRange(12, 4).ToArray();
Array.Reverse(refCountBytes);
refCount = BitConverter.ToInt32(refCountBytes, 0);
byte[] offsetTableOffsetBytes = trailer.GetRange(24, 8).ToArray();
Array.Reverse(offsetTableOffsetBytes);
offsetTableOffset = BitConverter.ToInt64(offsetTableOffsetBytes, 0);
}
private static void parseOffsetTable(List<byte> offsetTableBytes)
{
for (int i = 0; i < offsetTableBytes.Count; i += offsetByteSize)
{
byte[] buffer = offsetTableBytes.GetRange(i, offsetByteSize).ToArray();
Array.Reverse(buffer);
offsetTable.Add(BitConverter.ToInt32(RegulateNullBytes(buffer, 4), 0));
}
}
private static object parseBinaryDictionary(int objRef)
{
Dictionary<string, object> buffer = new Dictionary<string, object>();
List<int> refs = new List<int>();
int refCount = 0;
byte dictByte = objectTable[offsetTable[objRef]];
int refStartPosition;
refCount = getCount(offsetTable[objRef], out refStartPosition);
if (refCount < 15)
refStartPosition = offsetTable[objRef] + 1;
else
refStartPosition = offsetTable[objRef] + 2 + RegulateNullBytes(BitConverter.GetBytes(refCount), 1).Length;
for (int i = refStartPosition; i < refStartPosition + refCount * 2 * objRefSize; i += objRefSize)
{
byte[] refBuffer = objectTable.GetRange(i, objRefSize).ToArray();
Array.Reverse(refBuffer);
refs.Add(BitConverter.ToInt32(RegulateNullBytes(refBuffer, 4), 0));
}
for (int i = 0; i < refCount; i++)
{
buffer.Add((string)parseBinary(refs[i]), parseBinary(refs[i + refCount]));
}
return buffer;
}
private static object parseBinaryArray(int objRef)
{
List<object> buffer = new List<object>();
List<int> refs = new List<int>();
int refCount = 0;
byte arrayByte = objectTable[offsetTable[objRef]];
int refStartPosition;
refCount = getCount(offsetTable[objRef], out refStartPosition);
if (refCount < 15)
refStartPosition = offsetTable[objRef] + 1;
else
//The following integer has a header aswell so we increase the refStartPosition by two to account for that.
refStartPosition = offsetTable[objRef] + 2 + RegulateNullBytes(BitConverter.GetBytes(refCount), 1).Length;
for (int i = refStartPosition; i < refStartPosition + refCount * objRefSize; i += objRefSize)
{
byte[] refBuffer = objectTable.GetRange(i, objRefSize).ToArray();
Array.Reverse(refBuffer);
refs.Add(BitConverter.ToInt32(RegulateNullBytes(refBuffer, 4), 0));
}
for (int i = 0; i < refCount; i++)
{
buffer.Add(parseBinary(refs[i]));
}
return buffer;
}
private static int getCount(int bytePosition, out int newBytePosition)
{
byte headerByte = objectTable[bytePosition];
byte headerByteTrail = Convert.ToByte(headerByte & 0xf);
int count;
if (headerByteTrail < 15)
{
count = headerByteTrail;
newBytePosition = bytePosition + 1;
}
else
count = (int)parseBinaryInt(bytePosition + 1, out newBytePosition);
return count;
}
private static object parseBinary(int objRef)
{
byte header = objectTable[offsetTable[objRef]];
switch (header & 0xF0)
{
case 0:
{
//If the byte is
//0 return null
//9 return true
//8 return false
return (objectTable[offsetTable[objRef]] == 0) ? (object)null : ((objectTable[offsetTable[objRef]] == 9) ? true : false);
}
case 0x10:
{
return parseBinaryInt(offsetTable[objRef]);
}
case 0x20:
{
return parseBinaryReal(offsetTable[objRef]);
}
case 0x30:
{
return parseBinaryDate(offsetTable[objRef]);
}
case 0x40:
{
return parseBinaryByteArray(offsetTable[objRef]);
}
case 0x50://String ASCII
{
return parseBinaryAsciiString(offsetTable[objRef]);
}
case 0x60://String Unicode
{
return parseBinaryUnicodeString(offsetTable[objRef]);
}
case 0xD0:
{
return parseBinaryDictionary(objRef);
}
case 0xA0:
{
return parseBinaryArray(objRef);
}
}
throw new Exception("This type is not supported");
}
public static object parseBinaryDate(int headerPosition)
{
byte[] buffer = objectTable.GetRange(headerPosition + 1, 8).ToArray();
Array.Reverse(buffer);
double appleTime = BitConverter.ToDouble(buffer, 0);
DateTime result = PlistDateConverter.ConvertFromAppleTimeStamp(appleTime);
return result;
}
private static object parseBinaryInt(int headerPosition)
{
int output;
return parseBinaryInt(headerPosition, out output);
}
private static object parseBinaryInt(int headerPosition, out int newHeaderPosition)
{
byte header = objectTable[headerPosition];
int byteCount = (int)Math.Pow(2, header & 0xf);
byte[] buffer = objectTable.GetRange(headerPosition + 1, byteCount).ToArray();
Array.Reverse(buffer);
//Add one to account for the header byte
newHeaderPosition = headerPosition + byteCount + 1;
return BitConverter.ToInt32(RegulateNullBytes(buffer, 4), 0);
}
private static object parseBinaryReal(int headerPosition)
{
byte header = objectTable[headerPosition];
int byteCount = (int)Math.Pow(2, header & 0xf);
byte[] buffer = objectTable.GetRange(headerPosition + 1, byteCount).ToArray();
Array.Reverse(buffer);
return BitConverter.ToDouble(RegulateNullBytes(buffer, 8), 0);
}
private static object parseBinaryAsciiString(int headerPosition)
{
int charStartPosition;
int charCount = getCount(headerPosition, out charStartPosition);
var buffer = objectTable.GetRange(charStartPosition, charCount);
return buffer.Count > 0 ? Encoding.ASCII.GetString(buffer.ToArray()) : string.Empty;
}
private static object parseBinaryUnicodeString(int headerPosition)
{
int charStartPosition;
int charCount = getCount(headerPosition, out charStartPosition);
charCount = charCount * 2;
byte[] buffer = new byte[charCount];
byte one, two;
for (int i = 0; i < charCount; i += 2)
{
one = objectTable.GetRange(charStartPosition + i, 1)[0];
two = objectTable.GetRange(charStartPosition + i + 1, 1)[0];
if (BitConverter.IsLittleEndian)
{
buffer[i] = two;
buffer[i + 1] = one;
}
else
{
buffer[i] = one;
buffer[i + 1] = two;
}
}
return Encoding.Unicode.GetString(buffer);
}
private static object parseBinaryByteArray(int headerPosition)
{
int byteStartPosition;
int byteCount = getCount(headerPosition, out byteStartPosition);
return objectTable.GetRange(byteStartPosition, byteCount).ToArray();
}
#endregion
}
public enum plistType
{
Auto, Binary, Xml
}
public static class PlistDateConverter
{
public static long timeDifference = 978307200;
public static long GetAppleTime(long unixTime)
{
return unixTime - timeDifference;
}
public static long GetUnixTime(long appleTime)
{
return appleTime + timeDifference;
}
public static DateTime ConvertFromAppleTimeStamp(double timestamp)
{
DateTime origin = new DateTime(2001, 1, 1, 0, 0, 0, 0);
return origin.AddSeconds(timestamp);
}
public static double ConvertToAppleTimeStamp(DateTime date)
{
DateTime begin = new DateTime(2001, 1, 1, 0, 0, 0, 0);
TimeSpan diff = date - begin;
return Math.Floor(diff.TotalSeconds);
}
}
}
and use this method in commit action of Installer.cs class to add an entry of extension Extension.plist
public void InstallSafariExt()
{
string safariExtPlist = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Apple Computer\\Safari\\Extensions\\Extensions.plist";
string safariSetupPlist = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + "\YourComp\\YourSoft\\Extensions.plist";
string ExtDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Apple Computer\\Safari\\Extensions";
if (!Directory.Exists(ExtDir))
{
Directory.CreateDirectory(ExtDir);
if (!File.Exists(safariExtPlist))
{
File.Copy(safariSetupPlist, safariExtPlist);
}
}
else
{
if (!File.Exists(safariExtPlist))
{
File.Copy(safariSetupPlist, safariExtPlist);
}
}
object obj = Plist.readPlist(safariExtPlist);
Dictionary<string, object> dict = (Dictionary<string, object>)obj;
Dictionary<string, object> NewExt = new Dictionary<string, object>();
NewExt.Add("Hidden Bars", new List<object>());
NewExt.Add("Added Non-Default Toolbar Items", new List<object>());
NewExt.Add("Enabled", true);
NewExt.Add("Archive File Name", "YourExtName.safariextz");
NewExt.Add("Removed Default Toolbar Items", new List<object>());
NewExt.Add("Bundle Directory Name", "YourExtName.safariextension");
List<object> listExt = (List<object>)dict["Installed Extensions"];
listExt.Add(NewExt);
Plist.writeBinary(obj, safariExtPlist);
string safariExtFile = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + "\YourComp\\YourSoft\\YourExtName.safariextz";
string safariInstallfolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Apple Computer\\Safari\\Extensions\\YourExtName.safariextz";
string[] safExtFiles = Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Apple Computer\\Safari\\Extensions\\", "YourExtName*.safariextz");
for (int i = 0; i < safExtFiles.Length; i++)
{
if (File.Exists(safExtFiles[i]))
File.Delete(safExtFiles[i]);
}
File.Copy(safariExtFile, safariInstallfolder);
}

How to convert byte[] to base64 (and back) in J2ME?

I need to base64 encode a byte[] to send it over to a http server, as well as read an encoded byte[] back. However, there is no Base64 encoder/decoder in j2me.
I would appreciate a piece of code for this!
br, perza
I use this class:
public class Base64 {
static byte[] encodeData;
static String charSet =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static {
encodeData = new byte[64];
for (int i = 0; i<64; i++) {
byte c = (byte) charSet.charAt(i);
encodeData[i] = c;
}
}
private Base64() {}
/**
* base-64 encode a string
* #param s The ascii string to encode
* #returns The base64 encoded result
*/
public static String
encode(String s) {
return encode(s.getBytes());
}
/**
* base-64 encode a byte array
* #param src The byte array to encode
* #returns The base64 encoded result
*/
public static String
encode(byte[] src) {
return encode(src, 0, src.length);
}
/**
* base-64 encode a byte array
* #param src The byte array to encode
* #param start The starting index
* #param len The number of bytes
* #returns The base64 encoded result
*/
public static String
encode(byte[] src, int start, int length) {
byte[] dst = new byte[(length+2)/3 * 4 + length/72];
int x = 0;
int dstIndex = 0;
int state = 0; // which char in pattern
int old = 0; // previous byte
int len = 0; // length decoded so far
int max = length + start;
for (int srcIndex = start; srcIndex<max; srcIndex++) {
x = src[srcIndex];
switch (++state) {
case 1:
dst[dstIndex++] = encodeData[(x>>2) & 0x3f];
break;
case 2:
dst[dstIndex++] = encodeData[((old<<4)&0x30)
| ((x>>4)&0xf)];
break;
case 3:
dst[dstIndex++] = encodeData[((old<<2)&0x3C)
| ((x>>6)&0x3)];
dst[dstIndex++] = encodeData[x&0x3F];
state = 0;
break;
}
old = x;
if (++len >= 72) {
dst[dstIndex++] = (byte) '\n';
len = 0;
}
}
/*
* now clean up the end bytes
*/
switch (state) {
case 1: dst[dstIndex++] = encodeData[(old<<4) & 0x30];
dst[dstIndex++] = (byte) '=';
dst[dstIndex++] = (byte) '=';
break;
case 2: dst[dstIndex++] = encodeData[(old<<2) & 0x3c];
dst[dstIndex++] = (byte) '=';
break;
}
return new String(dst);
}
/**
* A Base64 decoder. This implementation is slow, and
* doesn't handle wrapped lines.
* The output is undefined if there are errors in the input.
* #param s a Base64 encoded string
* #returns The byte array eith the decoded result
*/
public static byte[]
decode(String s) {
int end = 0; // end state
if (s.endsWith("=")) {
end++;
}
if (s.endsWith("==")) {
end++;
}
int len = (s.length() + 3)/4 * 3 - end;
byte[] result = new byte[len];
int dst = 0;
try {
for(int src = 0; src< s.length(); src++) {
int code = charSet.indexOf(s.charAt(src));
if (code == -1) {
break;
}
switch (src%4) {
case 0:
result[dst] = (byte) (code<<2);
break;
case 1:
result[dst++] |= (byte) ((code>>4) & 0x3);
result[dst] = (byte) (code<<4);
break;
case 2:
result[dst++] |= (byte) ((code>>2) & 0xf);
result[dst] = (byte) (code<<6);
break;
case 3:
result[dst++] |= (byte) (code & 0x3f);
break;
}
}
} catch (ArrayIndexOutOfBoundsException e) {}
return result;
}
/**
* Test the decoder and encoder.
* Call as <code>Base64 [string]</code>.
*/
public static void
main(String[] args) {
System.out.println("encode: " + args[0] + " -> ("
+ encode(args[0]) + ")");
System.out.println("decode: " + args[0] + " -> ("
+ new String(decode(args[0])) + ")");
}
}
You can use it's encode and decode methods.
I found it in "Data Encodings - Herong's Tutorial Examples".

Resources