chameleon-ultra.js - v0.3.29
    Preparing search index...

    Class ChameleonUltra

    The core library of chameleon-ultra.js. You need to register exactly one adapter to the ChameleonUltra instance.

    You can learn how to use @taichunmin/buffer from here.

    Click here see how to use the SDK.

    Example of import the library using import or require:

    // import
    import { Buffer, ChameleonUltra } from 'chameleon-ultra.js'
    import SerialPortAdapter from 'chameleon-ultra.js/plugin/SerialPortAdapter'
    import WebbleAdapter from 'chameleon-ultra.js/plugin/WebbleAdapter'
    import WebserialAdapter from 'chameleon-ultra.js/plugin/WebserialAdapter'

    // require
    const { Buffer, ChameleonUltra } = require('chameleon-ultra.js')
    const SerialPortAdapter = require('chameleon-ultra.js/plugin/SerialPortAdapter')
    const WebbleAdapter = require('chameleon-ultra.js/plugin/WebbleAdapter')
    const WebserialAdapter = require('chameleon-ultra.js/plugin/WebserialAdapter')

    Example of import the library in Browser (place at the end of body):

    <!-- script -->
    <script src="https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/index.global.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/Crypto1.global.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/plugin/WebbleAdapter.global.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/plugin/WebserialAdapter.global.js"></script>
    <script>
    const { Buffer, ChameleonUltra, WebbleAdapter, WebserialAdapter } = window.ChameleonUltraJS
    </script>

    <!-- module -->
    <script type="module">
    import { Buffer, ChameleonUltra } from 'https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm'
    import WebbleAdapter from 'https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/plugin/WebbleAdapter.mjs/+esm'
    import WebserialAdapter from 'https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/plugin/WebserialAdapter.mjs/+esm'
    </script>

    <!-- module + async import -->
    <script type="module">
    const { Buffer, ChameleonUltra } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
    const { default: WebbleAdapter } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/plugin/WebbleAdapter.mjs/+esm')
    const { default: WebserialAdapter } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/plugin/WebserialAdapter.mjs/+esm')
    </script>

    After importing the SDK, you need to register exactly one adapter to the ChameleonUltra instance:

    const ultraUsb = new ChameleonUltra()
    ultraUsb.use(new WebserialAdapter())
    const ultraBle = new ChameleonUltra()
    ultraBle.use(new WebbleAdapter())
    Index

    Constructors

    Connection Related

    Device Related

    Slot Related

    Reader Related

    Emulator Related

    Mifare Classic Related

    Mifare Ultralight Related

    DFU Related

    Internal

    Constructors

    Connection Related

    Device Related

    VERSION_SUPPORTED: { gte: "2.0"; lt: "3.0" } = VERSION_SUPPORTED

    The supported version of SDK.

    • Delete all ble bindings.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdBleDeleteAllBonds()
      })(vm.ultra)
    • Get the ble address of device.

      Returns Promise<string>

      The ble address of device.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      console.log(await ultra.cmdBleGetAddress()) // 'E8:B6:3D:04:B6:FE'
      })(vm.ultra)
    • Get current ble pairing key of device.

      Returns Promise<string>

      The ble pairing key.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      console.log(await ultra.cmdBleGetPairingKey()) // '123456'
      })(vm.ultra)
    • Get the ble pairing mode of device.

      Returns Promise<boolean>

      true if pairing is required to connect to device, otherwise return false.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      console.log(await ultra.cmdBleGetPairingMode()) // false
      })(vm.ultra)
    • Set the ble pairing key of device.

      Parameters

      • key: string

        The new ble pairing key.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdBleSetPairingKey('123456')
      })(vm.ultra)
    • Set if the ble pairing is required when connecting to device.

      Parameters

      • enable: number | boolean

        true to enable pairing mode, false to disable pairing mode.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdBleSetPairingMode(false)
      })(vm.ultra)
    • Change device mode to tag reader or tag emulator.

      Parameters

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { DeviceMode } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdChangeDeviceMode(DeviceMode.TAG)
      })(vm.ultra)
    • Get the animation mode of device while wake-up and sleep.

      Returns Promise<AnimationMode>

      The animation mode of device.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { AnimationMode } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const mode = await ultra.cmdGetAnimationMode()
      console.log(AnimationMode[mode]) // 'FULL'
      })(vm.ultra)
    • Get current firmware version of device.

      Returns Promise<`${number}.${number}`>

      Current firmware version of device.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      console.log(await ultra.cmdGetAppVersion()) // '1.0'
      })(vm.ultra)
    • Get the battery info of device.

      Returns Promise<{ level: number; voltage: number }>

      The battery info of device.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const battery = await ultra.cmdGetBatteryInfo()
      console.log(JSON.stringify(battery)) // { "voltage": 4192, "level": 99 }
      })(vm.ultra)
    • Get the button long press action of specified button.

      Parameters

      Returns Promise<ButtonAction>

      The button long press action of specified button.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { ButtonAction, ButtonType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const btnAction = await ultra.cmdGetButtonLongPressAction(ButtonType.BUTTON_A)
      console.log(ButtonAction[btnAction]) // 'CLONE_IC_UID'
      })(vm.ultra)
    • Get the button press action of specified button.

      Parameters

      Returns Promise<ButtonAction>

      The button press action of specified button.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { ButtonAction, ButtonType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const btnAction = await ultra.cmdGetButtonPressAction(ButtonType.BUTTON_A)
      console.log(ButtonAction[btnAction]) // 'CYCLE_SLOT_INC'
      })(vm.ultra)
    • Get chipset id of device in hex format.

      Returns Promise<string>

      Chipset id of device in hex format.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      console.log(await ultra.cmdGetDeviceChipId()) // 'db1c624228d9634c'
      })(vm.ultra)
    • Get current mode of device.

      Returns Promise<DeviceMode>

      Current mode of device.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { DeviceMode } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const deviceMode = await ultra.cmdGetDeviceMode()
      console.log(DeviceMode[deviceMode]) // 'TAG'
      })(vm.ultra)
    • Get the device is ChameleonUltra or ChameleonLite.

      Returns Promise<DeviceModel>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { DeviceModel } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const model = await ultra.cmdGetDeviceModel()
      console.log(DeviceModel[model]) // 'ULTRA'
      })(vm.ultra)
    • Get the settings of device.

      Returns Promise<
          {
              animation: AnimationMode;
              blePairingKey: string;
              blePairingMode: boolean;
              buttonLongPressAction: ButtonAction[];
              buttonPressAction: ButtonAction[];
              version: number;
          },
      >

      The settings of device.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const settings = await ultra.cmdGetDeviceSettings()
      console.log(JSON.stringify(settings)
      /**
      * {
      * "version": 5,
      * "animation": 0,
      * "buttonPressAction": [1, 2],
      * "buttonLongPressAction": [3, 3],
      * "blePairingMode": false,
      * "blePairingKey": "123456"
      * }
      */
      })(vm.ultra)
    • Get the git version of firmware. The returned string is the output of git describe --abbrev=7 --dirty --always --tags --match "v*.*". Depending on the status of repo, the string can be:

      • a short tag, e.g. v2.0.0 if the firmware is built from the tagged commit
      • a longer tag indicating how many commits far from the latest tag and 7 nibbles of its commit hash, prepended with g, e.g. 5 commits away from v2.0.0: v2.0.0-5-g617d6d0
      • a long tag finishing with -dirty if the local repo contains changes not yet committed, e.g. v2.0.0-5-g617d6d0-dirty

      Returns Promise<string>

      The git version of firmware.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      console.log(await ultra.cmdGetGitVersion()) // 'v2.0.0-209-gc68ea99'
      })(vm.ultra)
    • Get the cmds supported by device.

      Returns Promise<Set<Cmd>>

      The cmds supported by device.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const cmds = await ultra.cmdGetSupportedCmds()
      console.log(cmds.size) // 67
      })(vm.ultra)
    • Reset the settings of device to default values.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdResetSettings()
      })(vm.ultra)
    • Save the settings of device to persistent storage.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdSaveSettings()
      })(vm.ultra)
    • Set the animation mode of device while wake-up and sleep.

      Parameters

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { AnimationMode } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdSetAnimationMode(AnimationMode.SHORT)
      })(vm.ultra)
    • Set the button long press action of specified button.

      Parameters

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { ButtonAction, ButtonType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdSetButtonLongPressAction(ButtonType.BUTTON_A, ButtonAction.CYCLE_SLOT_INC)
      })(vm.ultra)
    • Set the button press action of specified button.

      Parameters

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { ButtonAction, ButtonType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdSetButtonPressAction(ButtonType.BUTTON_A, ButtonAction.CYCLE_SLOT_INC)
      })(vm.ultra)
    • Permanently wipes Chameleon to factory settings. This will delete all your slot data and custom settings. There's no going back.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdWipeFds()
      })(vm.ultra)
    • To check if the specified cmd is supported by device.

      Parameters

      Returns Promise<boolean>

      true if the specified cmd is supported by device, otherwise return false.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Cmd } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      console.log(await ultra.isCmdSupported(Cmd.GET_APP_VERSION)) // true
      })(vm.ultra)
    • Check if the firmware version is supported by SDK.

      Returns Promise<boolean>

      true if the firmware version is supported, false otherwise.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      if (await ultra.isSupportedAppVersion()) throw new Error('Firmware version is not supported. Please update the firmware.')
      })(vm.ultra)

    Slot Related

    • Change the emulation tag type of specified slot.

      Parameters

      • slot: Slot

        The slot to be set.

      • tagType: TagType

        The tag type to be set.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Slot, TagType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdSlotChangeTagType(Slot.SLOT_1, TagType.MIFARE_1024)
      })(vm.ultra)
    • Delete the nick name of the slot

      Parameters

      Returns Promise<boolean>

      true if success, false if slot name is empty.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Slot, FreqType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      console.log(await ultra.cmdSlotDeleteFreqName(Slot.SLOT_1, FreqType.HF)) // true
      })(vm.ultra)
    • Delete the emulation tag data of specified freq type in specified slot.

      Parameters

      • slot: Slot

        The slot to be deleted.

      • freq: FreqType

        The freq type of slot.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Slot, FreqType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdSlotDeleteFreqType(Slot.SLOT_1, FreqType.HF)
      })(vm.ultra)
    • Get the active emulation tag slot of device.

      Returns Promise<Slot>

      The active slot of device.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Slot } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const slot = await ultra.cmdSlotGetActive()
      console.log(Slot[slot]) // 'SLOT_1'
      })(vm.ultra)
    • Get the nickname of specified freq type in specified slot.

      Parameters

      • slot: Slot

        The slot to be get.

      • freq: FreqType

        The freq type to be get.

      Returns Promise<undefined | string>

      The nickname of specified freq type in specified slot.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Slot, FreqType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const name = await ultra.cmdSlotGetFreqName(Slot.SLOT_1, FreqType.HF)
      console.log(name) // 'My Tag'
      })(vm.ultra)
    • Get the slot info of all slots.

      Returns Promise<{ hfTagType: TagType; lfTagType: TagType }[]>

      The slot info of all slots.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const slots = await ultra.cmdSlotGetInfo()
      console.log(JSON.stringify(slots))
      /**
      * [
      * { "hfTagType": 1001, "lfTagType": 100 },
      * { "hfTagType": 1001, "lfTagType": 0 },
      * { "hfTagType": 0, "lfTagType": 100 },
      * { "hfTagType": 0, "lfTagType": 0 },
      * { "hfTagType": 0, "lfTagType": 0 },
      * { "hfTagType": 0, "lfTagType": 0 },
      * { "hfTagType": 0, "lfTagType": 0 },
      * { "hfTagType": 0, "lfTagType": 0 }
      * ]
      */
      })(vm.ultra)
    • Get enabled slots.

      Returns Promise<{ hf: boolean; lf: boolean }[]>

      Enabled slots.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const enabledSlots = await ultra.cmdSlotGetIsEnable()
      console.log(JSON.stringify(enabledSlots))
      // [
      // { "hf": true, "lf": true },
      // { "hf": true, "lf": false },
      // { "hf": false, "lf": true },
      // { "hf": false, "lf": false },
      // { "hf": false, "lf": false },
      // { "hf": false, "lf": false },
      // { "hf": false, "lf": false },
      // { "hf": true, "lf": false }
      // ]
      })(vm.ultra)
    • Reset the emulation tag data of specified tag type in specified slot to default values.

      Parameters

      • slot: Slot

        The slot to be reset.

      • tagType: TagType

        The tag type to be reset.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Slot, TagType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdSlotResetTagType(Slot.SLOT_1, TagType.MIFARE_1024)
      })(vm.ultra)
    • The SlotSettings, hf tag data and lf tag data will be written to persistent storage. But the slot nickname is not affected by this command.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdMf1EmuWriteBlock(1, Buffer.alloc(16))
      await ultra.cmdSlotSaveSettings()
      })(vm.ultra)
    • Change the active emulation tag slot of device.

      Parameters

      • slot: Slot

        The slot to be active.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Slot } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdSlotSetActive(Slot.SLOT_1)
      })(vm.ultra)
    • Enable or disable the specified slot.

      Parameters

      • slot: Slot

        The slot to be enable/disable.

      • freq: FreqType
      • enable: number | boolean

        true to enable the slot, false to disable the slot.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { FreqType, Slot } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdSlotSetEnable(Slot.SLOT_1, FreqType.HF, true)
      })(vm.ultra)
    • Set the nickname of specified freq type in specified slot.

      Parameters

      • slot: Slot

        The slot to be set.

      • freq: FreqType

        The freq type to be set.

      • name: string

        The name to be set. The byteLength of name should between 1 and 32.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Slot, FreqType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdSlotSetFreqName(Slot.SLOT_1, FreqType.HF, 'My Tag')
      })(vm.ultra)
    • Helper function to change slot to tagType, reset to default tagType data, enable slot, save settings and set active slot.

      Parameters

      • slot: Slot

        The target slot.

      • OptionalhfTagType: null | TagType

        The hf tagType to be change. If null, the hf of slot will be skip.

      • OptionallfTagType: null | TagType

        The lf tagType to be change. If null, the lf of slot will be skip.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Slot, TagType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.slotChangeTagTypeAndActive(Slot.SLOT_1, TagType.MIFARE_1024, TagType.EM410X)
      })(vm.ultra)

    Reader Related

    • Scan em410x tag and print id

      Returns Promise<Buffer>

      The id of em410x tag.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const id = await ultra.cmdEm410xScan()
      console.log(id.toString('hex')) // 'deadbeef88'
      })(vm.ultra)
    • Write id of em410x tag to t55xx tag.

      Parameters

      • id: Buffer

        The id of em410x tag.

      • newKey: Buffer

        The new key of t55xx tag.

      • oldKeys: Buffer[]

        The keys to be checked. Maximum length is 125.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const id = Buffer.from('deadbeef88', 'hex')
      // https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/t55xx_default_pwds.dic
      const newKey = Buffer.from('20206666', 'hex')
      const oldKeys = Buffer.from('5124364819920427', 'hex').chunk(4)
      await ultra.cmdEm410xWriteToT55xx(id, newKey, oldKeys)
      })(vm.ultra)
    • Send raw NfcA data to a tag and receive the response.

      Parameters

      • opts: {
            activateRfField?: boolean;
            appendCrc?: boolean;
            autoSelect?: boolean;
            checkResponseCrc?: boolean;
            data?: Buffer;
            dataBitLength?: number;
            keepRfField?: boolean;
            timeout?: number;
            waitResponse?: boolean;
        }
        • OptionalactivateRfField?: boolean

          Set true to activate RF field. If data is not empty or autoSelect is true, activateRfField will be set to true.

        • OptionalappendCrc?: boolean

          Set true to add CRC before sending data.

        • OptionalautoSelect?: boolean

          Set true to automatically select card before sending data.

        • OptionalcheckResponseCrc?: boolean

          Set true to verify CRC of response and remove. If CRC of response is valid, CRC will be removed from response, otherwise will throw HF_ERR_CRC error.

        • Optionaldata?: Buffer

          The data to be send. If appendCrc is true, the maximum length of data is 62, otherwise is 64.

        • OptionaldataBitLength?: number

          Number of bits to send. Useful for send partial byte. dataBitLength is incompatible with appendCrc.

        • OptionalkeepRfField?: boolean

          Set true to keep the RF field active after sending.

        • Optionaltimeout?: number

          Default value is 1000 ms. Maximum timeout for reading tag response in ms while waitResponse is true.

        • OptionalwaitResponse?: boolean

          Default value is true. Set false to skip reading tag response.

      Returns Promise<Buffer>

      The response from tag.

    • Scan 14a tag, and return basic information. The device mode must be set to READER before using this command.

      Returns Promise<{ atqa: Buffer; ats: Buffer; sak: Buffer; uid: Buffer }[]>

      The basic infomation of scanned tag.

      This command will throw an error if tag not scanned or any error occured.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const antiColl = _.first(await ultra.cmdHf14aScan())
      console.log(_.mapValues(antiColl, val => val.toString('hex')))
      // { uid: '040dc4420d2981', atqa: '4400', sak: '00', ats: ''}
      })(vm.ultra)
    • Get the info composed of cmdHf14aScan() and cmdMf1TestNtLevel().

      Returns Promise<
          {
              antiColl: { atqa: Buffer; ats: Buffer; sak: Buffer; uid: Buffer };
              nxpTypeBySak?: string;
              prngType?: Mf1PrngType;
          }[],
      >

      The info about 14a tag and mifare protocol.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Mf1PrngType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const tag = _.first(await ultra.hf14aInfo())
      console.log(tag.nxpTypeBySak) // 'MIFARE Classic 1K | Plus SE 1K | Plug S 2K | Plus X 2K'
      console.log(Mf1PrngType[tag.prngType]) // 'WEAK'
      console.log(_.mapValues(tag.antiColl, val => val.toString('hex')))
      // { uid: 'dbe3d63d', atqa: '0400', sak: '08', ats: '' }
      })(vm.ultra)

    Emulator Related

    • Get the em410x id of actived slot.

      Returns Promise<Buffer>

      The em410x id of actived slot.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const id = await ultra.cmdEm410xGetEmuId()
      console.log(id.toString('hex')) // 'deadbeef88'
      })(vm.ultra)
    • Set the em410x id of actived slot.

      Parameters

      • id: Buffer

        The em410x id of actived slot.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdEm410xSetEmuId(Buffer.from('deadbeef88', 'hex'))
      })(vm.ultra)
    • Get anti-collision data from actived slot.

      Returns Promise<null | { atqa: Buffer; ats: Buffer; sak: Buffer; uid: Buffer }>

      The anti-collision data from actived slot.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const res = await ultra.cmdHf14aGetAntiCollData()
      console.log(JSON.stringify(res))
      // {
      // "uid": { "type": "Buffer", "data": [222, 173, 190, 239] },
      // "atqa": { "type": "Buffer", "data": [4, 0] },
      // "sak": { "type": "Buffer", "data": [8] },
      // "ats": { "type": "Buffer", "data": [] }
      // }
      })(vm.ultra)
    • Set the mifare anti-collision data of actived slot.

      Parameters

      • opts: { atqa: Buffer; ats?: Buffer; sak: Buffer; uid: Buffer }
        • atqa: Buffer

          2 bytes, the new atqa to be set.

        • Optionalats?: Buffer

          The new ats to be set.

        • sak: Buffer

          1 byte, the new sak to be set.

        • uid: Buffer

          The new uid to be set.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdHf14aSetAntiCollData({
      atqa: Buffer.from('0400', 'hex'),
      sak: Buffer.of(0x08),
      uid: Buffer.from('01020304', 'hex')
      })
      })(vm.ultra)

    Mifare Classic Related

    • Acquire the data from mifare darkside attack.

      Parameters

      • block: number

        The target block.

      • keyType: Mf1KeyType

        The target key type.

      • isFirst: number | boolean

        true if this is the first attack.

      • syncMax: number = 30

        The max sync count of darkside attack.

      Returns Promise<
          {
              ar?: Buffer;
              ks?: Buffer;
              nr?: Buffer;
              nt?: Buffer;
              par?: Buffer;
              status: DarksideStatus;
              uid?: Buffer;
          },
      >

      The data from mifare darkside attack.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Mf1KeyType, DarksideStatus } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const res1 = await ultra.cmdMf1AcquireDarkside(0, Mf1KeyType.KEY_A, true)
      console.log(res1)
      const res2 = {
      status: `${DarksideStatus[res1.status]} (${res1.status})`,
      ...(res1.status !== DarksideStatus.OK ? {} : {
      ar: res1.ar.toString('hex'),
      ks: res1.ks.toString('hex'),
      nr: res1.nr.toString('hex'),
      nt: res1.nt.toString('hex'),
      par: res1.par.toString('hex'),
      uid: res1.uid.toString('hex'),
      }),
      }
      console.log(res2)
      // {
      // "ar": "00000000",
      // "ks": "0c0508080f04050a",
      // "nr": "00000000",
      // "nt": "b346fc3d",
      // "par": "0000000000000000",
      // "status": "OK (0)",
      // "uid": "d3efed0c"
      // }
      })(vm.ultra)

      If you want to use darkside attack to recover the key, you can use the following example code:

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer, DarksideStatus, Mf1KeyType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const block = 0
      const keyType = Mf1KeyType.KEY_A
      const key = await Crypto1.darkside(
      async attempt => {
      const acquired = await ultra.cmdMf1AcquireDarkside(block, keyType, attempt === 0)
      console.log(_.mapValues(acquired, buf => Buffer.isBuffer(buf) ? buf.toString('hex') : buf))
      if (acquired.status === DarksideStatus.LUCKY_AUTH_OK) throw new Error('LUCKY_AUTH_OK')
      if (acquired.status !== DarksideStatus.OK) throw new Error('card is not vulnerable to Darkside attack')
      return acquired
      },
      async key => {
      return await ultra.cmdMf1CheckBlockKey({ block, keyType, key })
      },
      )
      console.log(`key founded: ${key.toString('hex')}`)
      })(vm.ultra)
    • Use a known key to do the mifare hardnested attack.

      Parameters

      • known: { block: number; key: Buffer; keyType: Mf1KeyType }

        The info of known key.

        • block: number

          The block of known key.

        • key: Buffer

          The known key.

        • keyType: Mf1KeyType

          The key type of known key.

      • target: { block: number; keyType: Mf1KeyType; slow?: boolean }

        The info of target key to be attack.

        • block: number

          The block of target key.

        • keyType: Mf1KeyType

          The key type of target key.

        • Optionalslow?: boolean

          Is it a low-speed acquisition mode? Low-speed acquisition is suitable for some non-standard cards.

      Returns Promise<{ nt: number; ntEnc: number; par: number }[]>

      The result of mifare hardnested attack.

      • nt: tag nonce of nested verification encryption
      • ntEnc: encrypted tag nonce of nested verification encryption
      • par: The 8 parity bit of nested verification encryption
      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer, Mf1KeyType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const antiColl = _.first(await ultra.cmdHf14aScan())
      const key = Buffer.from('FFFFFFFFFFFF', 'hex')
      const res = await ultra.cmdMf1AcquireHardNested(
      { block: 0, keyType: Mf1KeyType.KEY_A, key },
      { block: 4, keyType: Mf1KeyType.KEY_A },
      )
      console.log(res)
      // [
      // { nt: 0xCE178123, ntEnc: 0x37ADDC14, par: 0xB8 },
      // { nt: 0xD9380BBF, ntEnc: 0x0080795A, par: 0xF3 },
      // // ...
      // ]
      })(vm.ultra)
    • Use a known key to do the mifare nested attack.

      Parameters

      • known: { block: number; key: Buffer; keyType: Mf1KeyType }

        The info of known key.

        • block: number

          The block of known key.

        • key: Buffer

          The known key.

        • keyType: Mf1KeyType

          The key type of known key.

      • target: { block: number; keyType: Mf1KeyType }

        The info of target key to be attack.

        • block: number

          The block of target key.

        • keyType: Mf1KeyType

          The key type of target key.

      Returns Promise<{ nt1: number; nt2: number; par: number }[]>

      The result of mifare nested attack.

      • nt1: Unblocked explicitly random number
      • nt2: Random number of nested verification encryption
      • par: The 3 parity bit of nested verification encryption
      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer, Mf1KeyType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const key = Buffer.from('FFFFFFFFFFFF', 'hex')
      const res1 = await ultra.cmdMf1TestNtDistance({ block: 0, keyType: Mf1KeyType.KEY_A, key })
      const res2 = await ultra.cmdMf1AcquireNested(
      { block: 0, keyType: Mf1KeyType.KEY_A, key },
      { block: 4, keyType: Mf1KeyType.KEY_A },
      )
      const res = {
      uid: res1.uid.toString('hex'),
      dist: res1.dist.toString('hex'),
      atks: res2,
      }
      console.log(res)
      // {
      // uid: '877209e1',
      // dist: '00000080',
      // atks: [
      // { nt1: 0x35141FCB, nt2: 0x40430522, par: 7 },
      // { nt1: 0xCFF2B3EF, nt2: 0x825BA8EA, par: 5 },
      // ]
      // }
      })(vm.ultra)
    • Use a known key to do the mifare static nested attack.

      Parameters

      • known: { block: number; key: Buffer; keyType: Mf1KeyType }

        The info of known key.

        • block: number

          The block of known key.

        • key: Buffer

          The known key.

        • keyType: Mf1KeyType

          The key type of known key.

      • target: { block: number; keyType: Mf1KeyType }

        The info of target key to be attack.

        • block: number

          The block of target key.

        • keyType: Mf1KeyType

          The key type of target key.

      Returns Promise<{ atks: { nt1: Buffer; nt2: Buffer }[]; uid: Buffer }>

      The result of mifare static nested attack.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer, Mf1KeyType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const key = Buffer.from('FFFFFFFFFFFF', 'hex')
      const res1 = await ultra.cmdMf1AcquireStaticNested({
      block: 0,
      keyType: Mf1KeyType.KEY_A,
      key
      }, {
      block: 4,
      keyType: Mf1KeyType.KEY_A
      })
      const res = {
      uid: res1.uid.toString('hex'),
      atks: _.map(res1.atks, item => ({ nt1: item.nt1.toString('hex'), nt2: item.nt2.toString('hex') })),
      }
      console.log(res)
      // {
      // uid: 'b908a16d',
      // atks: [
      // { nt1: '01200145', nt2: '81901975' },
      // { nt1: '01200145', nt2: 'cdd400f3' },
      // ],
      // }
      })(vm.ultra)
    • Check if the key is valid for specified block and key type.

      Parameters

      • opts: { block: number; key: Buffer; keyType: Mf1KeyType }

        The info of key to be checked.

        • block: number

          The block of key to be checked.

        • key: Buffer

          The key to be checked.

        • keyType: Mf1KeyType

          The type of key to be checked.

      Returns Promise<boolean>

      true if the key is valid for specified block and key type.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer, Mf1KeyType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const key = Buffer.from('FFFFFFFFFFFF', 'hex')
      console.log(await ultra.cmdMf1CheckBlockKey({
      block: 0,
      keyType: Mf1KeyType.KEY_A,
      key,
      })) // true
      })(vm.ultra)
    • Given a list of keys, check which is the correct key A and key B of the sectors. If you want to check more than 83 keys, you can use mf1CheckKeysOfSectors().

      Parameters

      • opts: { keys: Buffer[]; mask: Buffer }
        • keys: Buffer[]

          The keys to be checked. Maximum length is 83.

        • mask: Buffer

          The mask of sectors. 80 bits, 2 bits/sector, the first bit is key A, the second bit is key B, 0b1 represent to skip checking the key.

      Returns Promise<null | { found: Buffer; sectorKeys: (null | Buffer)[] }>

      • found: 80 bits, 2 bits/sector, the first bit is key A, the second bit is key B, 0b1 represent key is found.
      • sectorKeys: 80 keys, 2 keys/sector, the first key is key A, the second key is key B. null represent key is not found.
      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const mask = Buffer.from('00000000FFFFFFFFFFFF', 'hex')
      const keys = Buffer.from('FFFFFFFFFFFF\n000000000000\nA0A1A2A3A4A5\nD3F7D3F7D3F7', 'hex').chunk(6)
      const tsStart = Date.now()
      const result = await ultra.cmdMf1CheckKeysOfSectors({ keys, mask })
      console.log(`Time: ${Date.now() - tsStart}ms`)
      const replacer = function (k, v) { return Buffer.isBuffer(this[k]) ? this[k].toString('hex') : v }
      console.log(JSON.stringify(result, replacer, 2))
      })(vm.ultra)
      // {
      // "found": "ffffffff000000000000",
      // "sectorKeys": [
      // "ffffffffffff", "ffffffffffff", "ffffffffffff", "ffffffffffff",
      // "ffffffffffff", "ffffffffffff", "ffffffffffff", "ffffffffffff",
      // "ffffffffffff", "ffffffffffff", "ffffffffffff", "ffffffffffff",
      // "ffffffffffff", "ffffffffffff", "ffffffffffff", "ffffffffffff",
      // "ffffffffffff", "ffffffffffff", "ffffffffffff", "ffffffffffff",
      // "ffffffffffff", "ffffffffffff", "ffffffffffff", "ffffffffffff",
      // "ffffffffffff", "ffffffffffff", "ffffffffffff", "ffffffffffff",
      // "ffffffffffff", "ffffffffffff", "ffffffffffff", "ffffffffffff",
      // null, null, null, null,
      // null, null, null, null,
      // null, null, null, null,
      // null, null, null, null,
      // null, null, null, null,
      // null, null, null, null,
      // null, null, null, null,
      // null, null, null, null,
      // null, null, null, null,
      // null, null, null, null,
      // null, null, null, null,
      // null, null, null, null,
      // ]
      // }
    • Get the mifare block data of actived slot.

      Parameters

      • offset: number = 0

        The start block of actived slot.

      • length: number = 1

        The count of blocks to be get.

      Returns Promise<Buffer>

      The mifare block data of actived slot.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const data = await ultra.cmdMf1EmuReadBlock(1)
      console.log(data.toString('hex')) // '00000000000000000000000000000000'
      })(vm.ultra)
    • Set the mifare block data of actived slot.

      Parameters

      • offset: number

        The start block of actived slot.

      • data: Buffer

        The data to be set. the length of data should be multiples of 16.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdMf1EmuWriteBlock(1, Buffer.alloc(16))
      })(vm.ultra)
    • Get the mode of actived slot that using anti-collision data from block 0 for 4 byte UID tags or not.

      Returns Promise<boolean>

      The mode of actived slot that using anti-collision data from block 0 for 4 byte UID tags or not.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      console.log(await ultra.cmdMf1GetAntiCollMode()) // false
      })(vm.ultra)
    • Get the count of mifare MFKey32 detections.

      Returns Promise<number>

      The count of mifare MFKey32 detections.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      console.log(await ultra.cmdMf1GetDetectionCount()) // 0
      })(vm.ultra)
    • Get the feature of mifare MFKey32 detections is enabled or not.

      Returns Promise<boolean>

      true if the feature of mifare MFKey32 detections is enabled, otherwise return false.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      console.log(await ultra.cmdMf1GetDetectionEnable()) // false
      })(vm.ultra)
    • Get the data of mifare MFKey32 detections.

      Parameters

      • offset: number = 0

        The start log of detections to be get.

      Returns Promise<
          {
              ar: Buffer;
              block: number;
              isKeyB: boolean;
              isNested: boolean;
              nr: Buffer;
              nt: Buffer;
              uid: Buffer;
          }[],
      >

      The mifare MFKey32 detections.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const logs = await ultra.cmdMf1GetDetectionLogs(0)
      console.log(logs)
      /**
      * {
      * "block": 2,
      * "isKeyB": 1,
      * "isNested": 0,
      * "uid": Buffer.from('65535d33', 'hex'),
      * "nt": Buffer.from('cb7b9ed9', 'hex'),
      * "nr": Buffer.from('5a8ffec6', 'hex'),
      * "ar": Buffer.from('5c7c6f89', 'hex'),
      * }
      */
      })(vm.ultra)
    • Get the mifare settings of actived slot.

      Returns Promise<
          {
              antiColl: boolean;
              detection: boolean;
              gen1a: boolean;
              gen2: boolean;
              write: Mf1EmuWriteMode;
          },
      >

      The mifare settings of actived slot.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const mf1Settings = await ultra.cmdMf1GetEmuSettings()
      console.log(JSON.stringify(mf1Settings))
      /**
      * {
      * "detection": false,
      * "gen1a": false,
      * "gen2": false,
      * "antiColl": false,
      * "write": 0
      * }
      */
      })(vm.ultra)
    • Set the mifare gen1a mode of actived slot.

      Returns Promise<boolean>

      The mifare gen1a mode of actived slot.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      console.log(await ultra.cmdMf1GetGen1aMode()) // false
      })(vm.ultra)
    • Get the mifare gen2 mode of actived slot.

      Returns Promise<boolean>

      The mifare gen2 mode of actived slot.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      console.log(await ultra.cmdMf1GetGen2Mode()) // false
      })(vm.ultra)
    • Get the mifare write mode of actived slot.

      Returns Promise<Mf1EmuWriteMode>

      The mifare write mode of actived slot.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      console.log(await ultra.cmdMf1GetWriteMode()) // 0
      })(vm.ultra)
    • Test whether it is mifare classic tag.

      Returns Promise<boolean>

      true if tag is mifare classic tag, otherwise return false.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      console.log(await ultra.cmdMf1IsSupport()) // true
      })(vm.ultra)
    • Read block data from a mifare tag.

      Parameters

      • opts: { block: number; key: Buffer; keyType: Mf1KeyType }

        The block to be read and the key info of the block.

        • block: number

          The block to be read.

        • key: Buffer

          The key of the block.

        • keyType: Mf1KeyType

          The key type of the block.

      Returns Promise<Buffer>

      The block data read from a mifare tag.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer, Mf1KeyType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const key = Buffer.from('FFFFFFFFFFFF', 'hex')
      const block1 = await ultra.cmdMf1ReadBlock({
      block: 1,
      keyType: Mf1KeyType.KEY_A,
      key,
      })
      console.log(block1.toString('hex')) // '00000000000000000000000000000000'
      })(vm.ultra)
    • Set the mode of actived slot that using anti-collision data from block 0 for 4 byte UID tags or not.

      Parameters

      • enable: number | boolean

        true to enable the mode, false to disable the mode.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdMf1SetAntiCollMode(false)
      })(vm.ultra)
    • Enable or disable the mifare MFKey32 detection and clear the data of detections.

      Parameters

      • enable: number | boolean

        true to enable the detection, false to disable the detection.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdMf1SetDetectionEnable(true)
      })(vm.ultra)
    • Set the mifare gen1a mode of actived slot.

      Parameters

      • enable: number | boolean

        true to enable the gen1a mode, false to disable the gen1a mode.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdMf1SetGen1aMode(false)
      })(vm.ultra)
    • Set the mifare gen2 mode of actived slot.

      Parameters

      • enable: number | boolean

        true to enable the gen2 mode, false to disable the gen2 mode.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdMf1SetGen2Mode(false)
      })(vm.ultra)
    • Set the mifare write mode of actived slot.

      Parameters

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Mf1EmuWriteMode } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdMf1SetWriteMode(Mf1EmuWriteMode.NORMAL)
      })(vm.ultra)
    • Dectect the nt distance of mifare protocol.

      Parameters

      • known: { block: number; key: Buffer; keyType: Mf1KeyType }

        The info of known key.

        • block: number

          The block of known key.

        • key: Buffer

          The known key.

        • keyType: Mf1KeyType

          The key type of known key.

      Returns Promise<{ dist: Buffer; uid: Buffer }>

      The nt distance of mifare protocol.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer, Mf1KeyType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const key = Buffer.from('FFFFFFFFFFFF', 'hex')
      const res1 = await ultra.cmdMf1TestNtDistance({ block: 0, keyType: Mf1KeyType.KEY_A, key })
      const res2 = await ultra.cmdMf1AcquireNested(
      { block: 0, keyType: Mf1KeyType.KEY_A, key },
      { block: 4, keyType: Mf1KeyType.KEY_A },
      )
      const res = {
      uid: res1.uid.toString('hex'),
      dist: res1.dist.toString('hex'),
      atks: _.map(res2, item => ({
      nt1: item.nt1.toString('hex'),
      nt2: item.nt2.toString('hex'),
      par: item.par,
      }))
      }
      console.log(res)
      // {
      // uid: '877209e1',
      // dist: '00000080',
      // atks: [
      // { nt1: '35141fcb', nt2: '40430522', par: 7 },
      // { nt1: 'cff2b3ef', nt2: '825ba8ea', par: 5 },
      // ]
      // }
      })(vm.ultra)
    • Check the nt level of mifare protocol.

      Returns Promise<Mf1PrngType>

      The nt level of mifare protocol.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Mf1PrngType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      console.log(Mf1PrngType[await ultra.cmdMf1TestPrngType()]) // 'WEAK'
      })(vm.ultra)
    • MIFARE Classic manipulate value block

      • Decrement: decrement value by X (0 ~ 2147483647) from src to dst
      • Increment: increment value by X (0 ~ 2147483647) from src to dst
      • Restore: copy value from src to dst (Restore and Transfer)

      Parameters

      • src: { block: number; key: Buffer; keyType: Mf1KeyType }

        The key info of src block.

        • block: number

          The block of src block.

        • key: Buffer

          The key of src block.

        • keyType: Mf1KeyType

          The key type of src block.

      • operator: Mf1VblockOperator

        The operator of value block.

      • operand: number

        The operand of value block.

      • dst: { block: number; key: Buffer; keyType: Mf1KeyType }

        The key info of dst block.

        • block: number

          The block of dst block.

        • key: Buffer

          The key of dst block.

        • keyType: Mf1KeyType

          The key type of dst block.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer, Mf1KeyType, Mf1VblockOperator } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const key = Buffer.from('FFFFFFFFFFFF', 'hex')
      const src = { block: 4, keyType: Mf1KeyType.KEY_A, key }
      await ultra.mf1VblockSetValue(src, { value: 2 })
      console.log(await ultra.mf1VblockGetValue(src))
      await ultra.cmdMf1VblockManipulate(
      { block: 4, keyType: Mf1KeyType.KEY_A, key },
      Mf1VblockOperator.DECREMENT, 1,
      { block: 4, keyType: Mf1KeyType.KEY_A, key },
      )
      console.log(await ultra.mf1VblockGetValue(src))
      })(vm.ultra)
    • Write data to a mifare tag.

      Parameters

      • opts: { block: number; data: Buffer; key: Buffer; keyType: Mf1KeyType }

        The block to be written and the key info of the block.

        • block: number

          The block to be written.

        • data: Buffer

          The block data to be written.

        • key: Buffer

          The key of the block.

        • keyType: Mf1KeyType

          The key type of the block.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer, Mf1KeyType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const key = Buffer.from('FFFFFFFFFFFF', 'hex')
      const block1 = Buffer.from('00000000000000000000000000000000', 'hex')
      await ultra.cmdMf1WriteBlock({
      block: 1,
      keyType: Mf1KeyType.KEY_A,
      key,
      data: block1,
      })
      })(vm.ultra)
    • Mifare Classic check keys of sectors.

      Parameters

      • opts: {
            chunkSize?: number;
            keys: Buffer[];
            mask?: Buffer;
            maxSectors?: number;
            onChunkKeys?: (opts: { keys: Buffer[]; mask: Buffer }) => Promise<unknown>;
        }
        • OptionalchunkSize?: number

          keys will be chunked by this size.

        • keys: Buffer[]

          The keys to be checked.

        • Optionalmask?: Buffer

          The mask of sectors. 80 bits, 2 bits/sector, the first bit is key A, the second bit is key B, 0b1 represent to skip checking the key.

        • OptionalmaxSectors?: number

          The max sectors to be check.

        • OptionalonChunkKeys?: (opts: { keys: Buffer[]; mask: Buffer }) => Promise<unknown>

          The callback function to be invoked before checking every chunk of keys.

      Returns Promise<(null | Buffer)[]>

    • Given a list of keys, check which is the correct key A and key B of the sector.

      Parameters

      • sector: number

        The sector number to be checked.

      • keys: Buffer[]

        The keys dictionary.

      Returns Promise<{ "96"?: Buffer; "97"?: Buffer }>

      The Key A and Key B of the sector.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const keys = Buffer.from('FFFFFFFFFFFF\n000000000000\nA0A1A2A3A4A5\nD3F7D3F7D3F7', 'hex').chunk(6)
      const sectorKey = await ultra.mf1CheckSectorKeys(0, keys)
      console.log(_.mapValues(sectorKey, key => key.toString('hex')))
      // { "96": "ffffffffffff", "97": "ffffffffffff" }
      })(vm.ultra)
    • Read blocks from Mifare Classic Gen1a.

      Parameters

      • offset: number

        The start block of Mifare Classic Gen1a.

      • length: number = 1

        The amount of blocks to read.

      Returns Promise<Buffer>

      The blocks data.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const card = await ultra.mf1Gen1aReadBlocks(0, 64)
      console.log(_.map(card.chunk(16), chunk => chunk.toString('hex')).join('\n'))
      })(vm.ultra)
    • Write blocks to Mifare Classic Gen1a.

      Parameters

      • offset: number

        The start block of Mifare Classic Gen1a.

      • data: Buffer

        The blocks data to write.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.mf1Gen1aWriteBlocks(1, new Buffer(16))
      })(vm.ultra)
    • Send Mifare Classic HALT command and close RF field.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.mf1Halt()
      })(vm.ultra)
    • Read a block data of Mifare Classic by given keys.

      Parameters

      • block: number

        The block number to be read.

      • keys: Buffer[]

        The keys dictionary.

      Returns Promise<Buffer>

      The block data read from a mifare tag. An error is thrown if the block cannot be read.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const keys = Buffer.from('FFFFFFFFFFFF\n000000000000\nA0A1A2A3A4A5\nD3F7D3F7D3F7', 'hex').chunk(6)
      const data = await ultra.mf1ReadBlockByKeys(0, keys)
      console.log(data.toString('hex'))
      })(vm.ultra)
    • Read a sector data of Mifare Classic by given keys.

      Parameters

      • sector: number

        The sector number to be read.

      • keys: Buffer[]

        The keys dictionary.

      Returns Promise<{ data: Buffer; success: boolean[] }>

      The sector data and the read status of each block.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer, Mf1KeyType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const keys = Buffer.from('FFFFFFFFFFFF\n000000000000\nA0A1A2A3A4A5\nD3F7D3F7D3F7', 'hex').chunk(6)
      const { data, success } = await ultra.mf1ReadSectorByKeys(0, keys)
      console.log({ data: data.toString('hex'), success })
      // { "data": "...", "success": [true, true, true, true] }
      })(vm.ultra)
    • Get value from opts block (MIFARE Classic value block)

      Parameters

      • opts: { block: number; key: Buffer; keyType: Mf1KeyType }

        The key info of opts block.

        • block: number

          The block of opts block.

        • key: Buffer

          The key of opts block.

        • keyType: Mf1KeyType

          The key type of opts block.

      Returns Promise<{ adr: number; value: number }>

      The value and address of opts block.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer, Mf1KeyType, Mf1VblockOperator } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const key = Buffer.from('FFFFFFFFFFFF', 'hex')
      const src = { block: 4, keyType: Mf1KeyType.KEY_A, key }
      await ultra.mf1VblockSetValue(src, { value: 2 })
      console.log(await ultra.mf1VblockGetValue(src))
      })(vm.ultra)
    • Set value X (-2147483647 ~ 2147483647) to dst block (MIFARE Classic value block)

      Parameters

      • dst: { block: number; key: Buffer; keyType: Mf1KeyType }

        The key info of dst block.

        • block: number

          The block of dst block.

        • key: Buffer

          The key of dst block.

        • keyType: Mf1KeyType

          The key type of dst block.

      • val: { adr?: number; value?: number }

        The value and address to be set.

        • Optionaladr?: number

          The address to be set. Default is dst.block.

        • Optionalvalue?: number

          The value to be set. Default is 0.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer, Mf1KeyType, Mf1VblockOperator } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const key = Buffer.from('FFFFFFFFFFFF', 'hex')
      const src = { block: 4, keyType: Mf1KeyType.KEY_A, key }
      await ultra.mf1VblockSetValue(src, { value: 2 })
      console.log(await ultra.mf1VblockGetValue(src))
      })(vm.ultra)
    • Write a block data to Mifare Classic by given keys.

      Parameters

      • block: number

        The block number to be written.

      • keys: Buffer[]

        The keys dictionary.

      • data: Buffer

        Block data

      Returns Promise<void>

      An error is thrown if the block cannot be write.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const keys = Buffer.from('FFFFFFFFFFFF\n000000000000\nA0A1A2A3A4A5\nD3F7D3F7D3F7', 'hex').chunk(6)
      const data = Buffer.from('00000000000000000000000000000000', 'hex')
      await ultra.mf1WriteBlockByKeys(1, keys, data)
      })(vm.ultra)
    • Write a sector data to Mifare Classic by given keys.

      Parameters

      • sector: number

        The sector number to be written.

      • keys: Buffer[]

        The key dictionary.

      • data: Buffer

        Sector data

      Returns Promise<{ success: boolean[] }>

      the write status of each block.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const keys = Buffer.from('FFFFFFFFFFFF\n000000000000\nA0A1A2A3A4A5\nD3F7D3F7D3F7', 'hex').chunk(6)
      const data = Buffer.concat([
      Buffer.from('00000000000000000000000000000000', 'hex'),
      Buffer.from('00000000000000000000000000000000', 'hex'),
      Buffer.from('00000000000000000000000000000000', 'hex'),
      Buffer.from('ffffffffffffff078069ffffffffffff', 'hex'),
      ])
      const { success } = await ultra.mf1WriteSectorByKeys(1, keys, data)
      console.log(success)
      // [true, true, true, true]
      })(vm.ultra)
    • Convert Proxmark3 compatible EML string to dump for importing Mifare Classic.

      Parameters

      • eml: string | Uint8Array<ArrayBufferLike> | Buffer

        The EML string of the Mifare Classic.

      Returns Buffer

      The dump data imported from EML.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async () => {
      const { Buffer, ChameleonUltra, TagType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const dump = ChameleonUltra.mf1GenEmptyDump({ tagType: TagType.MIFARE_1024 })
      const eml = ChameleonUltra.mf1DumpToEml({ body: dump })
      const buf = ChameleonUltra.mf1DumpFromEml(eml)
      console.log(buf)
      })()
    • Convert MifareClassicTool compatible MCT string to dump for importing Mifare Classic.

      Parameters

      • mct: string | Uint8Array<ArrayBufferLike> | Buffer

        The MCT string of the Mifare Classic.

      Returns Buffer

      The dump data imported from MCT.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async () => {
      const { Buffer, ChameleonUltra, TagType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const dump = ChameleonUltra.mf1GenEmptyDump({ tagType: TagType.MIFARE_1024 })
      const mct = ChameleonUltra.mf1DumpToMct({ body: dump })
      const buf = ChameleonUltra.mf1DumpFromMct(mct)
      console.log(buf)
      })()
    • Convert Proxmark3 compatible JSON Object to dump for importing Mifare Classic.

      Parameters

      • pm3Json:
            | string
            | Uint8Array<ArrayBufferLike>
            | Buffer
            | {
                blocks: Record<number, string>;
                Card: {
                    ATQA: string;
                    ATS?: string;
                    SAK: string;
                    SIGNATURE: string;
                    UID: string;
                };
                Created: string;
                FileType: string;
            }

        Proxmark3 compatible JSON Object. If a string, Uint8Array, Buffer is provided, it will be parsed using JSON.parse.

      Returns {
          atqa: Buffer;
          ats: Buffer;
          body: Buffer;
          sak: Buffer;
          sig: Buffer;
          tagType: TagType;
          uid: Buffer;
      }

      The tag data imported from Proxmark3 JSON Object.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async () => {
      const { Buffer, ChameleonUltra, TagType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const dump = ChameleonUltra.mf1GenEmptyDump({ tagType: TagType.MIFARE_1024 })
      const json = ChameleonUltra.mf1DumpToPm3Json({
      atqa: Buffer.from('0004', 'hex').reverse(),
      body: dump,
      sak: Buffer.of(0x08),
      uid: Buffer.from('deadbeef', 'hex'),
      })
      const resp = ChameleonUltra.mf1DumpFromPm3Json(json)
      console.log(resp)
      })()
    • Convert dump to Proxmark3 compatible EML string for exporting Mifare Classic.

      Parameters

      • opts: { body: Buffer }
        • body: Buffer

          The body of the tag.

      Returns string

      The EML string for exporting Mifare Classic.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async () => {
      const { Buffer, ChameleonUltra, TagType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const dump = ChameleonUltra.mf1GenEmptyDump({ tagType: TagType.MIFARE_1024 })
      const eml = ChameleonUltra.mf1DumpToEml({ body: dump })
      console.log(eml)
      })()
    • Convert dump to MifareClassicTool compatible MCT string for exporting Mifare Classic.

      Parameters

      • opts: { body: Buffer }
        • body: Buffer

          The body of the tag.

      Returns string

      The MCT string for exporting Mifare Classic.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async () => {
      const { Buffer, ChameleonUltra, TagType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const dump = ChameleonUltra.mf1GenEmptyDump({ tagType: TagType.MIFARE_1024 })
      const mct = ChameleonUltra.mf1DumpToMct({ body: dump })
      console.log(mct)
      })()
    • Convert dump to Proxmark3 compatible JSON Object for exporting Mifare Classic.

      Parameters

      • opts: {
            atqa: Buffer;
            ats?: Buffer;
            body: Buffer;
            sak: Buffer;
            sig?: Buffer;
            uid: Buffer;
        }
        • atqa: Buffer

          The ATQA of the tag.

        • Optionalats?: Buffer

          The ATS of the tag.

        • body: Buffer

          The body of the tag.

        • sak: Buffer

          The SAK of the tag.

        • Optionalsig?: Buffer
        • uid: Buffer

          The UID of the tag.

      Returns {
          blocks: Record<number, string>;
          Card: {
              ATQA: string;
              ATS?: string;
              SAK: string;
              SIGNATURE: string;
              UID: string;
          };
          Created: string;
          FileType: string;
      }

      The JSON Object for exporting Mifare Classic.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async () => {
      const { Buffer, ChameleonUltra, TagType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const dump = ChameleonUltra.mf1GenEmptyDump({ tagType: TagType.MIFARE_1024 })
      const json = ChameleonUltra.mf1DumpToPm3Json({
      atqa: Buffer.from('0004', 'hex').reverse(),
      body: dump,
      sak: Buffer.of(0x08),
      uid: Buffer.from('deadbeef', 'hex'),
      })
      console.log(json)
      })()
    • Generate empty dump for magic mifare classic tag.

      Parameters

      • opts: { atqa?: Buffer; buf?: Buffer; sak?: Buffer; tagType?: TagType; uid?: Buffer } = {}
        • Optionalatqa?: Buffer

          The ATQA of the tag.

        • Optionalbuf?: Buffer

          If provided, the data will be written to this buffer.

        • Optionalsak?: Buffer

          The SAK of the tag.

        • OptionaltagType?: TagType

          The tag type of the mifare classic tag.

        • Optionaluid?: Buffer

          The UID of the tag.

      Returns Buffer

      The empty dump for magic mifare classic tag.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async () => {
      const { Buffer, ChameleonUltra, TagType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const dump = ChameleonUltra.mf1GenEmptyDump({
      uid: Buffer.from('deadbeef', 'hex'),
      atqa: Buffer.from('0004', 'hex').reverse(),
      sak: Buffer.of(0x08),
      tagType: TagType.MIFARE_1024,
      })
      console.log(dump.chunk(16).map(blk => blk.toString('hex')).join('\n'))
      })()
    • Generate block 0 (manufacturer block) for magic mifare classic tag.

      Parameters

      • opts: { atqa?: Buffer; buf?: Buffer; sak?: Buffer; uid: Buffer }
        • Optionalatqa?: Buffer

          The ATQA of the tag.

        • Optionalbuf?: Buffer

          If provided, the data will be written to this buffer.

        • Optionalsak?: Buffer

          The SAK of the tag.

        • uid: Buffer

          The UID of the tag.

      Returns Buffer

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async () => {
      const { Buffer, ChameleonUltra } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const block0 = ChameleonUltra.mf1GenMagicBlock0({
      uid: Buffer.from('deadbeef', 'hex'),
      atqa: Buffer.from('0004', 'hex').reverse(),
      sak: Buffer.of(0x08),
      })
      console.log(block0.toString('hex')) // deadbeef220804000000000000000000
      })()
    • Check acl bytes of ACL, block or sector.

      Parameters

      • data: Buffer

        Data of ACL, block or sector.

      Returns boolean

      true if the acl bytes is valid, false otherwise.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async () => {
      const { Buffer, ChameleonUltra } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      console.log(ChameleonUltra.mf1IsValidAcl(Buffer.from('ff078069', 'hex'))) // true
      })()
    • Convert Mifare Keys .dic string to keys.

      Parameters

      • dict: string

        Mifare Keys .dic string

      Returns Buffer[]

      The keys imported from Mifare Keys .dic string.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async () => {
      const { ChameleonUltra } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const dict = '#test\r\nFFFFFFFFFFFF\r\n\r\n'
      const keys = ChameleonUltra.mf1KeysFromDict(dict)
      console.log(keys.map(key => key.toString('hex').toUpperCase()))
      // ['FFFFFFFFFFFF']
      })()
    • Get the blockNo of sector trailer.

      Parameters

      • sector: number

        The sector number.

      Returns number

      The blockNo of sector trailer.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async () => {
      const { ChameleonUltra } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      console.log(ChameleonUltra.mf1TrailerBlockNoOfSector(0)) // 3
      })()

    Mifare Ultralight Related

    • Read the counter and tearing of actived slot.

      NTAG21x features a NFC counter function. The NFC counter is enabled or disabled with the NFC_CNT_EN bit. This function enables NTAG21x to automatically increase the 24 bit counter value, triggered by the first valid READ or FAST_READ command after the NTAG21x tag is powered by an RF field.

      Parameters

      • addr: number

        The address of the counter.

      Returns Promise<{ counter?: number; tearing?: boolean }>

      • counter: The counter of the specified address.
      • tearing: The slot is in tearing mode or not.
      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      console.log(await ultra.cmdMfuGetEmuCounter(0))
      // { "counter": 0, "tearing": false }
      })(vm.ultra)
    • Get the number of pages available in the actived slot.

      Returns Promise<number>

      The number of pages available in the actived slot.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      console.log(await ultra.cmdMfuGetEmuPageSize()) // 135
      })(vm.ultra)
    • Get the signature of actived slot. NTAG21x features a cryptographically supported originality check. The signature is used to verify with a certain confidence that the tag is using an IC manufactured by NXP Semiconductors. The signature digital is based on standard Elliptic Curve Cryptography (curve name secp128r1), according to the ECDSA algorithm.

      Returns Promise<undefined | Buffer>

      The signature of actived slot.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const data = await ultra.cmdMfuGetEmuSignature()
      console.log(data.toString('hex')) // '0000000000000000000000000000000000000000000000000000000000000000'
      })(vm.ultra)
    • Get the version of actived slot. The version is used to retrieve information on the NTAG family, the product version, storage size and other product data required to identify the specific NTAG21x.

      Returns Promise<undefined | Buffer>

      The version of actived slot.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const data = await ultra.cmdMfuGetEmuVersion()
      console.log(data.toString('hex')) // '0004040201001103'
      })(vm.ultra)
    • Get the magic mode of actived slot.

      If the actived slot is in magic mode, all read and write protection is bypassed.

      • The UID (page 0-1) can be write.
      • Static Lock Bytes (page 2) and Dynamic Lock Bytes can be write with any value.
      • The Capability Container CC of NTAG (page 3) can be write with any value.
      • PWD and PACK can be read.
      • All other pages can be read/write without authentication.
      • The counter of NTAG can be read without authentication.

      Returns Promise<boolean>

      The magic mode of actived slot.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      console.log(await ultra.cmdMfuGetMagicMode()) // false
      })(vm.ultra)
    • Get the page data of actived slot.

      Parameters

      • offset: number = 0

        The start page of actived slot.

      • length: number = 1

        The count of pages to be get. Must satisfy: 1 <= length <= 128.

      Returns Promise<Buffer>

      The page data of actived slot.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const data = await ultra.cmdMfuReadEmuPage(1)
      console.log(data.toString('hex')) // 'fa5c6480'
      })(vm.ultra)
    • Reset the authentication failed counter of actived slot.

      Returns Promise<number>

      The original value of the unsuccessful auth counter before reset.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      console.log(await ultra.cmdMfuResetEmuAuthFailedCounter()) // 0
      })(vm.ultra)
    • Set the counter and reset tearing of actived slot.

      NTAG21x features a NFC counter function. The NFC counter is enabled or disabled with the NFC_CNT_EN bit. This function enables NTAG21x to automatically increase the 24 bit counter value, triggered by the first valid READ or FAST_READ command after the NTAG21x tag is powered by an RF field.

      Parameters

      • opts: { addr?: number; counter?: number; resetTearing?: boolean }
        • Optionaladdr?: number

          The address of the counter.

        • Optionalcounter?: number

          The counter to be write. The counter must be a 24-bit unsigned integer.

        • OptionalresetTearing?: boolean

          true to reset tearing.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdMfuSetEmuCounter({ addr: 0, counter: 1 })
      console.log(await ultra.cmdMfuGetEmuCounter(0))
      // { "counter": 1, "tearing": false }
      })(vm.ultra)
    • Set the signature of actived slot. NTAG21x features a cryptographically supported originality check. The signature is used to verify with a certain confidence that the tag is using an IC manufactured by NXP Semiconductors. The signature digital is based on standard Elliptic Curve Cryptography (curve name secp128r1), according to the ECDSA algorithm.

      Parameters

      • signature: Buffer

        The signature. The signature must be a 32 bytes Buffer.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const signature = Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex')
      await ultra.cmdMfuSetEmuSignature(signature)
      })(vm.ultra)
    • Set the version of actived slot. The version is used to retrieve information on the NTAG family, the product version, storage size and other product data required to identify the specific NTAG21x.

      Parameters

      • version: Buffer

        The version of actived slot.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdMfuSetEmuVersion(Buffer.from('0004040201001103', 'hex'))
      })(vm.ultra)
    • Set the magic mode of actived slot.

      If the actived slot is in magic mode, all read and write protection is bypassed.

      • The UID (page 0-1) can be write.
      • Static Lock Bytes (page 2) and Dynamic Lock Bytes can be write with any value.
      • The Capability Container CC of NTAG (page 3) can be write with any value.
      • PWD and PACK can be read.
      • All other pages can be read/write without authentication.
      • The counter of NTAG can be read without authentication.

      Parameters

      • enable: number | boolean

        The magic mode of actived slot.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdMfuSetMagicMode(false)
      })(vm.ultra)
    • Set the page data of actived slot.

      Parameters

      • offset: number

        The start page of actived slot.

      • data: Buffer

        The data to be write. Length of data must be multiples of 4 and satisfy: 4 <= data.length <= 508.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdMfuWriteEmuPage(1, Buffer.from('fa5c6480', 'hex'))
      })(vm.ultra)
    • Assert the tag type of actived slot is Mifare Ultralight like. Throw an error if the tag type is not Mifare Ultralight like.

      Returns Promise<TagType>

      The tag type of actived slot.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { TagType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const tagType = await ultra.mfuAssertEmuTagType()
      console.log(TagType[tagType]) // '040dc445420d2981e7480000e1100600'
      })(vm.ultra)
    • A protected memory area can be accessed only after a successful password verification using the PWD_AUTH command. The AUTH0 configuration byte defines the protected area. It specifies the first page that the password mechanism protects. The level of protection can be configured using the PROT bit either for write protection or read/write protection. The PWD_AUTH command takes the password as parameter and, if successful, returns the password authentication acknowledge, PACK. By setting the AUTHLIM configuration bits to a value larger than 000b, the number of unsuccessful password verifications can be limited. Each unsuccessful authentication is then counted in a counter featuring anti-tearing support. After reaching the limit of unsuccessful attempts, the memory access specified in PROT, is no longer possible.

      Parameters

      • opts: { autoSelect?: boolean; keepRfField?: boolean; key: Buffer; timeout?: number }
        • OptionalautoSelect?: boolean

          true to enable auto-select, false to disable auto-select.

        • OptionalkeepRfField?: boolean

          true to keep RF field after auth, false to disable RF field.

        • key: Buffer

          The password to be verified. The password must be a 4 bytes Buffer.

        • Optionaltimeout?: number

      Returns Promise<Buffer>

      The password authentication acknowledge, PACK

    • Detect Mifare Ultralight tag and return the tag infomation.

      Returns Promise<NxpMfuType>

      The tag infomation of detected tag.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { NxpMfuTypeName } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const NxpMfuType = await ultra.mfuDetectTagType()
      console.log(`tagType = ${NxpMfuTypeName.get(NxpMfuType)}`)
      })(vm.ultra)
    • Read multiple pages from start to end. For example if the start address is 0x03 and the end address is 0x07 then pages 0x03, 0x04, 0x05, 0x06 and 0x07 are returned. If the addressed page is outside of accessible area, NTAG21x replies a NAK.

      Parameters

      • opts: { end: number; key?: Buffer; start: number; timeout?: number }
        • end: number

          end page address

        • Optionalkey?: Buffer

          The password to be verified. The password must be a 4 bytes Buffer.

        • start: number

          start page address

        • Optionaltimeout?: number

      Returns Promise<Buffer>

      4 pages (16 bytes)

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const data = await ultra.mfuFastReadPages({ start: 0, end: 3 })
      console.log(data.toString('hex')) // '047c79896cb62a8171480000e1103e00'
      })(vm.ultra)
    • Get the mifare ultralight settings of actived emulator slot.

      Returns Promise<
          {
              counters: (undefined | number)[];
              magic?: boolean;
              pageSize?: number;
              signature?: Buffer;
              tearing?: boolean;
              version?: Buffer;
          },
      >

      • counters: The value of the NFC one-way counter.
      • magic: The magic mode.
      • pageSize: The page size.
      • signature: The IC specific, 32-byte ECC signature.
      • tearing: The slot is in tearing mode or not.
      • version: The version information for the specific NTAG21x type.
      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const data = await ultra.mfuGetEmuSettings()
      console.log(data)
      })(vm.ultra)
    • The GET_VERSION command is used to retrieve information on the NTAG family, the product version, storage size and other product data required to identify the specific NTAG21x. This command is also available on other NTAG products to have a common way of identifying products across platforms and evolution steps. The GET_VERSION command has no arguments and replies the version information for the specific NTAG21x type.

      Parameters

      • opts: { timeout?: number } = {}

      Returns Promise<Buffer>

      • response for NTAG213, NTAG215 and NTAG216
      Byte no. Description NTAG213 NTAG215 NTAG216 Interpretation
      0 fixed Header 0x00 0x00 0x00
      1 vendor ID 0x04 0x04 0x04 NXP Semiconductors
      2 product type 0x04 0x04 0x04 NTAG
      3 product subtype 0x02 0x02 0x02 50 pF
      4 major product version 0x01 0x01 0x01 1
      5 minor product version 0x00 0x00 0x00 V0
      6 storage size 0x0F 0x11 0x13 reference
      7 protocol 0x03 0x03 0x03 ISO/IEC 14443-3 compliant
      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const data = await ultra.mfuGetVersion()
      console.log(data.toString('hex')) // '0004040201001103'
      })(vm.ultra)
    • The READ_CNT command is used to read out the current value of the NFC one-way counter of the Mifare Ultralight. The command has a single argument specifying the counter number and returns the 24-bit counter value of the corresponding counter. If the NFC_CNT_PWD_PROT bit is set to 1b the counter is password protected and can only be read with the READ_CNT command after a previous valid password authentication.

      Parameters

      • opts: { addr?: number; key?: Buffer }
        • Optionaladdr?: number

          The counter addr to read. Must be 0, 1 or 2. Default is 2.

        • Optionalkey?: Buffer

          The password to be verified. The password must be a 4 bytes Buffer.

      Returns Promise<number>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const cnt = await ultra.mfuReadCounter({ addr: 2 })
      console.log(cnt) // 0
      })(vm.ultra)
    • Read the dump of Mifare Ultralight tag.

      Parameters

      • opts: { end?: number; key?: Buffer; start?: number } = {}
        • Optionalend?: number

          end page address

        • Optionalkey?: Buffer

          The key to read pages if tag is read protected.

        • Optionalstart?: number

          start page address

      Returns Promise<Buffer>

      The dump of Mifare Ultralight tag.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const dump = await ultra.mfuReadDump()
      console.log(`Read ${dump.length} bytes.`) // Read 160 bytes.
      return dump
      })(vm.ultra)
    • Get the mifare ultralight emulator data of actived slot.

      Returns Promise<Buffer>

      The mifare ultralight emulator data of actived slot.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const dump = await ultra.mfuReadEmuDump()
      console.log(`Read ${dump.length} bytes.`)
      })(vm.ultra)
    • Read 4 pages (16 bytes) from Mifare Ultralight

      Parameters

      • opts: { key?: Buffer; start: number; timeout?: number }
        • Optionalkey?: Buffer

          The password to be verified. The password must be a 4 bytes Buffer.

        • start: number

          start page address

        • Optionaltimeout?: number

      Returns Promise<Buffer>

      4 pages (16 bytes)

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const data = await ultra.mfuReadPages({ start: 0 })
      console.log(data.toString('hex')) // '040dc445420d2981e7480000e1100600'
      })(vm.ultra)
    • The READ_SIG command returns an IC specific, 32-byte ECC signature, to verify NXP Semiconductors as the silicon vendor. The signature is programmed at chip production and cannot be changed afterwards.

      Returns Promise<Buffer>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const data = await ultra.mfuReadSignature()
      console.log(data.toString('base64url')) // 'w9dq8MPprf1Ro-C1si32rg3y7cO8UChrtXlNyjLScS4'
      })(vm.ultra)
    • Write new dump to the actived slot.

      Parameters

      • dump: Buffer

        New dump to be write to actived slot.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const dump = new Buffer(540) // Dump size of NTAG_213 is 540 bytes.
      dump.set(Buffer.from('04689571fa5c648042480fe0', 'hex'))
      dump.set(Buffer.from('040000ff00000000ffffffff', 'hex'), 524)
      await ultra.mfuWriteEmuDump(dump)
      })(vm.ultra)
    • Write 1 page (4 bytes) to Mifare Ultralight

      Parameters

      • opts: { data: Buffer; key?: Buffer; start: number }
        • data: Buffer

          4 bytes, the page data to be written.

        • Optionalkey?: Buffer

          The password to be verified. The password must be a 4 bytes Buffer.

        • start: number

          start page address

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const data = await ultra.mfuWritePage({ start: 9, data: Buffer.from('00000000', 'hex') })
      })(vm.ultra)

    DFU Related

    • Abort the DFU procedure.

      Returns Promise<void>

      Please refer to nRF5 SDK: DFU Protocol for more infomation.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdDfuEnter()
      await ultra.cmdDfuAbort()
      })(vm.ultra)
    • Enter bootloader mode.

      Returns Promise<void>

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdDfuEnter()
      })(vm.ultra)
    • Retrieve firmware version.

      Parameters

      Returns Promise<{ addr: number; len: number; type: DfuFwType; version: number }>

      • addr: Firmware address in flash.
      • len: Firmware length in bytes.
      • type: Firmware type.
      • version: Firmware version.

      Please refer to nRF5 SDK: DFU Protocol for more infomation.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { DfuFwId, DfuFwType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      await ultra.cmdDfuEnter()
      for (const fwId of [DfuFwId.BOOTLOADER, DfuFwId.APPLICATION, DfuFwId.SOFTDEVICE]) {
      const { type, version, addr, len } = await ultra.cmdDfuGetFirmwareVersion(fwId)
      console.log(`type = ${DfuFwType[type]}, version = ${version}, addr = 0x${addr.toString(16)}, len = ${len}`)
      }
      await ultra.cmdDfuAbort()
      // type = BOOTLOADER, version = 1, addr = 0xf3000, len = 45056
      // type = SOFTDEVICE, version = 7002000, addr = 0x1000, len = 159744
      // type = APPLICATION, version = 1, addr = 0x27000, len = 222844
      })(vm.ultra)
    • Retrieve hardware version.

      Returns Promise<
          {
              part: string;
              ramSize: number;
              romPageSize: number;
              romSize: number;
              variant: string;
          },
      >

      • part: Hardware part, from FICR register.
      • ramSize: RAM size, in bytes.
      • romPageSize: ROM flash page size, in bytes.
      • romSize: ROM size, in bytes.
      • variant: Hardware variant, from FICR register.

      Please refer to nRF5 SDK: DFU Protocol for more infomation.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdDfuEnter()
      console.log(await ultra.cmdDfuGetHardwareVersion())
      await ultra.cmdDfuAbort()
      // {
      // "part": "nRF52840",
      // "variant": "AAD0",
      // "romSize": 1048576,
      // "ramSize": 262144,
      // "romPageSize": 4096
      // }
      })(vm.ultra)
    • Retrieve MTU size.

      Returns Promise<undefined | number>

      The preferred MTU size on this request.

      Please refer to nRF5 SDK: DFU Protocol for more infomation.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdDfuEnter()
      console.log(await ultra.cmdDfuGetMtu()) // Print: 1025
      await ultra.cmdDfuAbort()
      })(vm.ultra)
    • Retrieve DFU protocol version.

      Syntax and ID of this command is permanent. If protocol version changes other opcode may not be valid any more.

      Returns Promise<number>

      Protocol version.

      Please refer to nRF5 SDK: DFU Protocol for more infomation.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdDfuEnter()
      console.log(await ultra.cmdDfuGetProtocol()) // Print: 1
      await ultra.cmdDfuAbort()
      })(vm.ultra)
    • Ping.

      Parameters

      • id: number

        Ping ID that will be returned in response.

      Returns Promise<number>

      The received ID which is echoed back.

      Please refer to nRF5 SDK: DFU Protocol for more infomation.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      await ultra.cmdDfuEnter()
      console.log(await ultra.cmdDfuPing(1)) // Print: 1
      await ultra.cmdDfuAbort()
      })(vm.ultra)
    • Select object.

      Parameters

      Returns Promise<{ crc32: number; maxSize: number; offset: number }>

      • crc32: Current CRC.
      • maxSize: Maximum size of selected object.
      • offset: Current offset.

      Please refer to nRF5 SDK: DFU Protocol for more infomation.

    • Set receipt notification

      This request configures the frequency of sending CRC responses after Write request commands.

      Parameters

      • prn: number

        If set to 0, then the CRC response is never sent after Write request. Otherwise, it is sent every prn'th Write request.

      Returns Promise<void>

      Please refer to nRF5 SDK: DFU Protocol for more infomation.

    • Upload DFU image.

      Parameters

      • image: { body: Buffer; header: Buffer; type: DfuImageType }

        The DFU image.

      Returns Promise<void>

      Please refer to nRF5 SDK: DFU Protocol for more infomation.

      // you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
      await (async ultra => {
      const { DeviceModel } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
      const { default: DfuZip } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/plugin/DfuZip.mjs/+esm')
      const model = (await ultra.cmdGetDeviceModel()) === DeviceModel.ULTRA ? 'ultra' : 'lite'
      const dfuZipUrl = `https://taichunmin.idv.tw/ChameleonUltra-releases/dev/${model}-dfu-app.zip`
      const dfuZip = new DfuZip(new Buffer((await axios.get(dfuZipUrl, { responseType: 'arraybuffer' }))?.data))
      const image = await dfuZip.getAppImage()
      const imageGitVersion = await dfuZip.getGitVersion()
      console.log({ type: image.type, headerSize: image.header.length, bodySize: image.body.length, gitVersion: imageGitVersion })
      // {
      // "type": "application",
      // "headerSize": 141,
      // "bodySize": 222844,
      // "gitVersion": "v2.0.0-135-g3cadd47"
      // }
      const gitVersion = await ultra.cmdGetGitVersion()
      console.log(`gitVersion = ${gitVersion}`) // Print: gitVersion = v2.0.0-135-g3cadd47
      await ultra.cmdDfuEnter()
      ultra.emitter.on('progress', console.log)
      // {
      // "func": "dfuUpdateObject",
      // "offset": 0,
      // "size": 222844,
      // "type": 2
      // }
      await ultra.dfuUpdateImage(image)
      ultra.emitter.removeListener('progress', console.log)
      })(vm.ultra)

    Internal

    • Internal

      Register a hook.

      Parameters

      • hookName: string

        The hook name.

      • fn: (ctx: Record<string, any>, next: () => Promise<unknown>) => Promise<unknown>

        The function to register.

      Returns this

    • Internal

      Invoke a hook with context.

      Parameters

      • hookName: string

        The hook name.

      • ctx: any = {}

        The context will be passed to every middleware.

      • Optionalnext: (ctx: Record<string, any>, next: () => Promise<unknown>) => Promise<unknown>

        The next middleware function.

      Returns Promise<unknown>

      The return value depent on the middlewares

    • Internal

      Register a plugin.

      Parameters

      • plugin: {
            install: <T extends { Buffer: typeof Buffer; ultra: ChameleonUltra }>(
                context: T,
                pluginOption: any,
            ) => Promise<unknown>;
            name: string;
        }

        The plugin to register.

      • Optionaloption: any

        The option to pass to plugin.install().

      Returns Promise<ChameleonUltra>