mirror of
https://github.com/signalapp/libsignal.git
synced 2025-12-05 01:10:27 +00:00
Doc comments for AES-CTR, AES-GCM, and AES-GCM-SIV APIs
This commit is contained in:
@@ -11,6 +11,13 @@ import org.signal.libsignal.internal.Native;
|
||||
import org.signal.libsignal.internal.NativeHandleGuard;
|
||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||
|
||||
/**
|
||||
* Implements the <a
|
||||
* href="https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR)">AES-256-CTR</a>
|
||||
* stream cipher with a 12-byte nonce and an initial counter.
|
||||
*
|
||||
* <p>CTR mode is built on XOR, so encrypting and decrypting are the same operation.
|
||||
*/
|
||||
public class Aes256Ctr32 extends NativeHandleGuard.SimpleOwner {
|
||||
public Aes256Ctr32(byte[] key, byte[] nonce, int initialCtr) throws InvalidKeyException {
|
||||
super(
|
||||
@@ -23,10 +30,20 @@ public class Aes256Ctr32 extends NativeHandleGuard.SimpleOwner {
|
||||
Native.Aes256Ctr32_Destroy(nativeHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the plaintext, or decrypts the ciphertext, in {@code data}, in place, advancing the
|
||||
* state of the cipher.
|
||||
*/
|
||||
public void process(byte[] data) {
|
||||
this.process(data, 0, data.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the plaintext, or decrypts the ciphertext, in {@code data}, in place, advancing the
|
||||
* state of the cipher.
|
||||
*
|
||||
* <p>Bytes outside the designated offset/length are unchanged.
|
||||
*/
|
||||
public void process(byte[] data, int offset, int length) {
|
||||
guardedRun((nativeHandle) -> Native.Aes256Ctr32_Process(nativeHandle, data, offset, length));
|
||||
}
|
||||
|
||||
@@ -11,9 +11,27 @@ import org.signal.libsignal.internal.Native;
|
||||
import org.signal.libsignal.internal.NativeHandleGuard;
|
||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||
|
||||
/**
|
||||
* Implements the <a
|
||||
* href="https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Galois/counter_(GCM)">AES-256-GCM</a>
|
||||
* authenticated stream cipher with a 12-byte nonce.
|
||||
*
|
||||
* <p>This API exposes the streaming nature of AES-GCM to allow decrypting data without having it
|
||||
* resident in memory all at once. You <strong>must</strong> call {@link #verifyTag} when the
|
||||
* decryption is complete, or else you have no authenticity guarantees.
|
||||
*
|
||||
* @see Aes256GcmEncryption
|
||||
*/
|
||||
public class Aes256GcmDecryption extends NativeHandleGuard.SimpleOwner {
|
||||
/** The size of the authentication tag, as used by {@link #verifyTag} */
|
||||
public static final int TAG_SIZE_IN_BYTES = 16;
|
||||
|
||||
/**
|
||||
* Initializes the cipher with the given inputs.
|
||||
*
|
||||
* <p>The associated data is not included in the plaintext or tag; instead, it's expected to match
|
||||
* between the encrypter and decrypter.
|
||||
*/
|
||||
public Aes256GcmDecryption(byte[] key, byte[] nonce, byte[] associatedData)
|
||||
throws InvalidKeyException {
|
||||
super(
|
||||
@@ -27,18 +45,35 @@ public class Aes256GcmDecryption extends NativeHandleGuard.SimpleOwner {
|
||||
Native.Aes256GcmDecryption_Destroy(nativeHandle);
|
||||
}
|
||||
|
||||
public void decrypt(byte[] plaintext) {
|
||||
/**
|
||||
* Decrypts {@code ciphertext} in place and advances the state of the cipher.
|
||||
*
|
||||
* <p>Don't forget to call {@link #verifyTag} when decryption is complete.
|
||||
*/
|
||||
public void decrypt(byte[] ciphertext) {
|
||||
guardedRun(
|
||||
(nativeHandle) ->
|
||||
Native.Aes256GcmDecryption_Update(nativeHandle, plaintext, 0, plaintext.length));
|
||||
Native.Aes256GcmDecryption_Update(nativeHandle, ciphertext, 0, ciphertext.length));
|
||||
}
|
||||
|
||||
public void decrypt(byte[] plaintext, int offset, int length) {
|
||||
/**
|
||||
* Decrypts {@code ciphertext} in place and advances the state of the cipher.
|
||||
*
|
||||
* <p>Bytes outside the designated offset/length are unchanged.
|
||||
*
|
||||
* <p>Don't forget to call {@link #verifyTag} when decryption is complete.
|
||||
*/
|
||||
public void decrypt(byte[] ciphertext, int offset, int length) {
|
||||
guardedRun(
|
||||
(nativeHandle) ->
|
||||
Native.Aes256GcmDecryption_Update(nativeHandle, plaintext, offset, length));
|
||||
Native.Aes256GcmDecryption_Update(nativeHandle, ciphertext, offset, length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if and only if {@code tag} matches the ciphertext that has been processed.
|
||||
*
|
||||
* <p>After calling {@code verifyTag}, this object may not be used anymore.
|
||||
*/
|
||||
public boolean verifyTag(byte[] tag) {
|
||||
return guardedMap(
|
||||
(nativeHandle) ->
|
||||
|
||||
@@ -11,7 +11,25 @@ import org.signal.libsignal.internal.Native;
|
||||
import org.signal.libsignal.internal.NativeHandleGuard;
|
||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||
|
||||
/**
|
||||
* Implements the <a
|
||||
* href="https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Galois/counter_(GCM)">AES-256-GCM</a>
|
||||
* authenticated stream cipher with a 12-byte nonce.
|
||||
*
|
||||
* <p>This API exposes the streaming nature of AES-GCM to allow encrypting data without having it
|
||||
* resident in memory all at once. You must call {@link #computeTag} when the encryption is complete
|
||||
* to produce the authentication tag for the ciphertext, and then make sure the tag makes it to the
|
||||
* decrypter.
|
||||
*
|
||||
* @see Aes256GcmDecryption
|
||||
*/
|
||||
public class Aes256GcmEncryption extends NativeHandleGuard.SimpleOwner {
|
||||
/**
|
||||
* Initializes the cipher with the given inputs.
|
||||
*
|
||||
* <p>The associated data is not included in the plaintext or tag; instead, it's expected to match
|
||||
* between the encrypter and decrypter. If you don't need any extra data, pass an empty array.
|
||||
*/
|
||||
public Aes256GcmEncryption(byte[] key, byte[] nonce, byte[] associatedData)
|
||||
throws InvalidKeyException {
|
||||
super(
|
||||
@@ -25,18 +43,35 @@ public class Aes256GcmEncryption extends NativeHandleGuard.SimpleOwner {
|
||||
Native.Aes256GcmEncryption_Destroy(nativeHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts {@code plaintext} in place and advances the state of the cipher.
|
||||
*
|
||||
* <p>Bytes outside the designated offset/length are unchanged.
|
||||
*
|
||||
* <p>Don't forget to call {@link #computeTag} when encryption is complete.
|
||||
*/
|
||||
public void encrypt(byte[] plaintext, int offset, int length) {
|
||||
guardedRun(
|
||||
(nativeHandle) ->
|
||||
Native.Aes256GcmEncryption_Update(nativeHandle, plaintext, offset, length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts {@code plaintext} in place and advances the state of the cipher.
|
||||
*
|
||||
* <p>Don't forget to call {@link #computeTag} when encryption is complete.
|
||||
*/
|
||||
public void encrypt(byte[] plaintext) {
|
||||
guardedRun(
|
||||
(nativeHandle) ->
|
||||
Native.Aes256GcmEncryption_Update(nativeHandle, plaintext, 0, plaintext.length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces an authentication tag for the plaintext that has been processed.
|
||||
*
|
||||
* <p>After calling {@code computeTag}, this object may not be used anymore.
|
||||
*/
|
||||
public byte[] computeTag() {
|
||||
return guardedMap(Native::Aes256GcmEncryption_ComputeTag);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,13 @@ import org.signal.libsignal.internal.NativeHandleGuard;
|
||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||
import org.signal.libsignal.protocol.InvalidMessageException;
|
||||
|
||||
/**
|
||||
* Implements the <a href="https://en.wikipedia.org/wiki/AES-GCM-SIV">AES-256-GCM-SIV</a>
|
||||
* authenticated stream cipher with a 12-byte nonce.
|
||||
*
|
||||
* <p>AES-GCM-SIV is a multi-pass algorithm (to generate the "synthetic initialization vector"), so
|
||||
* this API does not expose a streaming form.
|
||||
*/
|
||||
public class Aes256GcmSiv extends NativeHandleGuard.SimpleOwner {
|
||||
|
||||
public Aes256GcmSiv(byte[] key) throws InvalidKeyException {
|
||||
@@ -23,6 +30,15 @@ public class Aes256GcmSiv extends NativeHandleGuard.SimpleOwner {
|
||||
Native.Aes256GcmSiv_Destroy(nativeHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the given plaintext using the given nonce, and authenticating the ciphertext and given
|
||||
* associated data.
|
||||
*
|
||||
* <p>The associated data is not included in the ciphertext; instead, it's expected to match
|
||||
* between the encrypter and decrypter. If you don't need any extra data, pass an empty array.
|
||||
*
|
||||
* @return The encrypted data, including an appended 16-byte authentication tag.
|
||||
*/
|
||||
public byte[] encrypt(byte[] plaintext, byte[] nonce, byte[] associated_data) {
|
||||
return filterExceptions(
|
||||
() ->
|
||||
@@ -31,6 +47,15 @@ public class Aes256GcmSiv extends NativeHandleGuard.SimpleOwner {
|
||||
Native.Aes256GcmSiv_Encrypt(nativeHandle, plaintext, nonce, associated_data)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the given ciphertext using the given nonce, and authenticating the ciphertext and
|
||||
* given associated data.
|
||||
*
|
||||
* <p>The associated data is not included in the ciphertext; instead, it's expected to match
|
||||
* between the encrypter and decrypter.
|
||||
*
|
||||
* @return The decrypted data
|
||||
*/
|
||||
public byte[] decrypt(byte[] ciphertext, byte[] nonce, byte[] associated_data)
|
||||
throws InvalidMessageException {
|
||||
return filterExceptions(
|
||||
|
||||
@@ -136,6 +136,13 @@ export class Fingerprint {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the <a href="https://en.wikipedia.org/wiki/AES-GCM-SIV">AES-256-GCM-SIV</a>
|
||||
* authenticated stream cipher with a 12-byte nonce.
|
||||
*
|
||||
* AES-GCM-SIV is a multi-pass algorithm (to generate the "synthetic initialization vector"), so
|
||||
* this API does not expose a streaming form.
|
||||
*/
|
||||
export class Aes256GcmSiv {
|
||||
readonly _nativeHandle: Native.Aes256GcmSiv;
|
||||
|
||||
@@ -147,20 +154,38 @@ export class Aes256GcmSiv {
|
||||
return new Aes256GcmSiv(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the given plaintext using the given nonce, and authenticating the ciphertext and given
|
||||
* associated data.
|
||||
*
|
||||
* The associated data is not included in the ciphertext; instead, it's expected to match between
|
||||
* the encrypter and decrypter. If you don't need any extra data, pass an empty array.
|
||||
*
|
||||
* @returns The encrypted data, including an appended 16-byte authentication tag.
|
||||
*/
|
||||
encrypt(
|
||||
message: Uint8Array,
|
||||
nonce: Uint8Array,
|
||||
associated_data: Uint8Array
|
||||
associatedData: Uint8Array
|
||||
): Uint8Array {
|
||||
return Native.Aes256GcmSiv_Encrypt(this, message, nonce, associated_data);
|
||||
return Native.Aes256GcmSiv_Encrypt(this, message, nonce, associatedData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the given ciphertext using the given nonce, and authenticating the ciphertext and given
|
||||
* associated data.
|
||||
*
|
||||
* The associated data is not included in the ciphertext; instead, it's expected to match between
|
||||
* the encrypter and decrypter.
|
||||
*
|
||||
* @returns The decrypted data
|
||||
*/
|
||||
decrypt(
|
||||
message: Uint8Array,
|
||||
nonce: Uint8Array,
|
||||
associated_data: Uint8Array
|
||||
associatedData: Uint8Array
|
||||
): Uint8Array {
|
||||
return Native.Aes256GcmSiv_Decrypt(this, message, nonce, associated_data);
|
||||
return Native.Aes256GcmSiv_Decrypt(this, message, nonce, associatedData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,10 +6,19 @@
|
||||
import Foundation
|
||||
import SignalFfi
|
||||
|
||||
/// Implements the
|
||||
/// [AES-256-CTR](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR))
|
||||
/// stream cipher with a combined 12-byte nonce and initial 4-byte counter.
|
||||
///
|
||||
/// CTR mode is built on XOR, so encrypting and decrypting are the same operation.
|
||||
public class Aes256Ctr32: NativeHandleOwner<SignalMutPointerAes256Ctr32> {
|
||||
public static let keyLength: Int = 32
|
||||
public static let nonceLength: Int = 16
|
||||
|
||||
/// Initializes the cipher with the given key and combined nonce.
|
||||
///
|
||||
/// The first 12 bytes of the nonce are treated as a traditional nonce, while the last four are
|
||||
/// treated as the initial counter---the position in the cipher stream to start at.
|
||||
public convenience init<KeyBytes, NonceBytes>(
|
||||
key: KeyBytes,
|
||||
nonce: NonceBytes
|
||||
@@ -49,6 +58,8 @@ public class Aes256Ctr32: NativeHandleOwner<SignalMutPointerAes256Ctr32> {
|
||||
return signal_aes256_ctr32_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
/// Encrypts the plaintext, or decrypts the ciphertext, in `message`, in place, advancing the
|
||||
/// state of the cipher.
|
||||
public func process(_ message: inout Data) throws {
|
||||
try withNativeHandle { nativeHandle in
|
||||
try message.withUnsafeMutableBytes { messageBytes in
|
||||
@@ -64,6 +75,10 @@ public class Aes256Ctr32: NativeHandleOwner<SignalMutPointerAes256Ctr32> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Encrypts the plaintext, or decrypts the ciphertext, in `message`, in place, using the given
|
||||
/// key and nonce.
|
||||
///
|
||||
/// This is a convenience for when the entire message fits in memory.
|
||||
public static func process<KeyBytes, NonceBytes>(
|
||||
_ message: inout Data,
|
||||
key: KeyBytes,
|
||||
|
||||
@@ -6,6 +6,13 @@
|
||||
import Foundation
|
||||
import SignalFfi
|
||||
|
||||
/// Provides convenient use of the
|
||||
/// [AES-256-GCM](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Galois/counter_(GCM))
|
||||
/// authenticated stream cipher with a 12-byte nonce.
|
||||
///
|
||||
/// This struct packs up all the data needed to transmit an AES-GCM ciphertext, and makes it easy to
|
||||
/// operate on a full ciphertext at once. If you need streaming encryption or decryption, you can
|
||||
/// use the more manual APIs ``Aes256GcmEncryption`` and ``Aes256GcmDecryption``.
|
||||
public struct Aes256GcmEncryptedData: Sendable {
|
||||
public static let keyLength: Int = 32
|
||||
public static let nonceLength: Int = 12
|
||||
@@ -22,6 +29,11 @@ public struct Aes256GcmEncryptedData: Sendable {
|
||||
self.authenticationTag = authenticationTag
|
||||
}
|
||||
|
||||
/// Assumes `concatenated` is the concatenation `nonce || ciphertext || authenticationTag`, and
|
||||
/// splits it up accordingly.
|
||||
///
|
||||
/// Throws if the data is too short to contain all three parts (though technically the
|
||||
/// ciphertext may be empty).
|
||||
@inlinable
|
||||
public init(concatenated: Data) throws {
|
||||
guard concatenated.count >= Self.nonceLength + Self.authenticationTagLength else {
|
||||
@@ -32,6 +44,10 @@ public struct Aes256GcmEncryptedData: Sendable {
|
||||
self.authenticationTag = concatenated.suffix(Self.authenticationTagLength)
|
||||
}
|
||||
|
||||
/// Concatenates the nonce, ciphertext, and authentication tag, in that order.
|
||||
///
|
||||
/// This is a fairly standard way to send AES-GCM ciphertexts. The result is suitable for
|
||||
/// passing to ``init(concatenated:)``.
|
||||
public func concatenate() -> Data {
|
||||
var result = Data(capacity: nonce.count + self.ciphertext.count + self.authenticationTag.count)
|
||||
result += self.nonce
|
||||
@@ -40,6 +56,14 @@ public struct Aes256GcmEncryptedData: Sendable {
|
||||
return result
|
||||
}
|
||||
|
||||
/// Encrypts the given plaintext using the given key, and authenticating the ciphertext and
|
||||
/// given associated data.
|
||||
///
|
||||
/// The associated data is not included in the ciphertext; instead, it's expected to match
|
||||
/// between the encrypter and decrypter. If you don't need any extra data, use the other
|
||||
/// overload ``encrypt(_:key:)``.
|
||||
///
|
||||
/// This API will generate a random nonce, which is included in the result.
|
||||
public static func encrypt(
|
||||
_ message: Data,
|
||||
key: some ContiguousBytes,
|
||||
@@ -56,12 +80,22 @@ public struct Aes256GcmEncryptedData: Sendable {
|
||||
return Self(nonce: nonce, ciphertext: ciphertext, authenticationTag: tag)
|
||||
}
|
||||
|
||||
/// Encrypts the given plaintext using the given key, authenticating the ciphertext.
|
||||
///
|
||||
/// This API will generate a random nonce, which is included in the result.
|
||||
///
|
||||
/// - SeeAlso: ``encrypt(_:key:associatedData:)``
|
||||
public static func encrypt(_ message: Data, key: some ContiguousBytes) throws -> Self {
|
||||
return try self.encrypt(message, key: key, associatedData: [])
|
||||
}
|
||||
|
||||
// Inlinable here specifically to avoid copying the ciphertext again if the struct is no longer used.
|
||||
@inlinable
|
||||
/// Decrypts `self` using the given key, and authenticates the ciphertext and given associated
|
||||
/// data.
|
||||
///
|
||||
/// The associated data is not included in the ciphertext; instead, it's expected to match
|
||||
/// between the encrypter and decrypter. If you don't have any extra data, use the other
|
||||
/// overload ``decrypt(key:)``.
|
||||
@inlinable // Inlinable here specifically to avoid copying the ciphertext again if the struct is no longer used.
|
||||
public func decrypt(
|
||||
key: some ContiguousBytes,
|
||||
associatedData: some ContiguousBytes
|
||||
@@ -75,14 +109,30 @@ public struct Aes256GcmEncryptedData: Sendable {
|
||||
return plaintext
|
||||
}
|
||||
|
||||
/// Decrypts `self` using the given key, authenticating the ciphertext.
|
||||
///
|
||||
/// - SeeAlso: ``decrypt(key:associatedData:)``
|
||||
@inlinable
|
||||
public func decrypt(key: some ContiguousBytes) throws -> Data {
|
||||
return try self.decrypt(key: key, associatedData: [])
|
||||
}
|
||||
}
|
||||
|
||||
/// Supports streamed encryption and custom nonces. Use Aes256GcmEncryptedData if you don't need either.
|
||||
/// Implements the
|
||||
/// [AES-256-GCM](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Galois/counter_(GCM))
|
||||
/// authenticated stream cipher with a 12-byte nonce.
|
||||
///
|
||||
/// This API exposes the streaming nature of AES-GCM to allow decrypting data without having it
|
||||
/// resident in memory all at once. You must call ``computeTag()`` when the encryption is complete,
|
||||
/// or else you have no authenticity guarantees. Use ``Aes256GcmEncryptedData`` instead if you don't
|
||||
/// need to stream the data or choose your own nonce.
|
||||
///
|
||||
/// - SeeAlso: ``Aes256GcmDecryption``
|
||||
public class Aes256GcmEncryption: NativeHandleOwner<SignalMutPointerAes256GcmEncryption> {
|
||||
/// Initializes the cipher with the given inputs.
|
||||
///
|
||||
/// The associated data is not included in the plaintext or tag; instead, it's expected to match
|
||||
/// between the encrypter and decrypter. If you don't need any extra data, pass an empty array.
|
||||
public convenience init(
|
||||
key: some ContiguousBytes,
|
||||
nonce: some ContiguousBytes,
|
||||
@@ -111,6 +161,9 @@ public class Aes256GcmEncryption: NativeHandleOwner<SignalMutPointerAes256GcmEnc
|
||||
return signal_aes256_gcm_encryption_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
/// Encrypts `message` in place and advances the state of the cipher.
|
||||
///
|
||||
/// Don't forget to call ``computeTag()`` when encryption is complete.
|
||||
public func encrypt(_ message: inout Data) throws {
|
||||
try withNativeHandle { nativeHandle in
|
||||
try message.withUnsafeMutableBytes { messageBytes in
|
||||
@@ -126,6 +179,9 @@ public class Aes256GcmEncryption: NativeHandleOwner<SignalMutPointerAes256GcmEnc
|
||||
}
|
||||
}
|
||||
|
||||
/// Produces an authentication tag for the plaintext that has been processed.
|
||||
///
|
||||
/// After calling `computeTag()`, this object may not be used anymore.
|
||||
public func computeTag() throws -> Data {
|
||||
return try withNativeHandle { nativeHandle in
|
||||
try invokeFnReturningData {
|
||||
@@ -151,8 +207,21 @@ extension SignalMutPointerAes256GcmEncryption: SignalMutPointer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Supports streamed decryption. Use Aes256GcmEncryptedData if you don't need streamed decryption.
|
||||
/// Implements the
|
||||
/// [AES-256-GCM](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Galois/counter_(GCM))
|
||||
/// authenticated stream cipher with a 12-byte nonce.
|
||||
///
|
||||
/// This API exposes the streaming nature of AES-GCM to allow decrypting data without having it
|
||||
/// resident in memory all at once. You **must** call ``verifyTag(_:)`` when the decryption is
|
||||
/// complete, or else you have no authenticity guarantees. Use ``Aes256GcmEncryptedData`` instead if
|
||||
/// you don't need streamed decryption.
|
||||
///
|
||||
/// - SeeAlso: ``Aes256GcmEncryption``
|
||||
public class Aes256GcmDecryption: NativeHandleOwner<SignalMutPointerAes256GcmDecryption> {
|
||||
/// Initializes the cipher with the given inputs.
|
||||
///
|
||||
/// The associated data is not included in the plaintext or tag; instead, it's expected to match
|
||||
/// between the encrypter and decrypter.
|
||||
public convenience init(
|
||||
key: some ContiguousBytes,
|
||||
nonce: some ContiguousBytes,
|
||||
@@ -181,6 +250,9 @@ public class Aes256GcmDecryption: NativeHandleOwner<SignalMutPointerAes256GcmDec
|
||||
return signal_aes256_gcm_decryption_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
/// Decrypts `message` in place and advances the state of the cipher.
|
||||
///
|
||||
/// Don't forget to call ``verifyTag(_:)`` when decryption is complete.
|
||||
public func decrypt(_ message: inout Data) throws {
|
||||
try withNativeHandle { nativeHandle in
|
||||
try message.withUnsafeMutableBytes { messageBytes in
|
||||
@@ -196,6 +268,12 @@ public class Aes256GcmDecryption: NativeHandleOwner<SignalMutPointerAes256GcmDec
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if and only if `tag` matches the ciphertext that has been processed.
|
||||
///
|
||||
/// Throws if the tag is not structurally valid (which it's acceptable to treat as "did not
|
||||
/// return `true`").
|
||||
///
|
||||
/// After calling `verifyTag(_:)`, this object may not be used anymore.
|
||||
public func verifyTag(_ tag: some ContiguousBytes) throws -> Bool {
|
||||
return try withNativeHandle { nativeHandle in
|
||||
try tag.withUnsafeBorrowedBuffer { tagBuffer in
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
import Foundation
|
||||
import SignalFfi
|
||||
|
||||
/// Implements the [AES-256-GCM-SIV](https://en.wikipedia.org/wiki/AES-GCM-SIV)
|
||||
/// authenticated stream cipher with a 12-byte nonce.
|
||||
///
|
||||
/// AES-GCM-SIV is a multi-pass algorithm (to generate the "synthetic initialization vector"), so
|
||||
/// this API does not expose a streaming form.
|
||||
public class Aes256GcmSiv: NativeHandleOwner<SignalMutPointerAes256GcmSiv> {
|
||||
public convenience init<Bytes: ContiguousBytes>(key bytes: Bytes) throws {
|
||||
let handle = try bytes.withUnsafeBorrowedBuffer { bytes in
|
||||
@@ -22,6 +27,13 @@ public class Aes256GcmSiv: NativeHandleOwner<SignalMutPointerAes256GcmSiv> {
|
||||
return signal_aes256_gcm_siv_destroy(handle.pointer)
|
||||
}
|
||||
|
||||
/// Encrypts the given plaintext using the given nonce, and authenticating the ciphertext and given
|
||||
/// associated data.
|
||||
///
|
||||
/// The associated data is not included in the ciphertext; instead, it's expected to match between
|
||||
/// the encrypter and decrypter. If you don't need any extra data, pass an empty array.
|
||||
///
|
||||
/// - Returns: The encrypted data, including an appended 16-byte authentication tag.
|
||||
public func encrypt(
|
||||
_ message: some ContiguousBytes,
|
||||
nonce: some ContiguousBytes,
|
||||
@@ -46,6 +58,13 @@ public class Aes256GcmSiv: NativeHandleOwner<SignalMutPointerAes256GcmSiv> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Decrypts the given ciphertext using the given nonce, and authenticating the ciphertext and
|
||||
/// given associated data.
|
||||
///
|
||||
/// The associated data is not included in the ciphertext; instead, it's expected to match
|
||||
/// between the encrypter and decrypter.
|
||||
///
|
||||
/// - Returns: The decrypted data
|
||||
public func decrypt(
|
||||
_ message: some ContiguousBytes,
|
||||
nonce: some ContiguousBytes,
|
||||
|
||||
Reference in New Issue
Block a user