10 Replies Latest reply on Aug 20, 2011 11:01 AM by safarmer Branched to a new discussion.

    Creating Signature

    861148
      Hello i am trying to create a signature in java card 2.1.1

      I tried to create the signature the following way
      signature = Signature.getInstance(Signature.ALG_RSA_SHA_PKCS1, false);
      byte[] testSig = new byte[20];
      byte[] test = {0x01, 0x02, 0x04, 0x05, 0x06, 0x07};
      signature.sign(test, (short) 0, (short)test.length, testSig, (short) 0);
      But i got a CryptoException with ReasonCode IllegalUse. If i hash the input at first i got the same error. What is my mistake ??

      Thanks for answering.
        • 1. Re: Creating Signature
          safarmer
          Hi,

          Have you initialised the signature instance with a signing key?

          Cheers,
          Shane
          • 2. Re: Creating Signature
            861148
            Yes i did it. The signing Key is a RSAPrivateKey privateKeySmartCard.
            kp = new KeyPair(KeyPair.ALG_RSA_CRT, KeyBuilder.LENGTH_RSA_2048);
            kp.genKeyPair();
            privateKeySmartCard = (RSAPrivateKey) kp.getPrivate();
            signature.init(privateKeySmartCard, Signature.MODE_SIGN);
            Cheers
            • 3. Re: Creating Signature
              safarmer
              Hi,

              I probably should have paid more attention to your original code. You need to sign into a 256 byte buffer as the sign operation is a hash and then RSA encryption. The encrypted text is the same length as the modulus of you key (2048 bits) so you need enough space for the result.

              Cheers,
              Shane
              • 4. Re: Creating Signature
                861148
                Hi,

                i increase the size of the array but i still get the IllegalUse Reasoncode.
                • 5. Re: Creating Signature
                  safarmer
                  can you post the complete code? A fully self contained working example would be nice.

                  Cheers.
                  Shane
                  • 6. Re: Creating Signature
                    safarmer
                    The following works for me:
                    import javacard.framework.APDU;
                    import javacard.framework.Applet;
                    import javacard.framework.ISO7816;
                    import javacard.framework.ISOException;
                    import javacard.security.KeyBuilder;
                    import javacard.security.KeyPair;
                    import javacard.security.Signature;
                    
                    /**
                     * @author shane
                     * 
                     */
                    public class Main extends Applet {
                        private KeyPair keys = null;
                        private Signature sig;
                         
                         byte[] testSig = new byte[256];
                         byte[] test = {0x01, 0x02, 0x04, 0x05, 0x06, 0x07};
                        
                    
                        public Main() {
                            sig = Signature.getInstance(Signature.ALG_RSA_SHA_PKCS1, false);
                        }
                    
                        public static void install(byte[] bArray, short bOffset, byte bLength) {
                            // GP-compliant JavaCard applet registration
                            new Main().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
                        }
                    
                        public void process(APDU apdu) {
                            // Good practice: Return 9000 on SELECT
                            if (selectingApplet()) {
                                return;
                            }
                    
                            byte[] buf = apdu.getBuffer();
                            switch (buf[ISO7816.OFFSET_INS]) {
                                case (byte) 0x00:
                                     if(keys == null) {
                                          keys = new KeyPair(KeyPair.ALG_RSA_CRT, KeyBuilder.LENGTH_RSA_2048);
                                          keys.genKeyPair();
                                     }
                                     
                                     sig.init(keys.getPrivate(), Signature.MODE_SIGN);
                                     short len = sig.sign(test, (short) 0, (short) test.length, testSig, (short) 0);
                                     apdu.setOutgoing();
                                     apdu.setOutgoingLength(len);
                                     apdu.sendBytesLong(testSig, (short) 0, len);
                                     break;
                                    
                                default:
                                    // good practice: If you don't know the INStruction, say so:
                                    ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
                            }
                        }
                    }
                    You wouldn't happen to be using a Cyberflex card would you? There have been recent discussions on this cards signature implementation being broken. If so, pass in exactly 20 bytes and it should work, but you probably wont be able to verify signatures.

                    Cheers,
                    Shane
                    • 7. Re: Creating Signature
                      861148
                      Of course i can, here it is
                      package smartcard;
                      
                      import javacard.framework.APDU;
                      import javacard.framework.Applet;
                      import javacard.framework.ISO7816;
                      import javacard.framework.ISOException;
                      import javacard.security.CryptoException;
                      import javacard.security.KeyBuilder;
                      import javacard.security.KeyPair;
                      import javacard.security.RSAPrivateKey;
                      import javacard.security.Signature;
                      
                      public class SigningExample extends Applet {
                      
                          private final static byte SmartCard_CLA = (byte) 0xB0;
                          private final static byte INS_SIGN_DATA = (byte) 0x60;
                          private final static short SW_CRYPTO_EXCEPTION = 0x63A0;
                          private final static short SW_NULLPOINTER_EXCEPTION = 0x63C0;
                          private final static short SW_ARRAY_EXCEPTION = 0x63D0;
                          private RSAPrivateKey privateKeySmartCard;
                          private Signature signature;
                          private KeyPair kp;
                      
                          public static void install(byte[] bArray, short bOffset, byte bLength) {
                              new SigningExample().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
                          }
                      
                          private SigningExample() {
                              try {
                                  kp = new KeyPair(KeyPair.ALG_RSA_CRT, KeyBuilder.LENGTH_RSA_2048);
                                  signature = Signature.getInstance(Signature.ALG_RSA_SHA_PKCS1, false);
                      
                                  kp.genKeyPair();
                                  privateKeySmartCard = (RSAPrivateKey) kp.getPrivate();
                      
                      
                              } catch (CryptoException ex) {
                                  ISOException.throwIt((short) (SW_CRYPTO_EXCEPTION + ex.getReason()));
                              }
                          }
                      
                          public boolean select() {
                              return true;
                          }
                      
                          public void deselect() {
                          }
                      
                          public void process(APDU apdu) {
                              // APDU object carries a byte array (buffer) to transfer  incoming
                              // and outgoing APDU header and data bytes between the card and the host
                      
                              // at this point, only the first fine bytes
                              // [CLA, INS, P1, P2, P3] are available in the APDU buffer
                              byte[] buffer = apdu.getBuffer();
                      
                              // return if the ADPU is the SELECT command
                              if (selectingApplet()) {
                                  return;
                              }
                      
                              // verify the CLA byte
                              if (buffer[ISO7816.OFFSET_CLA] != SmartCard_CLA) {
                                  ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
                              }
                              short len = apdu.setIncomingAndReceive(); // This is the amount of data read from the OS.
                      
                              byte ins = buffer[ISO7816.OFFSET_INS];
                              short lc = (short) (buffer[ISO7816.OFFSET_LC] & 0x00ff); // this is the LC from the APDU.
                      
                              // get all bytes from the buffer
                              while (len < lc) {
                                  len += apdu.receiveBytes(len);
                              }
                      
                              switch (ins) {
                                  case INS_SIGN_DATA:
                                      signData();
                                      break;
                                  default:
                                      // good practice: If you don't know the INStruction, say so:
                                      ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
                              }
                          }
                      
                          private void signData() {
                              try {
                                  signature.init(privateKeySmartCard, Signature.MODE_SIGN);
                                  byte[] test = {0x01, 0x02, 0x04, 0x05, 0x06, 0x07};
                                  byte[] testSig = new byte[256];
                                  signature.sign(test, (short) 0, (short) test.length, testSig, (short) 0);
                              } catch (CryptoException ex) {
                                  ISOException.throwIt((short) (SW_CRYPTO_EXCEPTION + ex.getReason()));
                              } catch (ArrayIndexOutOfBoundsException ex) {
                                  ISOException.throwIt(SW_ARRAY_EXCEPTION);
                              } catch (NullPointerException ex) {
                                  ISOException.throwIt(SW_NULLPOINTER_EXCEPTION);
                              }
                          }
                      }
                      
                      Cheers
                      • 8. Re: Creating Signature
                        safarmer
                        Hi,

                        What card are you using? Have you tried my test code?

                        Cheers,
                        Shane
                        • 9. Re: Creating Signature
                          861148
                          Hi,

                          i tested your code, but it does not work. So i tried your hint with the input size of 20 bytes and now it works.

                          Edited by: 858145 on 19.08.2011 11:23
                          • 10. Re: Creating Signature
                            safarmer
                            Then you have a cyberflex 64K card with a broken signature implementation. You should really get a different card if you want signatures to work. This has been discussed recently.

                            Cheers,
                            Shane