Skip to content

CIP-67 — Asset name labels

CIP67 (Cardano Improvement Proposal 67) defines a standard for asset name labels on the Cardano blockchain. The Cardano Client Library provides utilities for creating, validating, and working with CIP67-compliant asset names. The utilities keep the rules around padding, CRC8 checksum, and label ranges in one place so you can focus on assembling asset names without re-implementing the bit-twiddling logic.

  • Label Encoding: Convert decimal labels to CIP67 asset name prefixes
  • Label Decoding: Extract labels from CIP67 asset names
  • Validation: Verify CIP67 compliance and checksum validation
  • CRC8 Checksum: Built-in CRC8 checksum calculation and verification
  • Standard Compliance: Full CIP67 specification support
  • Group ID: com.bloxbean.cardano
  • Artifact ID: cardano-client-cip67
  • Dependencies: crypto

Generate the 4-byte prefix for a given label; you can append your own suffix bytes afterwards.

// Convert a decimal label to CIP67 asset name prefix
int label = 222; // Label range: [0, 65535]
byte[] prefixBytes = CIP67AssetNameUtil.labelToPrefix(label);
// Convert to hex string for display
String prefixHex = HexUtil.encodeHexString(prefixBytes);
System.out.println("Label " + label + " -> Prefix: " + prefixHex);
// Output: Label 222 -> Prefix: 000de140

Recover the numeric label from the prefix to inspect or validate existing assets.

// Extract label from CIP67 asset name prefix
byte[] prefixBytes = HexUtil.decodeHexString("000de140");
int extractedLabel = CIP67AssetNameUtil.prefixToLabel(prefixBytes);
System.out.println("Prefix 000de140 -> Label: " + extractedLabel);
// Output: Prefix 000de140 -> Label: 222

isValidAssetName checks the padding and the checksum. It doesn’t check every padding bit (see known issues), so treat it as a sanity check rather than proof of a well-formed name.

// Validate asset name from bytes
byte[] assetNameBytes = HexUtil.decodeHexString("000de140");
boolean isValidBytes = CIP67AssetNameUtil.isValidAssetName(assetNameBytes);
System.out.println("Asset name valid (bytes): " + isValidBytes);
// Output: Asset name valid (bytes): true
// Validate asset name from integer
int assetNameInt = 0x000de140;
boolean isValidInt = CIP67AssetNameUtil.isValidAssetName(assetNameInt);
System.out.println("Asset name valid (int): " + isValidInt);
// Output: Asset name valid (int): true

Combine the CIP67 prefix with your human-readable suffix to form the final asset name used in minting.

// Create asset name with CIP67 label
int label = 222; // NFT label
byte[] labelPrefix = CIP67AssetNameUtil.labelToPrefix(label);
// Create full asset name by combining prefix with unique suffix
byte[] uniqueSuffix = "MyNFT".getBytes(StandardCharsets.UTF_8);
byte[] fullAssetName = new byte[labelPrefix.length + uniqueSuffix.length];
System.arraycopy(labelPrefix, 0, fullAssetName, 0, labelPrefix.length);
System.arraycopy(uniqueSuffix, 0, fullAssetName, labelPrefix.length, uniqueSuffix.length);
// Create asset with CIP67-compliant name
Asset nftAsset = Asset.builder()
.name("0x" + HexUtil.encodeHexString(fullAssetName)) // without 0x, the text is read as UTF-8
.value(BigInteger.ONE)
.build();

Run validations over multiple asset names and extract labels where valid.

// Process multiple asset names
List<String> assetNameHexes = Arrays.asList(
"000de140", // Valid CIP67 asset name
"000de141", // Invalid padding
"100de140", // Invalid checksum
"000de130" // Invalid checksum
);
for (String assetNameHex : assetNameHexes) {
byte[] assetNameBytes = HexUtil.decodeHexString(assetNameHex);
boolean isValid = CIP67AssetNameUtil.isValidAssetName(assetNameBytes);
if (isValid) {
int label = CIP67AssetNameUtil.prefixToLabel(assetNameBytes);
System.out.println(assetNameHex + " -> Valid, Label: " + label);
} else {
System.out.println(assetNameHex + " -> Invalid");
}
}

Predefined labels are handy for common asset categories; encode them once and reuse.

// Common CIP67 labels
Map<Integer, String> commonLabels = new HashMap<>();
commonLabels.put(222, "NFT Standard");
commonLabels.put(333, "Fungible Token Standard");
commonLabels.put(444, "Rich Fungible Token Standard");
for (Map.Entry<Integer, String> entry : commonLabels.entrySet()) {
int label = entry.getKey();
String description = entry.getValue();
byte[] prefix = CIP67AssetNameUtil.labelToPrefix(label);
String prefixHex = HexUtil.encodeHexString(prefix);
System.out.println("Label " + label + " (" + description + ") -> " + prefixHex);
}

Utility class for CIP67 asset name operations.

Converts a decimal label to CIP67 asset name prefix.

public static byte[] labelToPrefix(int label)

Parameters:

  • label - Decimal label in range [0, 65535]

Returns: 4-byte prefix array

Extracts the label from CIP67 asset name prefix.

public static int prefixToLabel(byte[] labelBytes)

Parameters:

  • labelBytes - 4-byte prefix array

Returns: Decimal label

Validates a CIP67 asset name from integer value.

public static boolean isValidAssetName(int assetName)

Parameters:

  • assetName - Asset name as integer

Returns: true if valid CIP67 asset name

Validates a CIP67 asset name from byte array.

public static boolean isValidAssetName(byte[] assetName)

Parameters:

  • assetName - Asset name as byte array

Returns: true if valid CIP67 asset name

A CIP-67 prefix is 4 bytes, [0000 | 16-bit label | 8-bit CRC8 checksum | 0000], followed by the rest of the asset name.

  • Range: 0 to 65535
  • Encoding: Big-endian format
  • Checksum: CRC8 validation required
  1. Padding Check: The first and last 4 bits must be 0000
  2. Checksum Verification: The CRC8 checksum must match the label
LabelDescriptionPrefix (Hex)
100CIP-68 reference token000643b0
222CIP-68 NFT000de140
333CIP-68 fungible token0014df10
444CIP-68 rich fungible token001bc280
  1. Use Standard Labels: Use established labels (222, 333, 444) for common asset types
  2. Validate Asset Names: Always validate asset names before using them
  3. Handle Errors: Check validation results before processing asset names
  4. Preserve Checksums: Don’t modify asset name prefixes without recalculating checksums
  5. Document Custom Labels: Document any custom labels used in your application
// Create CIP68-compliant asset name
int label = 222; // NFT label for CIP68
byte[] labelPrefix = CIP67AssetNameUtil.labelToPrefix(label);
// Combine with asset-specific data, in hex with a 0x prefix
String assetName = "0x" + HexUtil.encodeHexString(labelPrefix)
+ HexUtil.encodeHexString("MyUniqueNFT".getBytes(StandardCharsets.UTF_8));

For more information about CIP67, refer to the official CIP67 specification.