> ## Documentation Index
> Fetch the complete documentation index at: https://iso8583sim.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# PIN blocks

> ISO 9564-1 PIN blocks (formats 0, 1, 3 and 4).

`iso8583sim.security.pinblock`

For testing and simulation only. Real PIN handling happens inside an HSM, and clear PINs
and keys must never pass through application code like this.

## Functions

### `encode_pin_block()`

```python theme={null}
def encode_pin_block(pin: str, pan: str | None = None, fmt: int = 0) -> bytes
```

Build a clear (unencrypted) 8-byte PIN block in format 0, 1 or 3.

**Parameters**

<ResponseField name="pin" type="str" required>
  4 to 12 digit PIN
</ResponseField>

<ResponseField name="pan" type="str | None" default="None">
  Primary Account Number (required for formats 0 and 3)
</ResponseField>

<ResponseField name="fmt" type="int" default="0">
  PIN block format: 0, 1 or 3
</ResponseField>

<ResponseField name="Returns" type="bytes">
  The 8-byte clear PIN block
</ResponseField>

### `decode_pin_block()`

```python theme={null}
def decode_pin_block(block: bytes, pan: str | None = None, fmt: int = 0) -> str
```

Recover the PIN from a clear 8-byte PIN block in format 0, 1 or 3.

### `encrypt_pin_block()`

```python theme={null}
def encrypt_pin_block(pin: str, pan: str | None, key: str | bytes, fmt: int = 0) -> str
```

Build an encrypted PIN block as it appears in field 52.

Formats 0, 1 and 3 use a double or triple length TDES key and give 8 bytes. Format 4
uses an AES key and gives 16 bytes, which fits field 52 in the 1993 and 2003 versions.

**Parameters**

<ResponseField name="pin" type="str" required>
  4 to 12 digit PIN
</ResponseField>

<ResponseField name="pan" type="str | None" required>
  Primary Account Number (not used by format 1)
</ResponseField>

<ResponseField name="key" type="str | bytes" required>
  PIN encryption key as bytes or hex
</ResponseField>

<ResponseField name="fmt" type="int" default="0">
  PIN block format: 0, 1, 3 or 4
</ResponseField>

<ResponseField name="Returns" type="str">
  The encrypted PIN block as uppercase hex
</ResponseField>

### `decrypt_pin_block()`

```python theme={null}
def decrypt_pin_block(
    block: str | bytes,
    pan: str | None,
    key: str | bytes,
    fmt: int = 0,
) -> str
```

Recover the PIN from an encrypted PIN block (formats 0, 1, 3 and 4).

A wrong key is detected in every format, because it scrambles the whole block. A wrong
PAN is always detected in format 4, but only sometimes in formats 0 and 3: there the PAN
is applied with a single XOR, so a different PAN can still decode to a well-formed block
with a different PIN. This is a property of those formats, not of this implementation.

**Raises**

* `SecurityError`: The block doesn't decode to a valid PIN block


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.