swift-sodium/Sodium/KeyDerivation.swift

54 lines
2.2 KiB
Swift

import Foundation
import Clibsodium
public class KeyDerivation {
public let BytesMin = Int(crypto_kdf_bytes_min())
public let BytesMax = Int(crypto_kdf_bytes_max())
public let ContextBytes = Int(crypto_kdf_contextbytes())
public typealias SubKey = Bytes
/**
Derives a subkey from the specified input key. Each index (from 0 to (2^64) - 1) yields a unique deterministic subkey.
The sequence of subkeys is likely unique for a given context.
- Parameter secretKey: the master key from which to derive the subkey (must be KeyBytes bytes)
- Parameter index: the index of the subkey to generate (allowed range: 0 to (2^64) - 1)
- Parameter length: the desired length of the subkey in bytes (allowed range: BytesMin to BytesMax)
- Parameter context: a String that identifies the context; use a different value for different types of keys (should be exactly 8 characters long but must be no longer than 8 characters)
- Returns: the derived key or nil on error.
- Note: Output keys must have a length between BytesMin and BytesMax bytes (inclusive), otherwise an error is returned. Context must be at most 8 characters long. If the specified context is shorter than 8 characters, it will be padded to 8 characters. The master key is KeyBytes long.
*/
public func derive(secretKey: Bytes, index: UInt64, length: Int, context: String) -> Bytes? {
var contextBin = Bytes(context.utf8).map(Int8.init)
guard (BytesMin...BytesMax).contains(length),
secretKey.count == KeyBytes,
contextBin.count <= ContextBytes
else { return nil }
while contextBin.count < ContextBytes {
contextBin += [0]
}
var output = Bytes(count: length)
guard .SUCCESS == crypto_kdf_derive_from_key(
&output, length,
index,
contextBin,
secretKey
).exitCode else { return nil }
return output
}
}
extension KeyDerivation: SecretKeyGenerator {
public var KeyBytes: Int { return Int(crypto_kdf_keybytes()) }
public typealias Key = Bytes
static var keygen: (UnsafeMutablePointer<UInt8>) -> Void = crypto_kdf_keygen
}