cryptnox-sdk-arduino 1.0.0
Arduino library for Cryptnox Hardware Wallet
Loading...
Searching...
No Matches
BasicUsage.ino

Example demonstrating the use of CryptnoxWallet with a PN532 module on Arduino.

Example demonstrating the use of CryptnoxWallet with a PN532 module on Arduino.This sketch initializes the PN532 NFC reader using the CryptnoxWallet class. It continuously detects NFC/ISO-DEP cards and processes wallet-specific APDU commands with granular step-by-step control.

Select the communication interface by defining USE_SPI or USE_I2C below.

/*
* SPDX-License-Identifier: LGPL-3.0-or-later
* Copyright (c) 2026 Cryptnox SA
*/
#include <CryptnoxWallet.h>
/* ============================================================================
* 1. Interface Selection
* --------------------------------------------------------------------------
* Uncomment exactly ONE of the two lines below to choose the PN532 interface.
* ========================================================================= */
#define USE_SPI
// #define USE_I2C
/* ============================================================================
* 2. Pin Configuration
* ========================================================================= */
#if defined(USE_SPI)
#include <SPI.h>
#define PN532_SS (10U)
/* PRODUCTION NOTE (LOW-03): ArduinoLoggerAdapter streams all log output over
* USB-CDC Serial, which is visible to any attached host process. For firmware
* that is shipped to end-users, replace the two lines below with:
* NullLoggerAdapter serialAdapter;
* and remove the serialAdapter.begin() call in setup(). NullLoggerAdapter is
* a no-op and incurs zero code-size or runtime overhead. */
#elif defined(USE_I2C)
#include <Wire.h>
#define PN532_IRQ (2U)
#define PN532_RST (3U)
/* PRODUCTION NOTE (LOW-03): see comment in the USE_SPI block above. */
PN532Adapter nfc(serialAdapter, PN532_IRQ, PN532_RST, &Wire);
#else
#error "Please define USE_SPI or USE_I2C to select the PN532 interface."
#endif
#define DEFAULT_PIN "000000000"
#define DEFAULT_PIN_LEN (sizeof(DEFAULT_PIN) - 1U)
void setup() {
serialAdapter.begin(115200);
/* Arduino R4: Wait 1s to get Serial ready */
delay(1000);
#if defined(USE_SPI)
/* Initialize SPI bus */
SPI.begin();
#elif defined(USE_I2C)
/* Initialize I2C bus */
Wire.begin();
#endif
/* Initialize the PN532 module — halt on failure to avoid silent errors */
if (!wallet.begin()) {
serialAdapter.println(F("PN532 init failed"));
while(1);
}
}
void loop() {
/* Step 1: Connect to card and establish secure channel */
if (wallet.connect(session)) {
serialAdapter.println(F("Card connected and secure channel established"));
/* Step 2: Sign a test hash (32 bytes of 0x01 for demo purposes) */
/* NOTE: Card must have a seed loaded (via Python SDK: card.generate_seed(pin) */
/* or card.load_seed(seed, pin)) before signing will work. */
serialAdapter.println(F("Signing test hash..."));
uint8_t testHash[CW_HASH_SIZE];
memset(testHash, 0x01, sizeof(testHash));
/* Build sign request per CW_SignRequest API.
* PIN is included in the sign data payload for authentication.
* Alternatively, call verifyPin() first and omit the PIN here. */
signRequest.hash = testHash;
signRequest.hashLength = sizeof(testHash);
/* Set PIN (must match the PIN used during card.init()) */
CW_Utils::safe_memcpy(signRequest.pin, sizeof(signRequest.pin),
reinterpret_cast<const uint8_t*>(DEFAULT_PIN), DEFAULT_PIN_LEN);
CW_SignResult signResult = wallet.sign(signRequest);
if (signResult.errorCode == CW_OK) {
serialAdapter.println(F("Signature received (64 bytes raw r||s)"));
/* Print first 8 bytes of R and S for quick visual check */
serialAdapter.print(F(" R[0..7]: "));
for (uint8_t i = CW_SIG_R_OFFSET; i < CW_SIG_R_OFFSET + 8U; i++) {
if (signResult.signature[i] < 0x10U) serialAdapter.print(F("0"));
serialAdapter.print(signResult.signature[i], HEX);
serialAdapter.print(F(" "));
}
serialAdapter.println();
serialAdapter.print(F(" S[0..7]: "));
for (uint8_t i = CW_SIG_S_OFFSET; i < CW_SIG_S_OFFSET + 8U; i++) {
if (signResult.signature[i] < 0x10U) serialAdapter.print(F("0"));
serialAdapter.print(signResult.signature[i], HEX);
serialAdapter.print(F(" "));
}
serialAdapter.println();
serialAdapter.println(F("Card processed successfully"));
} else {
serialAdapter.print(F("Sign failed, errorCode: 0x"));
serialAdapter.println(signResult.errorCode, HEX);
}
/* Securely wipe sensitive buffers */
CW_Utils::secure_wipe(testHash, sizeof(testHash));
CW_Utils::secure_wipe(signResult.signature, sizeof(signResult.signature));
}
/* Always disconnect to reset reader for next card detection */
wallet.disconnect(session);
/* Wait before next iteration */
delay(1000);
}
#define DEFAULT_PIN
Default PIN code (ASCII digits). Must match the PIN used during card.init().
void setup()
Arduino setup function.
CryptnoxWallet wallet(nfc, serialAdapter, cryptoProvider, platform)
#define PN532_SS
SPI slave select (CS) pin for the PN532 module.
PN532Adapter nfc(serialAdapter, PN532_SS, &SPI)
#define DEFAULT_PIN_LEN
ArduinoLoggerAdapter serialAdapter
ArduinoPlatform platform
ArduinoCryptoProvider cryptoProvider
void loop()
Arduino main loop.
#define CW_SIG_R_OFFSET
Definition CW_Defs.h:116
#define CW_HASH_SIZE
Definition CW_Defs.h:108
#define CW_OK
Definition CW_Defs.h:80
#define CW_SIGN_WITH_PIN
Definition CW_Defs.h:92
#define CW_SIGN_CURR_K1
Definition CW_Defs.h:85
#define CW_SIGN_SIG_ECDSA_LOW_S
Definition CW_Defs.h:96
#define CW_SIG_S_OFFSET
Definition CW_Defs.h:117
CW_CryptoProvider implementation for the Arduino UNO R4 (RA4M1).
CW_Logger implementation wrapping Arduino's HardwareSerial.
CW_Platform implementation using Arduino's blocking delay().
static bool safe_memcpy(uint8_t *dst, size_t dstSize, const uint8_t *src, size_t count)
Safe memcpy — validates pointers, sizes, and checks for overlap.
Definition CW_Utils.cpp:50
static void secure_wipe(uint8_t *buf, size_t len)
Securely zero a buffer, guaranteed not to be optimised away.
Definition CW_Utils.cpp:37
High-level interface for interacting with a Cryptnox Hardware Wallet over NFC.
CW_NfcTransport implementation over the Adafruit_PN532 driver.
#define F(string_literal)
#define HEX
Holds cryptographic session state for reentrant secure channel operations.
Definition CW_Defs.h:168
Request parameters for CryptnoxWallet::sign.
Result of CryptnoxWallet::sign.
uint8_t signature[CW_RAW_SIGNATURE_SIZE]