File: SymmetricKeys.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (131 lines) | stat: -rw-r--r-- 4,580 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftCrypto open source project
//
// Copyright (c) 2019-2020 Apple Inc. and the SwiftCrypto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.md for the list of SwiftCrypto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
#if CRYPTO_IN_SWIFTPM && !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
@_exported import CryptoKit
#else
import Foundation

/// The sizes that a symmetric cryptographic key can take.
///
/// When creating a new ``SymmetricKey`` instance with a call to its
/// ``SymmetricKey/init(size:)`` initializer, you typically use one of the
/// standard key sizes, like ``bits128``, ``bits192``, or ``bits256``. When you
/// need a key with a non-standard length, use the ``init(bitCount:)``
/// initializer to create a `SymmetricKeySize` instance with a custom bit count.
public struct SymmetricKeySize {
    /// The number of bits in the key.
    public let bitCount: Int

    /// A size of 128 bits.
    public static var bits128: SymmetricKeySize {
        return self.init(bitCount: 128)
    }

    /// A size of 192 bits.
    public static var bits192: SymmetricKeySize {
        return self.init(bitCount: 192)
    }

    /// A size of 256 bits.
    public static var bits256: SymmetricKeySize {
        return self.init(bitCount: 256)
    }
    
    /// Creates a new key size of the given length.
    ///
    /// In most cases, you can use one of the standard key sizes, like bits256.
    /// If instead you need a key with a non-standard size, use the
    /// ``init(bitCount:)`` initializer to create a custom key size.
    ///
    /// - Parameters:
    ///   - bitCount: The number of bits in the key size.
    public init(bitCount: Int) {
        precondition(bitCount > 0 && bitCount % 8 == 0)
        self.bitCount = bitCount
    }
}

/// A symmetric cryptographic key.
///
/// You typically derive a symmetric key from an instance of a shared secret
/// (``SharedSecret``) that you obtain through key agreement. You use a
/// symmetric key to compute a message authentication code like ``HMAC``, or to
/// open and close a sealed box (``ChaChaPoly/SealedBox`` or
/// ``AES/GCM/SealedBox``) using a cipher like ``ChaChaPoly`` or ``AES``.
public struct SymmetricKey: ContiguousBytes {
    let sb: SecureBytes

    /// Invokes the given closure with a buffer pointer covering the raw bytes
    /// of the key.
    ///
    /// - Parameters:
    ///   - body: A closure that takes a raw buffer pointer to the bytes of the
    /// key and returns the key.
    ///
    /// - Returns: The key, as returned from the body closure.
    public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
        return try sb.withUnsafeBytes(body)
    }

    /// Creates a key from the given data.
    ///
    /// - Parameters:
    ///   - data: The contiguous bytes from which to create the key.
    public init<D: ContiguousBytes>(data: D) {
        self.init(key: SecureBytes(bytes: data))
    }

    /// Generates a new random key of the given size.
    ///
    /// - Parameters:
    ///   - size: The size of the key to generate. You can use one of the standard
    /// sizes, like ``SymmetricKeySize/bits256``, or you can create a key of
    /// custom length by initializing a ``SymmetricKeySize`` instance with a
    /// non-standard value.
    public init(size: SymmetricKeySize) {
        self.init(key: SecureBytes(count: Int(size.bitCount / 8)))
    }

    internal init(unsafeUninitializedCapacity: Int, initializingWith callback: (inout UnsafeMutableRawBufferPointer, inout Int) throws -> Void) rethrows {
        self.init(key: try SecureBytes(unsafeUninitializedCapacity: unsafeUninitializedCapacity, initializingWith: callback))
    }

    // Fast-path alias for cases whe know we have a SecureBytes object.
    internal init(data: SecureBytes) {
        self.init(key: data)
    }

    /// The number of bits in the key.
    public var bitCount: Int {
        return self.byteCount * 8
    }
    
    var byteCount: Int {
        return self.withUnsafeBytes({ (rbf) in
            return rbf.count
        })
    }

    private init(key: SecureBytes) {
        sb = key
    }
}

extension SymmetricKey: Equatable {
    public static func == (lhs: Self, rhs: Self) -> Bool {
        return safeCompare(lhs, rhs)
    }
}

#endif // Linux or !SwiftPM