Java card send APDU command through server - javacard

I have created a server to send APDU commands to java card application.
The connection has been established successfully. The only problem that I encounter is that that I send a command successfully but the Java Card aplication doesn't receive it.
The following code represents the client from which I do send commands :
public class Client {
public static void main(String[] args) {
Socket sock;
try {
sock = new Socket("localhost", 9025);
InputStream is = sock.getInputStream();
OutputStream os = sock.getOutputStream();
CadClientInterface cad = CadDevice.getCadClientInstance(CadDevice.PROTOCOL_T0, is, os);
Apdu apdu = new Apdu();
System.out.println("Initialized apdu !");
byte[] installer = new byte[]{0x00, (byte) 0xA4, 0x04, 0x00, 0x09, (byte) 0xA0, 0x00, 0x00, 0x00, 0x62, 0x03, 0x01, 0x08, 0x01, 0x7F};
System.out.println("Prepare installer of cap !");
apdu.setDataIn(installer, installer.length);
System.out.println("Apdu set !");
System.out.println("Apdu sent !");
System.out.println(apdu);
cad.powerUp();
System.out.println("Powered up !");
cad.exchangeApdu(apdu);
cad.powerDown();
System.out.println("Powered down !");
} catch (IOException | CadTransportException e) {
e.printStackTrace();
System.out.println("Fail! " + e.getMessage());
}
}
}
The java card applet is a simple applet created by the IDE.
public class Proj extends Applet {
/**
* Installs this applet.
*
* #param bArray
* the array containing installation parameters
* #param bOffset
* the starting offset in bArray
* #param bLength
* the length in bytes of the parameter data in bArray
*/
public static void install(byte[] bArray, short bOffset, byte bLength) {
new Proj();
}
/**
* Only this class's install method should create the applet object.
*/
protected Proj() {
register();
}
/**
* Processes an incoming APDU.
*
* #see APDU
* #param apdu
* the incoming APDU
*/
#Override
public void process(APDU apdu) {
//Insert your code here
}
}
In the java card I turn on the Device and the port is established. I do not know why the command is successfully sent and the java card server doesn't receive it.
Edit:
I saw the problem about why javacard didn't receive any data. The problem is within the client. When the statement cad.powerUp(); reaches the whole client blocks and nothing more is executed, like in as a sleep(); function was called. So now the really problem is why the cad.powerUp() blocks the client.

I am assuming here that you have pasted the full applet code here. The Applet.register() method is not called in the applet on installation. So, the applet is never registered with JCRE and therefore no APDU can be received by it.
In fact, it will not be available for selection because JCRE does not have any information about it.
modify the code with the following and share the result.
public static void install(byte[] bArray, short bOffset, byte bLength) {
new Proj();
}
protected Proj(){
register();
}
Also, make sure to install the applet.

Related

Unfortunately app has stopped error in notification sending

import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import com.google.android.gms.gcm.GcmListenerService;
import com.htl.jsfshoppingfestival.DataBaseHandler;
public class MyGcmListenerService extends GcmListenerService {
private static final String TAG = "MyGcmListenerService";
private NotificationManager mNotificationManager;
Context ctx;
int countNotification=0;
public void onMessageReceived(String from, Bundle data) {
String message = data.getString("Message");
Log.d(TAG, "From: " + from);
Log.d(TAG, "Message: " + message);
// Toast.makeText(getApplicationContext(), "Notification :"+message, Toast.LENGTH_LONG).show();
// Toast.makeText(getApplicationContext(),from+message,Toast.LENGTH_LONG).show();
if (from.startsWith("/topics/")) {
// message received from some topic.
} else {
// normal downstream message.
}
// [START_EXCLUDE]
/**
* Production applications would usually process the message here.
* Eg: - Syncing with server.
* - Store message in local database.
* - Update UI.
*/
/**
* In some cases it may be useful to show a notification indicating to the user
* that a message was received.
*/
sendNotification(message);
// [END_EXCLUDE]
}
// [END receive_message]
/**
* Create and show a simple notification containing the received GCM message.
*
* #param message GCM message received.
*/
private void sendNotification(String message) {
DataBaseHandler db = new DataBaseHandler(this);
db.addMessage(message);
countNotification=db.getRowCount();
db.close();
Log.d("sender", "Broadcasting message");
Intent localIntent = new Intent("badge count");
// You can also include some extra data.
localIntent.putExtra("Count", countNotification);
LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
}
}
I did not get the message as a notification when I send the notification, my app shows:
Unfortunately app has stopped
In debugging I got message=null and app gives error.
In which block you got null? OnMessageReceived or SendNotification?
You need check the message not equal to null.
if(message != null && !message.trim().isEmpty())
{
sendNotification(message);
}

Java Card APDU Error

I am trying to send a simple APDU to a Java Card( I attached the simple code of the applet below).I already tested the applet in the Eclipse simulator but when I want to send an APDU to the applet it fails with the following error : send_APDU() returns 0x80206E00 (6E00: Wrong CLA byte.) .Applet is already installed into the card ( I used GpShell to do that ) .Here is the full output from the script I used to send the APDU.
D:\GPShell-1.4.4>GPShell.exe send_APDU.txt
establish_context
enable_trace
enable_timer
card_connect
command time: 15 ms
send_apdu -sc 0 -APDU b0000000010000
Command --> B0000000010000
Wrapped command --> B0000000010000
Response <-- 6E00
send_APDU() returns 0x80206E00 (6E00: Wrong CLA byte.)
command time: 860 ms
card_disconnect
command time: 31 ms
release_context
command time: 0 ms
Here is the full code of the applet.
public class Contor extends Applet {
private byte contor = 0;
private final static byte CLS=(byte)0xB0;
private final static byte INC=(byte)0x00;
private final static byte DEC=(byte)0x01;
private final static byte GET=(byte)0x02;
private final static byte INIT=(byte)0x03;
private Contor() {
}
public static void install(byte bArray[], short bOffset, byte bLength) throws ISOException {
new Contor().register();
}
public void process(APDU apdu) throws ISOException {
if(this.selectingApplet())return;
byte[] buffer = apdu.getBuffer();
if(buffer[ISO7816.OFFSET_CLA] != CLS)
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
switch(buffer[ISO7816.OFFSET_INS])
{
case INC:contor++; break;
case DEC:contor--; break;
case GET:
buffer[0] = contor;
apdu.setOutgoingAndSend((short)0,(short)1);
break;
case INIT:
apdu.setIncomingAndReceive();
contor = buffer[ISO7816.OFFSET_CDATA];
break;
}
}
In order to have a communication with your applet, you must select your applet first.
To do that you have two options. The first option is making your applet Default Selected in the applet installation phase and make it implicitly selected applet after each power up. The second option is sending SELECT APDU command concatenated with your applet AUD before sending other commands.
SELECT APDU Command = 00A40400 <AID Length> <AID>
Other wise, the entity that respond to your command, is not your applet and most probably it is the default Default-Selected applet, i.e. Card Manager.

How to send string data to socket connection via telnet or any other program?

I am trying to send and receive string data to socket connection via telnet, but I am not able to type or see anything in the telnet window. I am able to connect to the server via telnet, but not able to send the string data.
Is there any other alternate method to send string data over socket connection.
Telnet, unless it negotiates parameters to the contrary, does "remote echo" meaning that you won't see anything you type unless the server echos it back.
A lot of people use the term "Telnet" when really it is a raw socket connection that does no configuration negotiation upon connect.
If you're sending data from a file or source other than the keyboard (and even often when sending from the keyboard), you're better of using a program like socket or nc (netcat) which don't attempt to do any processing of the data stream and so provide simple 8-bit clean connections.
In the case of both those problems, you can simply redirect stdin from a file or echo a string to them through a pipe.
i have a example of a server that talks to with many telnet client.
You must use the class DataInputStream and DataOutputStream
You must use A Class Implements Runnable for establish multiple sessions
You must use a ServerSocket Class.
Good, this is the code of the main class called SocketServerExample:
import java.net.*;
import java.io.*;
import socketserverexample.ThreadServer;
/**
*
* #author JuanLuisHiciano
*/
public class SocketServerExample {
public static void main(String args[]) throws InterruptedException {
ServerSocket mi_servicio = null;
String linea_recibida;
DataInputStream entrada = null;
DataOutputStream salida = null;
Socket socket_conectado = null;
try {
mi_servicio = new ServerSocket(2017);
}
catch (IOException excepcion) {
System.out.println(excepcion);
}
try {
int n=1;
while(n<2){
socket_conectado = mi_servicio.accept();
System.out.println("Un cliente se a conectado "+socket_conectado.getPort());
entrada= new DataInputStream(socket_conectado.getInputStream());
String nombre = entrada.readUTF();
// Se instancia una clase para atender al cliente y se lanza en
// un hilo aparte.
Runnable nuevoCliente = new ThreadServer(nombre, socket_conectado); //Input and Output data Channels
Thread hilo = new Thread(nuevoCliente);
hilo.start();
}
salida.writeUTF("Fin de la conexion....");
salida.close();
entrada.close();
socket_conectado.close();
}
catch (IOException excepcion) {
System.out.println(excepcion);
}
}
}
ok,This run de Main Server with the UTP port (2017) and delivering sessions to other threads to receive new connections.
Good , below is the code of the class Called ThreadServer :
import java.net.*;
import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* #author JuanLuisHiciano
*/
public class ThreadServer implements Runnable{
DataInputStream entrada;
DataOutputStream salida;
Socket socket_conectado = null;
String linea_recibida;
String cliente;
ThreadServer(String cliente,Socket socket) {
socket_conectado = socket;
this.cliente=cliente;
}
#Override
public void run() {
int n=0;
while(n<3){
try {
salida = new DataOutputStream(socket_conectado.getOutputStream());
entrada = new DataInputStream(socket_conectado.getInputStream());
//System.out.println("Confirmando Conexion al cliente .....");
salida.writeUTF("Conexion Exitosa\n");
salida.writeUTF("Puede compartir un mensaje : ");
//recepcion de mensaje
linea_recibida = entrada.readUTF();
System.out.println(cliente+" dice: "+linea_recibida);
System.out.println(socket_conectado.getPort());
n++;
} catch (IOException ex) {
Logger.getLogger(ThreadServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
With this code you can talk to each of the clients connecting.
Goodbye Saludos de Republica Dominicana
I hope you serve something this code.

deviceToken of IOS Device

I am using Monotouch for mac and have gone through the steps to retrieve a provisioning profile certificate enabling push notification in the process. I have a working app and am now experimenting with apns-sharp and moon-apns but cant' figure out how to retrieve my device token. I'm hoping someone can provide me with detailed and straightforward steps to achieve this.
In your FinishedLaunching method, register the app for remote notifications, through the UIApplication object you get in it:
// Pass the UIRemoteNotificationType combinations you want
app.RegisterForRemoteNotificationTypes(UIRemoteNotificationType.Alert |
UIRemoteNotificationType.Sound);
Then, in your AppDelegate class, override the RegisteredForRemoteNotifications method:
public override void RegisteredForRemoteNotifications (UIApplication application, NSData deviceToken)
{
// The device token
byte[] token = deviceToken.ToArray();
}
You also have to override the FailedToRegisterForRemoteNotifications method, to handle the error, if any:
public override void FailedToRegisterForRemoteNotifications (UIApplication application, NSError error)
{
// Do something with the error
}
As of iOS deviceToken has changed. The following code worked for me to convert deviceToken as NSData to a string.
string deviceTokenString;
if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
{
deviceTokenString = BitConverter.ToString(deviceToken.ToArray()).Replace("-", string.Empty);
}
else
{
deviceTokenString = Regex.Replace(deviceToken.ToString(), "[^0-9a-zA-Z]+", string.Empty);
}
For me this was only half of the resolution. To use the DeviceToken from a webserver (PHP in my case), the DeviceToken needs to be a Hex String used in the PHP code for firing the Push Notification (e.g. as shown here: [Using PHP to send iOS Push Notifications via APNs
However, the NSdata object offers no simple way to provide that Hex String.
So my "RegisteredForRemoteNotifications" success handler is now:
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
// Get current device token
var DeviceToken = Tools.ByteToHex(deviceToken.ToArray());
string DeviceID = UIDevice.CurrentDevice.IdentifierForVendor.AsString();
System.Console.WriteLine("### UserNotification Device Token = " + DeviceToken + ", DeviceID = " + DeviceID);
// Get previous device token
var oldDeviceToken = NSUserDefaults.StandardUserDefaults.StringForKey("PushDeviceToken");
// Has the token changed?
if (string.IsNullOrEmpty(oldDeviceToken) || !oldDeviceToken.Equals(DeviceToken))
{
//### todo: Populate POSTdata set
//### todo: Send POSTdata to URL
// Save new device token
NSUserDefaults.StandardUserDefaults.SetString(DeviceToken, "PushDeviceToken");
}
}
And for the Byte to Hex Conversion:
public static string ByteToHex(byte[] data)
{
StringBuilder sb = new StringBuilder(data.Length * 2);
foreach (byte b in data)
{
sb.AppendFormat("{0:x2}", b);
}
return sb.ToString();
}
Now you can use the DeviceToken in PHP to create the PushNotification submission.

j2me bluetooth client. Function startInquiry nothing found

I develop simple j2me bluetooth client and have problem with bluetooth device search.
Function startInquiry nothing found.
Client : nokia 5220
Server : my pc with bluetooth adapter
All bluetooth devices is on.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import javax.microedition.midlet.*;
import javax.bluetooth.*;
import java.util.Vector;
import javax.microedition.lcdui.*;
/**
* #author Администратор
*/
public class Midlet extends MIDlet implements DiscoveryListener
{
private static Vector vecDevices=new Vector();
private static String connectionURL=null;
private LocalDevice localDevice;
private DiscoveryAgent agent;
private RemoteDevice remoteDevice;
private RemoteDevice[] devList;
private Display display;
private Form form;
public void startApp() {
display = Display.getDisplay(this);
form = new Form( "Client" );
try {
localDevice = LocalDevice.getLocalDevice();
} catch( BluetoothStateException e ) {
e.printStackTrace();
}
form.append("Address: "+localDevice.getBluetoothAddress()+"\n\n");
form.append("Name: "+localDevice.getFriendlyName()+"\n\n");
try {
agent = localDevice.getLocalDevice().getDiscoveryAgent();
form.append("Starting device inquiry... \n\n");
boolean si = agent.startInquiry(DiscoveryAgent.GIAC, this);
if ( si ) {
form.append("true");
} else {
form.append("false");
}
} catch( BluetoothStateException e ) {
}
int deviceCount = vecDevices.size();
if(deviceCount <= 0){
form.append("No Devices Found .");
}
else{
//print bluetooth device addresses and names in the format [ No. address (name) ]
form.append("Bluetooth Devices: ");
for (int i = 0; i < deviceCount; i++) {
remoteDevice=(RemoteDevice)vecDevices.elementAt(i);
form.append( remoteDevice.getBluetoothAddress() );
}
}
display.setCurrent(form);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {
//add the device to the vector
if(!vecDevices.contains(btDevice)){
vecDevices.addElement(btDevice);
}
}
public void inquiryCompleted(int discType)
{
}
//implement this method since services are not being discovered
public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
if(servRecord!=null && servRecord.length>0){
connectionURL=servRecord[0].getConnectionURL(0,false);
}
}
//implement this method since services are not being discovered
public void serviceSearchCompleted(int transID, int respCode) {
}
}
Not sure what the exact problem is, but you definitely don't want to be doing this in your midlet's startApp() method. This is a system lifecycle method, and should return quickly, but scanning for bluetooth devices will block it for a long time. Your startApp() method is tying up the device's resources which it could need for doing the actual scanning!
Refactor, so your device scanning is done in a new thread, then see what happens.
You seem to have misunderstood how the Bluetooth API works. The startInquiry method only starts the device discovery process and returns immediately afterwards, leaving the discovery running in the background. When devices are discovered, you get a callback of the deviceDiscovered method for each of them, and when the discovery process has completed, you get a callback of the inquiryCompleted method. So you need to move the accessing of the vecDevices member and the form manipulation from startApp to inquiryCompleted to be able to actually show the discovered information.
You say all devices are on - but also check if all devices are discoverable.
I've made this mistake before myself!
Lookup the method LocalDevice.setDiscoverable() if you want to toggle between modes programatically.

Resources