Commit c9d0b00a authored by Josh Ji's avatar Josh Ji

setPin, getPinToken, usePinToken and some dummy or unnecessary stuff while testing and debugging

parent fc423e41
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -26,6 +26,7 @@ public class AuthenticatorGetAssertion {
byte[] clientDataHash;
boolean[] options;
PublicKeyCredentialDescriptor[] allow;
private byte[] pinUvAuthParam;
public AuthenticatorGetAssertion(CBORDecoder decoder) throws UserException {
......@@ -117,8 +118,10 @@ public class AuthenticatorGetAssertion {
decoder.skipEntry();
break;
case 0x06:
// Pin stuff
decoder.skipEntry();
// Pin UV Auth Param // 0x06
pinUvAuthParam = new byte[16];
if(decoder.readByteString(pinUvAuthParam, (short)0 ) < (short)16)
UserException.throwIt(CTAP2_ERR_PIN_INVALID);
break;
case 0x07:
// Pin protocol
......
......@@ -27,6 +27,7 @@ public class AuthenticatorMakeCredential {
private PublicKeyCredentialUserEntity user;
private PublicKeyCredentialParams params;
private boolean[] options = new boolean[2];
private byte[] pinUvAuthParam;
public PublicKeyCredentialDescriptor[] exclude;
......@@ -282,6 +283,14 @@ public class AuthenticatorMakeCredential {
}
decoder.skipEntry();
break;
case (short)8: // pinUvAuthToken
pinUvAuthParam = new byte[16];
if(decoder.readByteString(pinUvAuthParam, (short)0 ) < (short)16)
UserException.throwIt(CTAP2_ERR_PIN_INVALID);
break;
case (short)9: // pinProtocol
short pinProtocol = decoder.readInt8();
break;
default:
// Skip it transparently
decoder.skipEntry();
......@@ -290,12 +299,16 @@ public class AuthenticatorMakeCredential {
}
}
if(pinUvAuthParam == null){
UserException.throwIt(CTAP2_ERR_PIN_INVALID);
}
// Check we've got stuff like the clientDataHash
if(dataHash == null || rp == null || user == null || params == null) {
UserException.throwIt(CTAP2_ERR_MISSING_PARAMETER);
}
// We're done, I guess
}
......@@ -319,6 +332,14 @@ public class AuthenticatorMakeCredential {
return (exclude != null && exclude.length > 0);
}
/**
*
* @return pinUvAuthToken
*/
public byte[] getPinUvAuthParam(){
return pinUvAuthParam;
}
/**
* Reads the clientDataHash into a buffer.
*
......@@ -326,9 +347,8 @@ public class AuthenticatorMakeCredential {
* @param outOff the offset to begin at.
* @return the length of the data read out.
*/
public short getDataHash(byte[] outBuf, short outOff) {
Util.arrayCopy(dataHash, (short) 0, outBuf, outOff, (short) dataHash.length);
return (short) dataHash.length;
public byte[] getDataHash() {
return dataHash;
}
}
......@@ -66,6 +66,10 @@ public class CTAP2 extends Applet implements ExtendedLength {
// private final KeyPair ecDhKeyPair;
// private final boolean[] ecDhSet;
private PinUvAuthProtocolOne pinUvAuthProtocolOne;
private short pinLength = 0;
private byte[] pin;
private final byte[] currentStoredPIN = new byte[16]; // LEFT(SHA-256(pin), 16)
private final byte[] pinToken = new byte[32];
// INS
......@@ -101,9 +105,9 @@ public class CTAP2 extends Applet implements ExtendedLength {
// this uniquely identifies the type of authenticator we have built.
// If you're reusing this code, please generate your own GUID and put it here -
// this is unique to manufacturer and device model.
public static final byte[] aaguid = {
(byte) 't', (byte) 'e', (byte) 's', (byte) 't', (byte) 'g', (byte) 'u', (byte) 'i', (byte) 'd',
(byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
public static final byte[] aaguid = {//yubikey 5c nfc aaguid
(byte) 0x2f, (byte) 0xc0, (byte) 0x57, (byte) 0x9f, (byte) 0x81, (byte) 0x13, (byte) 0x47, (byte) 0xea,
(byte) 0xb1, (byte) 0x16, (byte) 0xbb, (byte) 0x5a, (byte) 0x8d, (byte) 0xb9, (byte) 0x20, (byte) 0x2a, };
private CTAP2() {
......@@ -162,11 +166,11 @@ public class CTAP2 extends Applet implements ExtendedLength {
public void process(APDU apdu) throws ISOException {
byte[] buffer = apdu.getBuffer();
// return FIDO2 String when selecting
// return version String when selecting
if (selectingApplet()) {
Util.arrayCopyNonAtomic(Utf8Strings.UTF8_FIDO2, (short) 0, buffer, (short) 0,
(short) Utf8Strings.UTF8_FIDO2.length);
apdu.setOutgoingAndSend((short) 0, (short) Utf8Strings.UTF8_FIDO2.length);
Util.arrayCopyNonAtomic(Utf8Strings.UTF8_U2F_V2, (short) 0, buffer, (short) 0,
(short) Utf8Strings.UTF8_U2F_V2.length);
apdu.setOutgoingAndSend((short) 0, (short) Utf8Strings.UTF8_U2F_V2.length);
return;
}
......@@ -486,6 +490,11 @@ public class CTAP2 extends Applet implements ExtendedLength {
}
public void authMakeCredential(APDU apdu, short bufLen) {
if(pinRetries < (short)1){
returnError(apdu, CTAP2_ERR_PIN_AUTH_BLOCKED);
return;
}
// Init the decoder
cborDecoder.init(dataBuffer, (short) 1, bufLen);
// create a credential object
......@@ -512,8 +521,25 @@ public class CTAP2 extends Applet implements ExtendedLength {
return;
}
if (authenticatorMakeCredential.isResident()) {
// Check if a credential exists on the excluded list
idSecret.writeTempBuffer(pinUvAuthProtocolOne.authenticate(pinToken, authenticatorMakeCredential.getDataHash()), (short)0);
idSecret.writeTempBuffer(authenticatorMakeCredential.getPinUvAuthParam(), (short)64);
// verify the pin UV Auth token
if(pinUvAuthProtocolOne.verify(
pinToken,
authenticatorMakeCredential.getDataHash(),
authenticatorMakeCredential.getPinUvAuthParam()
)
){
pinRetries = MAX_PIN_RETRIES;
}else{
pinRetries--;
returnError(apdu, CTAP2_ERR_PIN_AUTH_INVALID);
return;
}
// Check if a credential exists on the excluded list
if (authenticatorMakeCredential.isExclude() && isPresent(authenticatorMakeCredential.exclude)) {
// Throw the error
returnError(apdu, CTAP2_ERR_CREDENTIAL_EXCLUDED);
......@@ -731,14 +757,15 @@ public class CTAP2 extends Applet implements ExtendedLength {
switch(clientPINCommand.getSubCommandCode()){
case SUBCOMMAND_GET_PIN_RETRIES:
dataBuffer[0] = 0x00; // 0x00 : response success code
dataBuffer[0] = CTAP1_ERR_SUCCESS; // 0x00 : response success code
cborEncoder.init(dataBuffer, (short)1, (short)(1199));
cborEncoder.startMap((short)1);
cborEncoder.encodeUInt8(ClientPINResponse.PIN_RETRIES);
cborEncoder.encodeUInt8(pinRetries);
sendLongChaining(apdu, cborEncoder.getCurrentOffset());
break;
case SUBCOMMAND_GET_KEY_AGREEMENT:
dataBuffer[0] = 0x00; // 0x00 : response success code
dataBuffer[0] = CTAP1_ERR_SUCCESS; // 0x00 : response success code
cborEncoder.init(dataBuffer, (short) 1, (short) 1199);
// Start a map
cborEncoder.startMap((short) 1);
......@@ -771,21 +798,66 @@ public class CTAP2 extends Applet implements ExtendedLength {
sendLongChaining(apdu, cborEncoder.getCurrentOffset());
break;
case SUBCOMMAND_SET_PIN:
// idSecret.writeTempBuffer(pinUvAuthProtocolOne.ecdh(clientPINCommand.getKeyAgreement()));
idSecret.writeTempBuffer(
pinUvAuthProtocolOne.decrypt(
pinUvAuthProtocolOne.ecdh(
clientPINCommand.getKeyAgreement()),
byte[] paddedPin = pinUvAuthProtocolOne.decrypt(
pinUvAuthProtocolOne.ecdh(clientPINCommand.getKeyAgreement()),
clientPINCommand.getNewPinEnc()
)
);
for(short i = 0 ; i < (short)paddedPin.length ; i ++){
if(paddedPin[i] == 0x00) {
pinLength = i;
break;
}
}
pin = new byte[pinLength];
Util.arrayCopy(paddedPin, (short)0, pin, (short)0, (short)pin.length);
// idSecret.writeTempBuffer(pin, (short)0);
byte[] hashedPin = pinUvAuthProtocolOne.hashPin(pin);
Util.arrayCopy(hashedPin, (short)0, currentStoredPIN, (short)0, (short)16);
// idSecret.writeTempBuffer(currentStoredPIN, (short)10);
isClientPinSet = true;
fidoInfo = null;
pinRetries = MAX_PIN_RETRIES;
JCSystem.requestObjectDeletion();
break;
case SUBCOMMAND_CHANGE_PIN:
break;
case SUBCOMMAND_GET_PIN_TOKEN:
byte[] hashedPin_leftHalf;
byte[] sharedSecret = pinUvAuthProtocolOne.ecdh(clientPINCommand.getKeyAgreement());
hashedPin_leftHalf = pinUvAuthProtocolOne.decryptHashedPin(
sharedSecret, clientPINCommand.getPinHashEnc()
);
// idSecret.writeTempBuffer(hashedPin_leftHalf, (short)36);
for(short i = 0; i < (short)hashedPin_leftHalf.length ; i++){
if(hashedPin_leftHalf[i] != currentStoredPIN[i]){
pinRetries--;
UserException.throwIt(CTAP2_ERR_PIN_INVALID);
break;
}
}
RandomData r = Random.getInstance();
r.nextBytes(pinToken, (short)0, (short)pinToken.length);
// idSecret.writeTempBuffer(pinToken, (short) 0);
byte[] pinTokenEnc = pinUvAuthProtocolOne.encrypt(sharedSecret, pinToken);
dataBuffer[0] = CTAP1_ERR_SUCCESS;
cborEncoder.init(dataBuffer, (short)1, (short)1199);
cborEncoder.startMap((short)1);
cborEncoder.encodeUInt8((byte)0x02);
cborEncoder.encodeByteString(pinTokenEnc, (short)0, (short)32);
sendLongChaining(apdu, cborEncoder.getCurrentOffset());
break;
case SUBCOMMAND_GET_PIN_UV_AUTH_TOKEN_UV:
break;
......@@ -944,40 +1016,57 @@ public class CTAP2 extends Applet implements ExtendedLength {
// Create the authGetInfo - 0x00 is success
dataBuffer[0] = 0x00;
cborEncoder.init(dataBuffer, (short) 1, (short) 1199);
cborEncoder.startMap((short) 6);
cborEncoder.startMap((short) 8);
// 0x01, versions
cborEncoder.encodeUInt8((byte) 0x01);
// Value is an array of strings
cborEncoder.startArray((short) 1);
cborEncoder.startArray((short) 2);
// Type 1, FIDO2
cborEncoder.encodeTextString(Utf8Strings.UTF8_FIDO2, (short) 0, (short) 8);
cborEncoder.encodeTextString(Utf8Strings.UTF8_FIDO2, (short) 0, (short) Utf8Strings.UTF8_FIDO2.length);
cborEncoder.encodeTextString(Utf8Strings.UTF8_FIDO_2_1_PRE, (short) 0, (short) Utf8Strings.UTF8_FIDO_2_1_PRE.length);
// 0x02, Extensions
cborEncoder.encodeUInt8((byte) 0x02);
cborEncoder.startArray((short) 2);
cborEncoder.encodeTextString(Utf8Strings.UTF8_PRLab, (short)0, (short)Utf8Strings.UTF8_PRLab.length);
cborEncoder.encodeTextString(Utf8Strings.UTF8_credProtect, (short)0, (short)Utf8Strings.UTF8_credProtect.length);
cborEncoder.encodeTextString(Utf8Strings.UTF8_hmac_secret, (short)0, (short)Utf8Strings.UTF8_hmac_secret.length);
// cborEncoder.encodeTextString(Utf8Strings.UTF8_PRLab, (short)0, (short)Utf8Strings.UTF8_PRLab.length);
// 0x03, AAGUID,
cborEncoder.encodeUInt8((byte) 0x03);
cborEncoder.encodeByteString(aaguid, (short) 0, (short) 16);
// 0x04, Options,
cborEncoder.encodeUInt8((byte) 0x04);
// Map of 3
cborEncoder.startMap((short) 4);
cborEncoder.startMap((short) 5);
// Rk
cborEncoder.encodeTextString(Utf8Strings.UTF8_RK, (short) 0, (short)Utf8Strings.UTF8_RK.length);
cborEncoder.encodeBoolean(true);
// UP
cborEncoder.encodeTextString(Utf8Strings.UTF8_UP, (short) 0, (short)Utf8Strings.UTF8_UP.length);
cborEncoder.encodeBoolean(true);
// // UV
// cborEncoder.encodeTextString(Utf8Strings.UTF8_UV, (short) 0, (short)Utf8Strings.UTF8_UV.length);
// cborEncoder.encodeBoolean(true);
// plat
cborEncoder.encodeTextString(Utf8Strings.UTF8_plat, (short) 0, (short)Utf8Strings.UTF8_plat.length);
cborEncoder.encodeBoolean(false);
// clientPin
cborEncoder.encodeTextString(Utf8Strings.UTF8_CLIENT_PIN, (short) 0, (short)Utf8Strings.UTF8_CLIENT_PIN.length);
cborEncoder.encodeBoolean(isClientPinSet);
// UV
cborEncoder.encodeTextString(Utf8Strings.UTF8_UV, (short) 0, (short)Utf8Strings.UTF8_UV.length);
// credentialMgmtPreview
cborEncoder.encodeTextString(Utf8Strings.UTF8_CREDENTIAL_MGMT_PREVIEW, (short) 0, (short)Utf8Strings.UTF8_CREDENTIAL_MGMT_PREVIEW.length);
cborEncoder.encodeBoolean(true);
// Max msg size, 0x05
cborEncoder.encodeUInt8((byte) 0x05);
cborEncoder.encodeUInt16((short) 1200);
// pin Protocols, 0x06
cborEncoder.encodeUInt8((byte) 0x06);
cborEncoder.startArray((short)0x01);
cborEncoder.encodeUInt8((byte) 0x01);
// transports, 0x09
cborEncoder.encodeUInt8((byte) 0x09);
cborEncoder.startArray((short)0x02);
cborEncoder.encodeTextString(Utf8Strings.UTF8_nfc, (short) 0, (short)Utf8Strings.UTF8_nfc.length);
cborEncoder.encodeTextString(Utf8Strings.UTF8_usb, (short) 0, (short)Utf8Strings.UTF8_usb.length);
// minPINLength, 0x0D
cborEncoder.encodeUInt8((byte) 0x0D);
cborEncoder.encodeUInt8((byte) 0x04);
......
......@@ -21,7 +21,7 @@ public class ClientPINCommand {
private byte[] y = new byte[32]; // y-coordinate
private byte[] pinUvAuthParam = new byte[64]; // byte string
private byte[] newPinEnc = new byte[64]; // byte string
private byte[] pinHashEnc = new byte[32]; // byte string
private byte[] pinHashEnc = new byte[16]; // byte string, aes256
private byte permissions; // unsigned int
private byte[] rpId = new byte[64]; // text string
byte[] scratch = JCSystem.makeTransientByteArray((short)64, JCSystem.CLEAR_ON_RESET);
......@@ -61,15 +61,15 @@ public class ClientPINCommand {
break;
case PARAMETER_PIN_UV_AUTH_PARAM:
// cborDecoder.readByteString(pinUvAuthParam, (short) 0);
cborDecoder.skipEntry();
cborDecoder.readByteString(pinUvAuthParam, (short) 0);
// cborDecoder.skipEntry();
break;
case PARAMETER_NEW_PIN_ENC:
cborDecoder.readByteString(newPinEnc, (short) 0);
break;
case PARAMETER_PIN_HASH_ENC:
// cborDecoder.readByteString(pinHashEnc, (short) 0);
cborDecoder.skipEntry();
cborDecoder.readByteString(pinHashEnc, (short) 0);
// cborDecoder.skipEntry();
break;
case PARAMETER_PERMISSIONS:
// permissions = cborDecoder.readInt8();
......@@ -93,6 +93,10 @@ public class ClientPINCommand {
return subCommandCode;
}
/**
*
* @return 0x04 || x-coordinate || y-coordinate
*/
public byte[] getKeyAgreement() {
keyAgreement[0] = 0x04;
Util.arrayCopy(x, (short)0, keyAgreement, (short)1, (short)x.length);
......
......@@ -121,14 +121,19 @@ public class IDSecret {
return tempBufferLength;
}
public void writeTempBuffer(byte[] inputBuffer){
if((short)inputBuffer.length > (short)tempBuffer.length){
/**
*
* @param inputBuffer the buffer copy from
* @param offset output offset
*/
public void writeTempBuffer(byte[] inputBuffer, short offset){
if((short)(inputBuffer.length + offset) > (short)tempBuffer.length){
tempBuffer[0] = 'T'; // too
tempBuffer[1] = 'L'; // long
Util.setShort(tempBuffer, (short)2, (short)inputBuffer.length); // input length
return;
}
Util.arrayCopy(inputBuffer, (short)0, tempBuffer, (short)0, (short)inputBuffer.length);
Util.arrayCopy(inputBuffer, (short)0, tempBuffer, offset, (short)inputBuffer.length);
}
/**
......
......@@ -10,5 +10,5 @@ public abstract class PinUvAuthProtocol {
public abstract byte[] getPublicKey();
public abstract byte[] decapsulate(COSEKey peerCoseKey);
public abstract byte[] decrypt(byte[] sharedSecret, byte[] cipherText);
public abstract void verify(byte[] key, byte[] message, byte[] signature);
public abstract boolean verify(byte[] key, byte[] message, byte[] signature);
}
package com.josh.vku2f;
import javacard.framework.JCSystem;
import javacard.framework.Util;
import javacard.security.*;
import javacardx.crypto.Cipher;
import jdk.nashorn.internal.ir.Block;
public class PinUvAuthProtocolOne extends PinUvAuthProtocol{
......@@ -73,8 +75,20 @@ public class PinUvAuthProtocolOne extends PinUvAuthProtocol{
return null;
}
/**
*
* @param key shared key from kdf()
* @param plaintext pinToken
* @return encrypted pinToken
*/
public byte[] encrypt(byte[] key, byte[] plaintext){
return null;
byte[] cipherText = new byte[32];
aesKey.setKey(key, (short)0);
aesEncrypt.init(aesKey, Cipher.MODE_ENCRYPT, IV_ZERO_AES, (short)0, (short)IV_ZERO_AES.length);
aesEncrypt.update(plaintext, (short)0, (short)16, cipherText, (short)0);
aesEncrypt.doFinal(plaintext, (short)16, (short)16, cipherText, (short)16);
return cipherText;
}
@Override
......@@ -87,13 +101,45 @@ public class PinUvAuthProtocolOne extends PinUvAuthProtocol{
return plainText;
}
/**
*
* @param key the key output from kdf()
* @param cipherText encrypted hashedPin
* @return hashed pin
*/
public byte[] decryptHashedPin(byte[] key, byte[] cipherText) {
byte[] hashedPin = new byte[16];
aesKey.setKey(key, (short)0);
aesDecrypt.init(aesKey, Cipher.MODE_DECRYPT, IV_ZERO_AES, (short)0, (short)IV_ZERO_AES.length);
aesDecrypt.doFinal(cipherText, (short)0, (short)16, hashedPin, (short)0);
return hashedPin;
}
/**
*
* @param key pinToken : 32 bytes
* @param message clientDataHash : 32 bytes
* @return signature
*/
public byte[] authenticate(byte[] key, byte[] message){
return null;
return hmac256(key, message);
}
/**
*
* @param key pinToken 32 bytes
* @param message clientDataHash 32 bytes
* @param signature pinUvAuthToken 16 bytes : LEFT(hmac-sha-256(pinToken, clientDataHash), 16)
* @return boolean result
*/
@Override
public void verify(byte[] key, byte[] message, byte[] signature) {
public boolean verify(byte[] key, byte[] message, byte[] signature) {
byte[] authenticate = authenticate(key, message);
for(short i = 0; i < (short)signature.length; i++){
if(authenticate[i] != signature[i])
return false;
}
return true;
}
public byte[] ecdh(byte[] peerKey){
......@@ -103,9 +149,71 @@ public class PinUvAuthProtocolOne extends PinUvAuthProtocol{
keyAgreement.generateSecret(peerKey, (short)0, (short)65, sharedKey, (short)0);
return kdf(sharedKey, (short)1);
}
/**
*
* @param Z shared key from ecdh
* @param offset where the x-coordinate begin
* @return derivative key
*/
public byte[] kdf(byte[] Z, short offset){
byte[] hashed = new byte[32];
sha256.reset();
sha256.doFinal(Z, offset, (short)32, hashed, (short)0);
return hashed;
}
/**
*
* @param pin pin
* @return hashed pin
*/
public byte[] hashPin(byte[] pin){
byte[] hashedPin = new byte[32];
sha256.reset();
sha256.doFinal(pin, (short)0, (short)pin.length, hashedPin, (short)0);
return hashedPin;
}
/**
*
* @param key key must <= 64 bytes
* @param message message must <= 32 bytes
* @return hmac
*/
public byte[] hmac256(byte[] key, byte[] message){
short BLOCKSIZE=64; // 512 bits
short HASHSIZE=32; // 256 bits
byte[] hashed = new byte[HASHSIZE];
byte[] hmacBuffer = new byte[(short)(BLOCKSIZE + hashed.length)];
for (short i=0; i < (short)key.length; i++){
hmacBuffer[i]= (byte) (key[i] ^ (0x36));
}
Util.arrayFillNonAtomic(hmacBuffer, (short)key.length, (short)(BLOCKSIZE-key.length), (byte)0x36); // ipad
Util.arrayCopyNonAtomic(message, (short)0, hmacBuffer, BLOCKSIZE, (short)message.length);
sha256.update(hmacBuffer, (short)0, HASHSIZE);
sha256.update(hmacBuffer, (short)32, HASHSIZE);
sha256.doFinal(hmacBuffer, BLOCKSIZE, (short)(message.length), hashed, (short)0);
for (short i=0; i< (short)key.length; i++){
hmacBuffer[i]= (byte) (key[i] ^ (0x5c));
}
Util.arrayFillNonAtomic(hmacBuffer, (short)key.length, (short)(BLOCKSIZE - key.length), (byte)0x5c); // opad
Util.arrayCopy(hashed, (short)0, hmacBuffer, BLOCKSIZE, (short)hashed.length);
sha256.update(hmacBuffer, (short)0, HASHSIZE);
sha256.update(hmacBuffer, (short)32, HASHSIZE);
sha256.doFinal(hmacBuffer, BLOCKSIZE, (short)(hashed.length), hashed, (short)0);
return hashed;
}
}
......@@ -17,7 +17,6 @@
package com.josh.vku2f;
public class Utf8Strings {
public static final byte[] UTF8_UP = {'u', 'p'};
// Representation of "id" in UTF8
public static final byte[] UTF8_ID = {'i', 'd'};
// Representation of "name" in UTF8
......@@ -26,20 +25,28 @@ public class Utf8Strings {
public static final byte[] UTF8_DISPLAYNAME = {'d', 'i', 's', 'p', 'l', 'a', 'y', 'n', 'a', 'm', 'e'};
// Representation of "alg" in UTF8
public static final byte[] UTF8_ALG = {'a', 'l', 'g'};
public static final byte[] UTF8_UV = {'u', 'v'};
public static final byte[] UTF8_RK = {'r', 'k'};
public static final byte[] UTF8_UP = {'u', 'p'};
public static final byte[] UTF8_UV = {'u', 'v'};
public static final byte[] UTF8_plat = {'p', 'l', 'a', 't'};
public static final byte[] UTF8_CLIENT_PIN = {'c', 'l', 'i', 'e', 'n', 't', 'P', 'i', 'n'};
public static final byte[] UTF8_CREDENTIAL_MGMT_PREVIEW = {'c', 'r', 'e', 'd', 'e', 'n', 't', 'i', 'a', 'l', 'M', 'g', 'm', 't', 'P', 'r', 'e', 'v', 'i', 'e', 'w', };
public static final byte[] UTF8_nfc = {'n', 'f', 'c'};
public static final byte[] UTF8_usb = {'u', 's', 'b'};
public static final byte[] UTF8_TYPE = {'t', 'y', 'p', 'e'};
public static final byte[] UTF8_PACKED = {'p', 'a', 'c', 'k', 'e', 'd'};
public static final byte[] UTF8_SIG = {'s', 'i', 'g'};
public static final byte[] UTF8_X5C = {'x', '5', 'c'};
public static final byte[] UTF8_PUBLIC_KEY = {'p', 'u', 'b', 'l', 'i', 'c', '-', 'k', 'e', 'y'};
public static final byte[] UTF8_U2F_V2 = {'U', '2', 'F', '_', 'V', '2'};
public static final byte[] UTF8_FIDO2 = {'F', 'I', 'D', 'O', '_', '2', '_', '0'};
public static final byte[] UTF8_FIDO_2_1_PRE = {'F', 'I', 'D', 'O', '_', '2', '_', '1', '_', 'P', 'R', 'E'};
public static final byte[] UTF8_ICON = {'i', 'c', 'o', 'n'};
public static final byte[] UTF8_NULL = {'n', 'u', 'l', 'l'};
public static final byte[] UTF8_EXTENSIONS = {'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's'};
public static final byte[] UTF8_PRLab = {'P', 'R', 'L', 'a', 'b'};
public static final byte[] UTF8_credProtect = {'c','r','e','d','P','r','o','t','e','c','t'};
public static final byte[] UTF8_hmac_secret = {'h','m','a','c','-','s','e','c','r','e','t'};
public static final byte[] UTF8_HMAC = {'H', 'M', 'A', 'C'};
public static final byte[] UTF8_Cx = {'C', 'x'};
public static final byte[] UTF8_IDx = {'I', 'D', 'x'};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment