1

I am using .NET smart card, it has the same concepts of .NET remoting.

So my smartcard (as a server) has this service:

public class MyService : MarshalByRefObject
{
     string a = "abC";

    public byte[] MySampleMethod()
    {
        MyService obj = new MyService();
        return help.ObjectToByteArray( obj);
    }}}

and this is ObjectToByteArray(obj)

public static byte[] ObjectToByteArray(MyService obj)
    {
        if (obj == null)
            return null;
        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream ms = new MemoryStream(0);
        bf.Serialize(ms, obj);
        return ms.ToArray();
    }

As for client :

    public static void Main()
    {
        // create and register communication channel
        APDUClientChannel channel = new APDUClientChannel();
        ChannelServices.RegisterChannel(channel);

        // get the referenc to remote object
        MyService service = (MyService)Activator.GetObject(typeof(MyService), URL);

        // invoke the remote method
        byte[] result = service.MySampleMethod();

        MyService obj = ByteArrayToObject(result);

        Console.WriteLine(result[0]);
        Console.ReadLine();
        // unregister the communication channel
        ChannelServices.UnregisterChannel(channel);
    }

ByteArrayToObject

    public static MyService ByteArrayToObject(byte[] arrBytes)
    {
        MemoryStream memStream = new MemoryStream(0);
        BinaryFormatter binForm = new BinaryFormatter();
        memStream.Write(arrBytes, 0, arrBytes.Length);

        memStream.Seek(0, SeekOrigin.Begin);
        //memStream.Position = 0;
        MyService obj = (MyService)binForm.Deserialize(memStream);
        return obj;
    }

The problem is when I want to Deserialize the object.

I test this string "ABCDE" , serialize it in the card and the result hex is :

1C-5D-D2-00-27-11-02-00-00-00-05-00-00-00-05-00-00-00-01-41-00-42-00-43-00-44-00‌​-45-00

WHILE the result when i serialize it on my pc is :

00-01-00-00-00-FF-FF-FF-FF-01-00-00-00-00-00-00-00-06-01-00-00-00-05-41-42-43-44‌​-45-0B.

So on my PC application, deserializing the second one works well, but when i deserialize the first string (from smart card) I got :

"The input stream is not a valid binary format. The starting contents (in bytes) are: 1C-5D-D2-00-27-11-02-00-00-00-05-00-00-00-05-00-00 ..."

Wajdy Essam
  • 4,280
  • 3
  • 28
  • 33
hum.
  • 25
  • 7
  • You are missing the 'T' in the above hexadecimal string :P, seriously, I'm not a .NET card expert, but how does the client know what kind of object is serialized? Please show the full binary format if possible. – Maarten Bodewes Mar 05 '13 at 23:13
  • what do you mean by "how the client know" , actually i add reference of server .exe in client side , if this what you are asking for – hum. Mar 07 '13 at 10:22
  • Do you have more data? The first byte is missing from above "starting contents", it seems some kind of type indicator, it starts with the ASCII encoding of `(T)ypeLoadSTEx`... Hmm, probably some kind of exception instead of the object? – Maarten Bodewes Mar 07 '13 at 23:16
  • I tried to serialize string : "ABCDE" in the card and the result hex is : 1C-5D-D2-00-27-11-02-00-00-00-05-00-00-00-05-00-00-00-01-41-00-42-00-43-00-44-00-45-00 , WHILE the result when i serialize it on my pc is : 00-01-00-00-00-FF-FF-FF-FF-01-00-00-00-00-00-00-00-06-01-00-00-00-05-41-42-43-44-45-0B. So on my PC application, deserializing the second one works well, but when i deserialize the first string (from smart card) I got : "The input stream is not a valid binary format. The starting contents (in bytes) are: 1C-5D-D2-00-27-11-02-00-00-00-05-00-00-00-05-00-00 ..." – hum. Mar 09 '13 at 20:56
  • Hum, most people here cannot debug on .NET card, and the hex strings you've put in now are completely different from the one you've shown before. .NET smartcards don't have much presence yet (as far as I've seen) so it may be tricky to answer this question. – Maarten Bodewes Mar 09 '13 at 22:10

1 Answers1

2

Gemalto.NET Smart Card supports only marshalling by reference, so any primitive and struct types you have in the server can be accessed in client without the need of serialization because you already have the reference to the object through remote invocation:

so first register your service:

public class MyServer
    {
        /// <summary>
        /// specify the exposed remote object URI.
        /// </summary>
        private const string REMOTE_OBJECT_URI = "MyService.uri";

        /// <summary>
        /// Register the server onto the card.
        /// </summary>
        /// <returns></returns>
        public static int Main()
        {
            // Register the channel the server will be listening to.
            ChannelServices.RegisterChannel(new APDUServerChannel());

            // Register this application as a server            
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(MyService), REMOTE_OBJECT_URI, WellKnownObjectMode.Singleton);

            return 0;
        }
    }

and then define the service class, and you can return primitive types and struct, for gemalto docs:

Types that can be marshalled include the basic value types (byte, short, char, int, long, string, etc), structs, arrays of basic types, and MemoryStreams

public class MyService : MarshalByRefObject
    {
        public struct Person
        {
            public string name;
            public int id;

            public Person(int id, string name)
            {
                this.name = name;
                this.id = id;
            }

            public string getName()
            {
                return this.name;
            }

            public int getId()
            {
                return this.id;
            }
        }

        public string MySampleMethod()
        {
            return "This is return String";
        }

        public Person getPerson()
        {
            Person person = new Person(15, "Wajdy");
            return person;
        }
    }

Now in the client application, you will have the reference to service object and you can call the methods normally:

public class MyClient
    {
        private const string URL = "apdu://selfdiscover/MyService.uri";

        public static void Main()
        {
            // create and register communication channel
            APDUClientChannel channel = new APDUClientChannel();
            ChannelServices.RegisterChannel(channel);

            // get the referenc to remote object
            MyService service = (MyService)Activator.GetObject(typeof(MyService), URL);
            Console.WriteLine(service.MySampleMethod());

            MyService.Person person = service.getPerson();
            Console.WriteLine(person.getName());
            Console.WriteLine(person.getId());

            Console.ReadLine();

            // unregister the communication channel
            ChannelServices.UnregisterChannel(channel);
        }
    }
Wajdy Essam
  • 4,280
  • 3
  • 28
  • 33