0
# Utilities
1
2
Comprehensive utility functions for data conversion between different formats (hex strings, byte lists, ASCII), padding operations, and specialized encoding support. These utilities are essential for smart card data processing and formatting.
3
4
## Capabilities
5
6
### Data Format Conversion
7
8
Core functions for converting between different data representations commonly used in smart card applications.
9
10
```python { .api }
11
def toHexString(data, output_format=0):
12
"""
13
Convert a list of integers to formatted hexadecimal string.
14
15
Args:
16
data (list[int] | None): List of bytes to convert (0-255)
17
output_format (int): Formatting options (bitwise OR of format constants)
18
19
Returns:
20
str: Formatted hexadecimal string
21
22
Format constants:
23
PACK (1): Remove spaces between bytes
24
HEX (2): Add 0x prefix to each byte
25
UPPERCASE (4): Use uppercase 0X prefix (requires HEX)
26
COMMA (8): Add commas between bytes
27
"""
28
29
def toBytes(bytestring):
30
"""
31
Convert hexadecimal string to list of integers.
32
33
Args:
34
bytestring (str): Hex string (spaces optional), e.g. "3B 65 00" or "3B6500"
35
36
Returns:
37
list[int]: List of byte values (0-255)
38
39
Raises:
40
TypeError: If string is not valid hexadecimal
41
"""
42
43
def toASCIIBytes(string):
44
"""
45
Convert string to list of UTF-8 encoded bytes.
46
47
Args:
48
string (str): String to convert
49
50
Returns:
51
list[int]: List of UTF-8 byte values
52
"""
53
54
def toASCIIString(bytelist):
55
"""
56
Convert list of integers to ASCII string.
57
58
Args:
59
bytelist (list[int]): List of bytes (0-255)
60
61
Returns:
62
str: ASCII string with non-printable chars (outside 32-127) as periods
63
"""
64
```
65
66
### Specialized Encoding
67
68
Support for GSM 3.38 encoding commonly used in telecommunications smart cards.
69
70
```python { .api }
71
def toGSM3_38Bytes(stringtoconvert):
72
"""
73
Convert string to GSM 3.38 encoded bytes.
74
75
Args:
76
stringtoconvert (str | bytes): String to encode using GSM 3.38 character set
77
78
Returns:
79
list[int]: List of GSM 3.38 encoded bytes
80
81
Note:
82
Supports GSM 3.38 character set including Greek letters and special symbols
83
"""
84
```
85
86
### Data Padding
87
88
Utility for padding byte lists to specified lengths.
89
90
```python { .api }
91
def padd(bytelist, length, padding="FF"):
92
"""
93
Pad byte list with constant value to specified length.
94
95
Args:
96
bytelist (list[int]): List of bytes to pad
97
length (int): Target length (no padding if length <= current length)
98
padding (str): Hex string for padding byte (default "FF" = 0xFF)
99
100
Returns:
101
list[int]: Padded byte list
102
"""
103
```
104
105
### Format Constants
106
107
Constants for controlling hex string formatting output.
108
109
```python { .api }
110
# Format constants for toHexString()
111
PACK = 1 # Remove spaces between bytes: "3B6500"
112
HEX = 2 # Add 0x prefix: "0x3B 0x65 0x00"
113
UPPERCASE = 4 # Use 0X prefix: "0X3B 0X65 0X00" (requires HEX)
114
COMMA = 8 # Add commas: "3B, 65, 00"
115
```
116
117
### Deprecated Functions
118
119
Legacy functions maintained for backward compatibility.
120
121
```python { .api }
122
def HexListToBinString(hexlist):
123
"""
124
Deprecated: Convert hex list to binary string.
125
Use bytes(hexlist).decode("utf-8") instead.
126
127
Args:
128
hexlist (list[int]): List of bytes
129
130
Returns:
131
str: Decoded string
132
"""
133
134
def BinStringToHexList(binstring):
135
"""
136
Deprecated: Convert binary string to hex list.
137
Use list(binstring.encode("utf-8")) instead.
138
139
Args:
140
binstring (str): String to encode
141
142
Returns:
143
list[int]: List of encoded bytes
144
"""
145
146
# Deprecated aliases
147
hl2bs = HexListToBinString
148
bs2hl = BinStringToHexList
149
```
150
151
## Usage Examples
152
153
### Basic Data Conversion
154
155
```python
156
from smartcard.util import toHexString, toBytes, toASCIIBytes, toASCIIString
157
158
# Convert bytes to hex string (default format)
159
data = [0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03]
160
hex_str = toHexString(data)
161
print(f"Default: {hex_str}") # "3B 65 00 00 9C 11 01 01 03"
162
163
# Convert hex string back to bytes
164
bytes_back = toBytes(hex_str)
165
print(f"Bytes: {bytes_back}") # [59, 101, 0, 0, 156, 17, 1, 1, 3]
166
167
# ASCII conversion
168
text = "Hello, Card!"
169
ascii_bytes = toASCIIBytes(text)
170
print(f"ASCII bytes: {ascii_bytes}")
171
172
text_back = toASCIIString(ascii_bytes)
173
print(f"Text back: {text_back}") # "Hello, Card!"
174
```
175
176
### Hex String Formatting Options
177
178
```python
179
from smartcard.util import toHexString, PACK, HEX, UPPERCASE, COMMA
180
181
data = [0x3B, 0x65, 0x00, 0x00, 0x9C]
182
183
# Different formatting options
184
print(f"Default: {toHexString(data)}") # "3B 65 00 00 9C"
185
print(f"Packed: {toHexString(data, PACK)}") # "3B6500009C"
186
print(f"With 0x: {toHexString(data, HEX)}") # "0x3B 0x65 0x00 0x00 0x9C"
187
print(f"Uppercase: {toHexString(data, HEX | UPPERCASE)}") # "0X3B 0X65 0X00 0X00 0X9C"
188
print(f"Commas: {toHexString(data, COMMA)}") # "3B, 65, 00, 00, 9C"
189
print(f"All opts: {toHexString(data, HEX | UPPERCASE | COMMA)}") # "0X3B, 0X65, 0X00, 0X00, 0X9C"
190
```
191
192
### Data Padding
193
194
```python
195
from smartcard.util import padd, toHexString
196
197
# Pad to specific length
198
data = [0x3B, 0x65, 0x00]
199
padded = padd(data, 8) # Pad to 8 bytes with 0xFF
200
print(f"Padded: {toHexString(padded)}") # "3B 65 00 FF FF FF FF FF"
201
202
# Custom padding value
203
padded_custom = padd(data, 8, "00") # Pad with 0x00
204
print(f"Zero pad: {toHexString(padded_custom)}") # "3B 65 00 00 00 00 00 00"
205
206
# Pad with specific value
207
padded_80 = padd(data, 6, "80") # Pad with 0x80
208
print(f"0x80 pad: {toHexString(padded_80)}") # "3B 65 00 80 80 80"
209
```
210
211
### GSM 3.38 Encoding
212
213
```python
214
from smartcard.util import toGSM3_38Bytes, toHexString
215
216
# GSM 3.38 supports special characters
217
text = "@£$¥èéùì" # GSM 3.38 special characters
218
gsm_bytes = toGSM3_38Bytes(text)
219
print(f"GSM 3.38: {toHexString(gsm_bytes)}")
220
221
# Regular ASCII characters
222
text2 = "Hello123"
223
gsm_bytes2 = toGSM3_38Bytes(text2)
224
print(f"ASCII in GSM: {toHexString(gsm_bytes2)}")
225
```
226
227
### Practical Smart Card Data Processing
228
229
```python
230
from smartcard.util import toHexString, toBytes, toASCIIString, padd
231
from smartcard import Session
232
233
def format_apdu_trace(command, response, sw1, sw2):
234
"""Format APDU command and response for logging."""
235
cmd_hex = toHexString(command, toHexString.HEX | toHexString.UPPERCASE)
236
237
if response:
238
resp_hex = toHexString(response)
239
print(f">> {cmd_hex}")
240
print(f"<< {resp_hex} {sw1:02X} {sw2:02X}")
241
else:
242
print(f">> {cmd_hex}")
243
print(f"<< {sw1:02X} {sw2:02X}")
244
245
def process_text_data(response_bytes):
246
"""Process response data that might contain text."""
247
# Try to extract readable text
248
text = toASCIIString(response_bytes)
249
250
# Show both hex and text representations
251
print(f"Hex: {toHexString(response_bytes)}")
252
print(f"Text: '{text}'")
253
254
# Check for meaningful text (more than 50% printable)
255
printable_count = sum(1 for c in text if c.isprintable() and c != '.')
256
if printable_count / len(text) > 0.5:
257
print("Data appears to contain readable text")
258
else:
259
print("Data appears to be binary")
260
261
# Example usage with session
262
try:
263
session = Session()
264
265
# Send GET DATA command
266
GET_DATA = [0x00, 0xCA, 0x9F, 0x7F, 0x00]
267
response, sw1, sw2 = session.sendCommandAPDU(GET_DATA)
268
269
# Format the trace
270
format_apdu_trace(GET_DATA, response, sw1, sw2)
271
272
# Process response if successful
273
if sw1 == 0x90 and sw2 == 0x00 and response:
274
process_text_data(response)
275
276
session.close()
277
278
except Exception as e:
279
print(f"Error: {e}")
280
```
281
282
## Related Types
283
284
```python { .api }
285
# Type aliases for utility functions
286
HexString = str
287
ByteList = list[int]
288
ASCIIString = str
289
FormatFlags = int
290
291
# Format constant values
292
PACK: int = 1
293
HEX: int = 2
294
UPPERCASE: int = 4
295
COMMA: int = 8
296
```