0
# Hash and Cryptographic Operations
1
2
Okio provides built-in hashing and cryptographic operations for data integrity and security. These operations can be performed on ByteString, Buffer, and streaming data through Sources and Sinks.
3
4
## Capabilities
5
6
### ByteString Hashing
7
8
Compute hashes directly on ByteString instances.
9
10
```kotlin { .api }
11
/**
12
* Computes MD5 hash of ByteString content (deprecated)
13
* @return ByteString containing MD5 hash (16 bytes)
14
*/
15
abstract fun ByteString.md5(): ByteString
16
17
/**
18
* Computes SHA-1 hash of ByteString content (deprecated)
19
* @return ByteString containing SHA-1 hash (20 bytes)
20
*/
21
abstract fun ByteString.sha1(): ByteString
22
23
/**
24
* Computes SHA-256 hash of ByteString content
25
* @return ByteString containing SHA-256 hash (32 bytes)
26
*/
27
abstract fun ByteString.sha256(): ByteString
28
29
/**
30
* Computes SHA-512 hash of ByteString content
31
* @return ByteString containing SHA-512 hash (64 bytes)
32
*/
33
abstract fun ByteString.sha512(): ByteString
34
35
/**
36
* Computes HMAC-SHA1 with the given key (deprecated)
37
* @param key Secret key for HMAC computation
38
* @return ByteString containing HMAC-SHA1 (20 bytes)
39
*/
40
@Deprecated("Use hmacSha256 instead", ReplaceWith("hmacSha256(key)"))
41
abstract fun ByteString.hmacSha1(key: ByteString): ByteString
42
43
/**
44
* Computes HMAC-SHA256 with the given key
45
* @param key Secret key for HMAC computation
46
* @return ByteString containing HMAC-SHA256 (32 bytes)
47
*/
48
abstract fun ByteString.hmacSha256(key: ByteString): ByteString
49
50
/**
51
* Computes HMAC-SHA512 with the given key
52
* @param key Secret key for HMAC computation
53
* @return ByteString containing HMAC-SHA512 (64 bytes)
54
*/
55
abstract fun ByteString.hmacSha512(key: ByteString): ByteString
56
```
57
58
**Usage Examples:**
59
60
```kotlin
61
val data = "Hello, World!".encodeUtf8()
62
val key = "secret-key".encodeUtf8()
63
64
// Basic hashing
65
val md5 = data.md5()
66
println("MD5: ${md5.hex()}")
67
68
val sha256 = data.sha256()
69
println("SHA-256: ${sha256.hex()}")
70
71
val sha512 = data.sha512()
72
println("SHA-512: ${sha512.hex()}")
73
74
// HMAC with key
75
val hmac256 = data.hmacSha256(key)
76
println("HMAC-SHA256: ${hmac256.hex()}")
77
78
val hmac512 = data.hmacSha512(key)
79
println("HMAC-SHA512: ${hmac512.hex()}")
80
```
81
82
### Buffer Hashing
83
84
Compute hashes on Buffer content without consuming the data.
85
86
```kotlin { .api }
87
/**
88
* Computes MD5 hash of Buffer content (deprecated)
89
* @return ByteString containing MD5 hash
90
*/
91
fun Buffer.md5(): ByteString
92
93
/**
94
* Computes SHA-1 hash of Buffer content (deprecated)
95
* @return ByteString containing SHA-1 hash
96
*/
97
fun Buffer.sha1(): ByteString
98
99
/**
100
* Computes SHA-256 hash of Buffer content
101
* @return ByteString containing SHA-256 hash
102
*/
103
fun Buffer.sha256(): ByteString
104
105
/**
106
* Computes SHA-512 hash of Buffer content
107
* @return ByteString containing SHA-512 hash
108
*/
109
fun Buffer.sha512(): ByteString
110
111
/**
112
* Computes HMAC-SHA1 of Buffer content (deprecated)
113
* @param key Secret key for HMAC computation
114
* @return ByteString containing HMAC-SHA1
115
*/
116
@Deprecated("Use hmacSha256 instead")
117
fun Buffer.hmacSha1(key: ByteString): ByteString
118
119
/**
120
* Computes HMAC-SHA256 of Buffer content
121
* @param key Secret key for HMAC computation
122
* @return ByteString containing HMAC-SHA256
123
*/
124
fun Buffer.hmacSha256(key: ByteString): ByteString
125
126
/**
127
* Computes HMAC-SHA512 of Buffer content
128
* @param key Secret key for HMAC computation
129
* @return ByteString containing HMAC-SHA512
130
*/
131
fun Buffer.hmacSha512(key: ByteString): ByteString
132
```
133
134
**Usage Examples:**
135
136
```kotlin
137
val buffer = Buffer()
138
buffer.writeUtf8("Hello, World!")
139
buffer.writeInt(42)
140
141
// Hash without consuming buffer data
142
val hash = buffer.sha256()
143
println("Buffer SHA-256: ${hash.hex()}")
144
println("Buffer still has ${buffer.size} bytes")
145
146
// HMAC of buffer content
147
val key = "secret".encodeUtf8()
148
val hmac = buffer.hmacSha256(key)
149
println("Buffer HMAC: ${hmac.hex()}")
150
```
151
152
### Streaming Hash Computation
153
154
Compute hashes while reading from Sources or writing to Sinks.
155
156
```kotlin { .api }
157
/**
158
* Sink that computes a hash while writing data
159
* Wraps another sink and computes hash of all data written
160
*/
161
abstract class HashingSink : Sink {
162
/**
163
* Current hash value of all data written so far
164
*/
165
abstract val hash: ByteString
166
167
companion object {
168
/**
169
* Creates a HashingSink that computes MD5 (deprecated)
170
* @param sink Underlying sink to write to
171
* @return HashingSink that computes MD5
172
*/
173
fun md5(sink: Sink): HashingSink
174
175
/**
176
* Creates a HashingSink that computes SHA-1 (deprecated)
177
* @param sink Underlying sink to write to
178
* @return HashingSink that computes SHA-1
179
*/
180
fun sha1(sink: Sink): HashingSink
181
182
/**
183
* Creates a HashingSink that computes SHA-256
184
* @param sink Underlying sink to write to
185
* @return HashingSink that computes SHA-256
186
*/
187
fun sha256(sink: Sink): HashingSink
188
189
/**
190
* Creates a HashingSink that computes SHA-512
191
* @param sink Underlying sink to write to
192
* @return HashingSink that computes SHA-512
193
*/
194
fun sha512(sink: Sink): HashingSink
195
196
/**
197
* Creates a HashingSink that computes HMAC-SHA1 (deprecated)
198
* @param sink Underlying sink to write to
199
* @param key Secret key for HMAC computation
200
* @return HashingSink that computes HMAC-SHA1
201
*/
202
@Deprecated("Use hmacSha256 instead")
203
fun hmacSha1(sink: Sink, key: ByteString): HashingSink
204
205
/**
206
* Creates a HashingSink that computes HMAC-SHA256
207
* @param sink Underlying sink to write to
208
* @param key Secret key for HMAC computation
209
* @return HashingSink that computes HMAC-SHA256
210
*/
211
fun hmacSha256(sink: Sink, key: ByteString): HashingSink
212
213
/**
214
* Creates a HashingSink that computes HMAC-SHA512
215
* @param sink Underlying sink to write to
216
* @param key Secret key for HMAC computation
217
* @return HashingSink that computes HMAC-SHA512
218
*/
219
fun hmacSha512(sink: Sink, key: ByteString): HashingSink
220
}
221
}
222
223
/**
224
* Source that computes a hash while reading data
225
* Wraps another source and computes hash of all data read
226
*/
227
abstract class HashingSource : Source {
228
/**
229
* Current hash value of all data read so far
230
*/
231
abstract val hash: ByteString
232
233
companion object {
234
/**
235
* Creates a HashingSource that computes MD5 (deprecated)
236
* @param source Underlying source to read from
237
* @return HashingSource that computes MD5
238
*/
239
fun md5(source: Source): HashingSource
240
241
/**
242
* Creates a HashingSource that computes SHA-1 (deprecated)
243
* @param source Underlying source to read from
244
* @return HashingSource that computes SHA-1
245
*/
246
fun sha1(source: Source): HashingSource
247
248
/**
249
* Creates a HashingSource that computes SHA-256
250
* @param source Underlying source to read from
251
* @return HashingSource that computes SHA-256
252
*/
253
fun sha256(source: Source): HashingSource
254
255
/**
256
* Creates a HashingSource that computes SHA-512
257
* @param source Underlying source to read from
258
* @return HashingSource that computes SHA-512
259
*/
260
fun sha512(source: Source): HashingSource
261
262
/**
263
* Creates a HashingSource that computes HMAC-SHA1 (deprecated)
264
* @param source Underlying source to read from
265
* @param key Secret key for HMAC computation
266
* @return HashingSource that computes HMAC-SHA1
267
*/
268
@Deprecated("Use hmacSha256 instead")
269
fun hmacSha1(source: Source, key: ByteString): HashingSource
270
271
/**
272
* Creates a HashingSource that computes HMAC-SHA256
273
* @param source Underlying source to read from
274
* @param key Secret key for HMAC computation
275
* @return HashingSource that computes HMAC-SHA256
276
*/
277
fun hmacSha256(source: Source, key: ByteString): HashingSource
278
279
/**
280
* Creates a HashingSource that computes HMAC-SHA512
281
* @param source Underlying source to read from
282
* @param key Secret key for HMAC computation
283
* @return HashingSource that computes HMAC-SHA512
284
*/
285
fun hmacSha512(source: Source, key: ByteString): HashingSource
286
}
287
}
288
```
289
290
**Usage Examples:**
291
292
```kotlin
293
// Hash while writing to file
294
val path = "/tmp/data.txt".toPath()
295
val fileSink = FileSystem.SYSTEM.sink(path)
296
val hashingSink = HashingSink.sha256(fileSink)
297
val bufferedSink = hashingSink.buffer()
298
299
bufferedSink.writeUtf8("Hello, World!")
300
bufferedSink.writeInt(42)
301
bufferedSink.close()
302
303
println("File SHA-256: ${hashingSink.hash.hex()}")
304
305
// Hash while reading from file
306
val fileSource = FileSystem.SYSTEM.source(path)
307
val hashingSource = HashingSource.sha256(fileSource)
308
val bufferedSource = hashingSource.buffer()
309
310
val content = bufferedSource.readUtf8()
311
val number = bufferedSource.readInt()
312
bufferedSource.close()
313
314
println("Content: $content, Number: $number")
315
println("Read SHA-256: ${hashingSource.hash.hex()}")
316
317
// HMAC while streaming
318
val key = "secret-key".encodeUtf8()
319
val hmacSink = HashingSink.hmacSha256(blackholeSink(), key)
320
val buffer = Buffer()
321
322
hmacSink.write(buffer.writeUtf8("Streaming data"), 13)
323
hmacSink.flush()
324
println("Streaming HMAC: ${hmacSink.hash.hex()}")
325
```
326
327
### Hash Verification
328
329
Common patterns for verifying data integrity.
330
331
```kotlin { .api }
332
/**
333
* Verifies data integrity by comparing computed hash with expected hash
334
* @param expectedHash Expected hash value
335
* @param actualHash Computed hash value
336
* @return true if hashes match
337
*/
338
fun verifyHash(expectedHash: ByteString, actualHash: ByteString): Boolean =
339
expectedHash == actualHash
340
341
/**
342
* Verifies data integrity by comparing hex-encoded hashes
343
* @param expectedHex Expected hash as hex string
344
* @param actualHash Computed hash value
345
* @return true if hashes match
346
*/
347
fun verifyHashHex(expectedHex: String, actualHash: ByteString): Boolean =
348
expectedHex.lowercase() == actualHash.hex()
349
```
350
351
**Usage Examples:**
352
353
```kotlin
354
// Download and verify file integrity
355
val expectedSha256 = "a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3"
356
val downloadedData = "hello".encodeUtf8()
357
358
val actualHash = downloadedData.sha256()
359
val isValid = verifyHashHex(expectedSha256, actualHash)
360
println("File integrity: ${if (isValid) "VALID" else "INVALID"}")
361
362
// Verify HMAC for authentication
363
val message = "authenticated message".encodeUtf8()
364
val sharedKey = "shared-secret".encodeUtf8()
365
val computedHmac = message.hmacSha256(sharedKey)
366
367
// Later, verify the message
368
val receivedMessage = "authenticated message".encodeUtf8()
369
val receivedHmac = computedHmac // would come from sender
370
val verificationHmac = receivedMessage.hmacSha256(sharedKey)
371
val isAuthentic = verifyHash(receivedHmac, verificationHmac)
372
println("Message authentic: ${if (isAuthentic) "YES" else "NO"}")
373
374
// Stream large file and verify hash
375
val largeFile = "/tmp/large-file.dat".toPath()
376
val expectedHash = "expected-hash-value".decodeHex()
377
378
val source = FileSystem.SYSTEM.source(largeFile)
379
val hashingSource = HashingSource.sha256(source)
380
val buffer = Buffer()
381
382
// Read entire file through hashing source
383
while (!hashingSource.exhausted()) {
384
hashingSource.read(buffer, 8192)
385
buffer.clear() // Process data in chunks
386
}
387
hashingSource.close()
388
389
val fileValid = verifyHash(expectedHash, hashingSource.hash)
390
println("Large file integrity: ${if (fileValid) "VALID" else "INVALID"}")
391
```