swift-sodium/Sodium/SecretBox.swift

152 lines
5.1 KiB
Swift

import Foundation
import Clibsodium
public class SecretBox {
public let MacBytes = Int(crypto_secretbox_macbytes())
public typealias MAC = Bytes
/**
Encrypts a message with a shared secret key.
- Parameter message: The message to encrypt.
- Parameter secretKey: The shared secret key.
- Returns: A `Bytes` object containing the nonce and authenticated ciphertext.
*/
public func seal(message: Bytes, secretKey: Key) -> Bytes? {
guard let (authenticatedCipherText, nonce): (Bytes, Nonce) = seal(
message: message,
secretKey: secretKey
) else { return nil }
return nonce + authenticatedCipherText
}
/**
Encrypts a message with a shared secret key.
- Parameter message: The message to encrypt.
- Parameter secretKey: The shared secret key.
- Returns: The authenticated ciphertext and encryption nonce.
*/
public func seal(message: Bytes, secretKey: Key) -> (authenticatedCipherText: Bytes, nonce: Nonce)? {
guard secretKey.count == KeyBytes else { return nil }
var authenticatedCipherText = Bytes(count: message.count + MacBytes)
let nonce = self.nonce()
guard .SUCCESS == crypto_secretbox_easy (
&authenticatedCipherText,
message, UInt64(message.count),
nonce,
secretKey
).exitCode else { return nil }
return (authenticatedCipherText: authenticatedCipherText, nonce: nonce)
}
/**
Encrypts a message with a shared secret key (detached mode).
- Parameter message: The message to encrypt.
- Parameter secretKey: The shared secret key.
- Returns: The encrypted ciphertext, encryption nonce, and authentication tag.
*/
public func seal(message: Bytes, secretKey: Key) -> (cipherText: Bytes, nonce: Nonce, mac: MAC)? {
guard secretKey.count == KeyBytes else { return nil }
var cipherText = Bytes(count: message.count)
var mac = Bytes(count: MacBytes)
let nonce = self.nonce()
guard .SUCCESS == crypto_secretbox_detached (
&cipherText,
&mac,
message, UInt64(message.count),
nonce,
secretKey
).exitCode else { return nil }
return (cipherText: cipherText, nonce: nonce, mac: mac)
}
/**
Decrypts a message with a shared secret key.
- Parameter nonceAndAuthenticatedCipherText: A `Bytes` object containing the nonce and authenticated ciphertext.
- Parameter secretKey: The shared secret key.
- Returns: The decrypted message.
*/
public func open(nonceAndAuthenticatedCipherText: Bytes, secretKey: Key) -> Bytes? {
guard nonceAndAuthenticatedCipherText.count >= MacBytes + NonceBytes else { return nil }
let nonce = nonceAndAuthenticatedCipherText[..<NonceBytes].bytes as Nonce
let authenticatedCipherText = nonceAndAuthenticatedCipherText[NonceBytes...].bytes
return open(authenticatedCipherText: authenticatedCipherText, secretKey: secretKey, nonce: nonce)
}
/**
Decrypts a message with a shared secret key and encryption nonce.
- Parameter authenticatedCipherText: The authenticated ciphertext.
- Parameter secretKey: The shared secret key.
- Parameter nonce: The encryption nonce.
- Returns: The decrypted message.
*/
public func open(authenticatedCipherText: Bytes, secretKey: Key, nonce: Nonce) -> Bytes? {
guard authenticatedCipherText.count >= MacBytes else { return nil }
var message = Bytes(count: authenticatedCipherText.count - MacBytes)
guard .SUCCESS == crypto_secretbox_open_easy (
&message,
authenticatedCipherText, UInt64(authenticatedCipherText.count),
nonce,
secretKey
).exitCode else { return nil }
return message
}
/**
Decrypts a message with a shared secret key, encryption nonce, and authentication tag.
- Parameter cipherText: The encrypted ciphertext.
- Parameter secretKey: The shared secret key.
- Parameter nonce: The encryption nonce.
- Returns: The decrypted message.
*/
public func open(cipherText: Bytes, secretKey: Key, nonce: Nonce, mac: MAC) -> Bytes? {
guard nonce.count == NonceBytes,
mac.count == MacBytes,
secretKey.count == KeyBytes
else { return nil }
var message = Bytes(count: cipherText.count)
guard .SUCCESS == crypto_secretbox_open_detached (
&message,
cipherText,
mac,
UInt64(cipherText.count),
nonce,
secretKey
).exitCode else { return nil }
return message
}
}
extension SecretBox: NonceGenerator {
public var NonceBytes: Int { return Int(crypto_secretbox_noncebytes()) }
public typealias Nonce = Bytes
}
extension SecretBox: SecretKeyGenerator {
public typealias Key = Bytes
public var KeyBytes: Int { return Int(crypto_secretbox_keybytes()) }
static let keygen: (_ k: UnsafeMutablePointer<UInt8>) -> Void = crypto_secretbox_keygen
}