AN156
8 of 23
Signing Data with Coprocessor at Container-Level Figure 13
For the data in the account file byte array to be a valid account file, it must have an inverted, two-byte
CRC16 at the end of the file. More detail on what makes a valid file on the 1-Wire file structure can be
found in AN114.
Adding Inverted CRC16 to 1-Wire File Figure 14
Writing the account file to the data page of the DS1963S user token is fairly easy. There is a utility
function provided in the container class for writing a page of data, the exact function which is used to
write the account data to the coprocessor for signing in the above code block.
2.3 Authenticating the User Token
Authenticating the user token involves a simple challenge-response scheme. First, the coprocessor is used
to generate a 3-byte, pseudo-random challenge. This challenge is then written to the scratchpad of the
user token and the Read Authenticated Page command is issued (see DS1963S data sheet). This returns
the entire contents of the memory page followed by the value of the write cycle counter for the page and
the write cycle counter for the secret location. The scratchpad of the DS1963S user token will contain the
20-byte SHA result of the user’s unique authentication secret, the page number the data was read from,
the serial number of the user token, and the random challenge. The coprocessor is then used to reproduce
this SHA result, ensuring that the user token is a valid member of the system.
Authenticating User Token with SHADebit Figure 15
The process for verifying a user is the same for both signed and unsigned transactions. Naturally, this can
be broken down into simple steps using the SHAiButtonCopr class and the SHAiButton
User class. The
code snippet presented in Figure 16 demonstrates the basic implementation of the user verification
method in the transaction classes (minus the error checking).
/* calculate the inverted CRC16 */
int crc = ~CRC16.compute(acctData, 0, acctData[0]+1, acctPage);
/* now the file is ready to be written */
acctData[30] = (byte)crc;
acctData[31] = (byte)(crc>>8);
/* write the account data to the signing page of the coprocessor */
coprDevice.writeDataPage(signPageNumber, acctData);
/* write the signScratchpad to the scratchpad of the coprocessor */
coprDevice.writeScratchpad(signPageNumber, 0, acctData, 0, 32);
/* sign the data and read the signature*/
coprDevice.SHAFunction(coprDevice.SIGN_DATA_PAGE, signPageNumber << 5);
coprDevice.readScratchpad(signScratchpad, 0);
/* place the resulting signature in the certificate */
System.arraycopy(signScratchpad, 8, acctData, 2, 20);
/* Verify user tokens authentication response, same for signed and unsigned */
SHADebit debit = new SHADebit(copr, 65536, 2);
debit.verifyUser(user18);