Initial commit
This commit is contained in:
128
Pods/BlueCryptor/Sources/Cryptor/Crypto.swift
generated
Executable file
128
Pods/BlueCryptor/Sources/Cryptor/Crypto.swift
generated
Executable file
@ -0,0 +1,128 @@
|
||||
//
|
||||
// Crypto.swift
|
||||
// Cryptor
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
///
|
||||
/// Implements a simplified API for calculating digests over single buffers
|
||||
///
|
||||
public protocol CryptoDigest {
|
||||
|
||||
/// Calculates a message digest
|
||||
func digest(using algorithm: Digest.Algorithm) -> Self
|
||||
}
|
||||
|
||||
///
|
||||
/// Extension to the CryptoDigest to return the digest appropriate to the selected algorithm.
|
||||
///
|
||||
extension CryptoDigest {
|
||||
|
||||
/// An MD2 digest of this object
|
||||
public var md2: Self {
|
||||
return self.digest(using: .md2)
|
||||
}
|
||||
|
||||
/// An MD4 digest of this object
|
||||
public var md4: Self {
|
||||
return self.digest(using: .md4)
|
||||
}
|
||||
|
||||
/// An MD5 digest of this object
|
||||
public var md5: Self {
|
||||
return self.digest(using: .md5)
|
||||
}
|
||||
|
||||
/// An SHA1 digest of this object
|
||||
public var sha1: Self {
|
||||
return self.digest(using: .sha1)
|
||||
}
|
||||
|
||||
/// An SHA224 digest of this object
|
||||
public var sha224: Self {
|
||||
return self.digest(using: .sha224)
|
||||
}
|
||||
|
||||
/// An SHA256 digest of this object
|
||||
public var sha256: Self {
|
||||
return self.digest(using: .sha256)
|
||||
}
|
||||
|
||||
/// An SHA384 digest of this object
|
||||
public var sha384: Self {
|
||||
return self.digest(using: .sha384)
|
||||
}
|
||||
|
||||
/// An SHA512 digest of this object
|
||||
public var sha512: Self {
|
||||
return self.digest(using: .sha512)
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Extension for Data to return an Data object containing the digest.
|
||||
///
|
||||
extension Data: CryptoDigest {
|
||||
///
|
||||
/// Calculates the Message Digest for this data.
|
||||
///
|
||||
/// - Parameter algorithm: The digest algorithm to use
|
||||
///
|
||||
/// - Returns: An `Data` object containing the message digest
|
||||
///
|
||||
public func digest(using algorithm: Digest.Algorithm) -> Data {
|
||||
|
||||
// This force unwrap may look scary but for CommonCrypto this cannot fail.
|
||||
// The API allows for optionals to support the OpenSSL implementation which can.
|
||||
#if swift(>=5.0)
|
||||
return self.withUnsafeBytes() {
|
||||
|
||||
let result = (Digest(using: algorithm).update(from: $0.baseAddress!, byteCount: self.count)?.final())!
|
||||
let data = type(of: self).init(bytes: result, count: result.count)
|
||||
return data
|
||||
}
|
||||
#else
|
||||
return self.withUnsafeBytes() { (buffer: UnsafePointer<UInt8>) -> Data in
|
||||
|
||||
let result = (Digest(using: algorithm).update(from: buffer, byteCount: self.count)?.final())!
|
||||
let data = type(of: self).init(bytes: result, count: result.count)
|
||||
return data
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Extension for String to return a String containing the digest.
|
||||
///
|
||||
extension String: CryptoDigest {
|
||||
///
|
||||
/// Calculates the Message Digest for this string.
|
||||
/// The string is converted to raw data using UTF8.
|
||||
///
|
||||
/// - Parameter algorithm: The digest algorithm to use
|
||||
///
|
||||
/// - Returns: A hex string of the calculated digest
|
||||
///
|
||||
public func digest(using algorithm: Digest.Algorithm) -> String {
|
||||
|
||||
// This force unwrap may look scary but for CommonCrypto this cannot fail.
|
||||
// The API allows for optionals to support the OpenSSL implementation which can.
|
||||
let result = (Digest(using: algorithm).update(string: self as String)?.final())!
|
||||
return CryptoUtils.hexString(from: result)
|
||||
|
||||
}
|
||||
}
|
||||
71
Pods/BlueCryptor/Sources/Cryptor/Cryptor.swift
generated
Executable file
71
Pods/BlueCryptor/Sources/Cryptor/Cryptor.swift
generated
Executable file
@ -0,0 +1,71 @@
|
||||
//
|
||||
// Cryptor.swift
|
||||
// Cryptor
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
///
|
||||
/// Encrypts or decrypts, accumulating result.
|
||||
///
|
||||
/// Useful for small in-memory buffers.
|
||||
///
|
||||
/// For large files or network streams use StreamCryptor.
|
||||
///
|
||||
public class Cryptor: StreamCryptor, Updatable {
|
||||
|
||||
/// Internal accumulator for gathering data from the update() and final() functions.
|
||||
var accumulator: [UInt8] = []
|
||||
|
||||
///
|
||||
/// Retrieves the encrypted or decrypted data.
|
||||
///
|
||||
///- Returns: the encrypted or decrypted data or nil if an error occured.
|
||||
///
|
||||
public func final() -> [UInt8]? {
|
||||
|
||||
let byteCount = Int(self.getOutputLength(inputByteCount: 0, isFinal: true))
|
||||
var dataOut = Array<UInt8>(repeating: 0, count:byteCount)
|
||||
var dataOutMoved = 0
|
||||
(dataOutMoved, self.status) = final(byteArrayOut: &dataOut)
|
||||
if self.status != .success {
|
||||
return nil
|
||||
}
|
||||
accumulator += dataOut[0..<Int(dataOutMoved)]
|
||||
return accumulator
|
||||
}
|
||||
|
||||
///
|
||||
/// Upates the accumulated encrypted/decrypted data with the contents
|
||||
/// of a raw byte buffer.
|
||||
///
|
||||
/// It is not envisaged the users of the framework will need to call this directly.
|
||||
///
|
||||
/// - Returns: this Cryptor object or nil if an error occurs (for optional chaining)
|
||||
///
|
||||
public func update(from buffer: UnsafeRawPointer, byteCount: Int) -> Self? {
|
||||
|
||||
let outputLength = Int(self.getOutputLength(inputByteCount: byteCount, isFinal: false))
|
||||
var dataOut = Array<UInt8>(repeating: 0, count:outputLength)
|
||||
var dataOutMoved = 0
|
||||
_ = update(bufferIn: buffer, byteCountIn: byteCount, bufferOut: &dataOut, byteCapacityOut: dataOut.count, byteCountOut: &dataOutMoved)
|
||||
if self.status != .success {
|
||||
return nil
|
||||
}
|
||||
accumulator += dataOut[0..<Int(dataOutMoved)]
|
||||
return self
|
||||
}
|
||||
|
||||
}
|
||||
279
Pods/BlueCryptor/Sources/Cryptor/Digest.swift
generated
Executable file
279
Pods/BlueCryptor/Sources/Cryptor/Digest.swift
generated
Executable file
@ -0,0 +1,279 @@
|
||||
//
|
||||
// Digest.swift
|
||||
// Cryptor
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
import CommonCrypto
|
||||
#elseif os(Linux)
|
||||
import OpenSSL
|
||||
typealias CC_LONG = size_t
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Public API for message digests.
|
||||
///
|
||||
/// Usage is straightforward
|
||||
///
|
||||
/// ```
|
||||
/// let s = "The quick brown fox jumps over the lazy dog."
|
||||
/// var md5: Digest = Digest(using:.md5)
|
||||
/// md5.update(s)
|
||||
/// let digest = md5.final()
|
||||
///```
|
||||
///
|
||||
public class Digest: Updatable {
|
||||
|
||||
///
|
||||
/// The status of the Digest.
|
||||
/// For CommonCrypto this will always be `.Success`.
|
||||
/// It is here to provide for engines which can fail.
|
||||
///
|
||||
public var status = Status.success
|
||||
|
||||
///
|
||||
/// Enumerates available Digest algorithms
|
||||
///
|
||||
public enum Algorithm {
|
||||
|
||||
/// Message Digest 2 See: http://en.wikipedia.org/wiki/MD2_(cryptography)
|
||||
case md2
|
||||
|
||||
/// Message Digest 4
|
||||
case md4
|
||||
|
||||
/// Message Digest 5
|
||||
case md5
|
||||
|
||||
/// Secure Hash Algorithm 1
|
||||
case sha1
|
||||
|
||||
/// Secure Hash Algorithm 2 224-bit
|
||||
case sha224
|
||||
|
||||
/// Secure Hash Algorithm 2 256-bit
|
||||
case sha256
|
||||
|
||||
/// Secure Hash Algorithm 2 384-bit
|
||||
case sha384
|
||||
|
||||
/// Secure Hash Algorithm 2 512-bit
|
||||
case sha512
|
||||
}
|
||||
|
||||
private var engine: DigestEngine
|
||||
|
||||
///
|
||||
/// Create an algorithm-specific digest calculator
|
||||
///
|
||||
/// - Parameter alrgorithm: the desired message digest algorithm
|
||||
///
|
||||
public init(using algorithm: Algorithm) {
|
||||
|
||||
switch algorithm {
|
||||
|
||||
case .md2:
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
engine = DigestEngineCC<CC_MD2_CTX>(initializer:CC_MD2_Init, updater:CC_MD2_Update, finalizer:CC_MD2_Final, length:CC_MD2_DIGEST_LENGTH)
|
||||
#elseif os(Linux)
|
||||
fatalError("MD2 digest not supported by OpenSSL")
|
||||
#endif
|
||||
|
||||
case .md4:
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
engine = DigestEngineCC<CC_MD4_CTX>(initializer:CC_MD4_Init, updater:CC_MD4_Update, finalizer:CC_MD4_Final, length:CC_MD4_DIGEST_LENGTH)
|
||||
#elseif os(Linux)
|
||||
engine = DigestEngineCC<MD4_CTX>(initializer:MD4_Init, updater:MD4_Update, finalizer:MD4_Final, length:MD4_DIGEST_LENGTH)
|
||||
#endif
|
||||
|
||||
case .md5:
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
engine = DigestEngineCC<CC_MD5_CTX>(initializer:CC_MD5_Init, updater:CC_MD5_Update, finalizer:CC_MD5_Final, length:CC_MD5_DIGEST_LENGTH)
|
||||
#elseif os(Linux)
|
||||
engine = DigestEngineCC<MD5_CTX>(initializer:MD5_Init, updater:MD5_Update, finalizer:MD5_Final, length:MD5_DIGEST_LENGTH)
|
||||
#endif
|
||||
|
||||
case .sha1:
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
engine = DigestEngineCC<CC_SHA1_CTX>(initializer:CC_SHA1_Init, updater:CC_SHA1_Update, finalizer:CC_SHA1_Final, length:CC_SHA1_DIGEST_LENGTH)
|
||||
#elseif os(Linux)
|
||||
engine = DigestEngineCC<SHA_CTX>(initializer:SHA1_Init, updater:SHA1_Update, finalizer:SHA1_Final, length:SHA_DIGEST_LENGTH)
|
||||
#endif
|
||||
|
||||
case .sha224:
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
engine = DigestEngineCC<CC_SHA256_CTX>(initializer:CC_SHA224_Init, updater:CC_SHA224_Update, finalizer:CC_SHA224_Final, length:CC_SHA224_DIGEST_LENGTH)
|
||||
#elseif os(Linux)
|
||||
engine = DigestEngineCC<SHA256_CTX>(initializer:SHA224_Init, updater:SHA224_Update, finalizer:SHA224_Final, length:SHA224_DIGEST_LENGTH)
|
||||
#endif
|
||||
|
||||
case .sha256:
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
engine = DigestEngineCC<CC_SHA256_CTX>(initializer:CC_SHA256_Init, updater:CC_SHA256_Update, finalizer:CC_SHA256_Final, length:CC_SHA256_DIGEST_LENGTH)
|
||||
#elseif os(Linux)
|
||||
engine = DigestEngineCC<SHA256_CTX>(initializer: SHA256_Init, updater:SHA256_Update, finalizer:SHA256_Final, length:SHA256_DIGEST_LENGTH)
|
||||
#endif
|
||||
|
||||
case .sha384:
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
engine = DigestEngineCC<CC_SHA512_CTX>(initializer:CC_SHA384_Init, updater:CC_SHA384_Update, finalizer:CC_SHA384_Final, length:CC_SHA384_DIGEST_LENGTH)
|
||||
#elseif os(Linux)
|
||||
engine = DigestEngineCC<SHA512_CTX>(initializer:SHA384_Init, updater:SHA384_Update, finalizer:SHA384_Final, length:SHA384_DIGEST_LENGTH)
|
||||
#endif
|
||||
|
||||
case .sha512:
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
engine = DigestEngineCC<CC_SHA512_CTX>(initializer:CC_SHA512_Init, updater:CC_SHA512_Update, finalizer:CC_SHA512_Final, length:CC_SHA512_DIGEST_LENGTH)
|
||||
#elseif os(Linux)
|
||||
engine = DigestEngineCC<SHA512_CTX>(initializer:SHA512_Init, updater:SHA512_Update, finalizer:SHA512_Final, length:SHA512_DIGEST_LENGTH)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Low-level update routine. Updates the message digest calculation with
|
||||
/// the contents of a byte buffer.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - buffer: The buffer
|
||||
/// - byteCount: Number of bytes in buffer
|
||||
///
|
||||
/// - Returns: This Digest object (for optional chaining)
|
||||
///
|
||||
public func update(from buffer: UnsafeRawPointer, byteCount: size_t) -> Self? {
|
||||
|
||||
engine.update(buffer: buffer, byteCount: CC_LONG(byteCount))
|
||||
return self
|
||||
}
|
||||
|
||||
///
|
||||
/// Completes the calculate of the messge digest
|
||||
///
|
||||
/// - Returns: The message digest
|
||||
///
|
||||
public func final() -> [UInt8] {
|
||||
|
||||
return engine.final()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Internal Classes
|
||||
|
||||
///
|
||||
/// Defines the interface between the Digest class and an
|
||||
/// algorithm specific DigestEngine
|
||||
///
|
||||
private protocol DigestEngine {
|
||||
|
||||
///
|
||||
/// Update method
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - buffer: The buffer to add.
|
||||
/// - byteCount: The length of the buffer.
|
||||
///
|
||||
func update(buffer: UnsafeRawPointer, byteCount: CC_LONG)
|
||||
|
||||
///
|
||||
/// Finalizer routine
|
||||
///
|
||||
/// - Returns: Byte array containing the digest.
|
||||
///
|
||||
func final() -> [UInt8]
|
||||
}
|
||||
|
||||
///
|
||||
/// Wraps the underlying algorithm specific structures and calls
|
||||
/// in a generic interface.
|
||||
///
|
||||
/// - Parameter CTX: The context for the digest.
|
||||
///
|
||||
private class DigestEngineCC<CTX>: DigestEngine {
|
||||
|
||||
typealias Context = UnsafeMutablePointer<CTX>
|
||||
typealias Buffer = UnsafeRawPointer
|
||||
typealias Digest = UnsafeMutablePointer<UInt8>
|
||||
typealias Initializer = (Context) -> (Int32)
|
||||
typealias Updater = (Context, Buffer, CC_LONG) -> (Int32)
|
||||
typealias Finalizer = (Digest, Context) -> (Int32)
|
||||
|
||||
let context = Context.allocate(capacity: 1)
|
||||
var initializer: Initializer
|
||||
var updater: Updater
|
||||
var finalizer: Finalizer
|
||||
var length: Int32
|
||||
|
||||
///
|
||||
/// Default initializer
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - initializer: The digest initializer routine.
|
||||
/// - updater: The digest updater routine.
|
||||
/// - finalizer: The digest finalizer routine.
|
||||
/// - length: The digest length.
|
||||
///
|
||||
init(initializer: @escaping Initializer, updater: @escaping Updater, finalizer: @escaping Finalizer, length: Int32) {
|
||||
|
||||
self.initializer = initializer
|
||||
self.updater = updater
|
||||
self.finalizer = finalizer
|
||||
self.length = length
|
||||
_ = initializer(context)
|
||||
}
|
||||
|
||||
///
|
||||
/// Cleanup
|
||||
///
|
||||
deinit {
|
||||
|
||||
#if swift(>=4.1)
|
||||
context.deallocate()
|
||||
#else
|
||||
context.deallocate(capacity: 1)
|
||||
#endif
|
||||
}
|
||||
|
||||
///
|
||||
/// Update method
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - buffer: The buffer to add.
|
||||
/// - byteCount: The length of the buffer.
|
||||
///
|
||||
func update(buffer: Buffer, byteCount: CC_LONG) {
|
||||
|
||||
_ = updater(context, buffer, byteCount)
|
||||
}
|
||||
|
||||
///
|
||||
/// Finalizer routine
|
||||
///
|
||||
/// - Returns: Byte array containing the digest.
|
||||
///
|
||||
func final() -> [UInt8] {
|
||||
|
||||
let digestLength = Int(self.length)
|
||||
var digest = Array<UInt8>(repeating: 0, count:digestLength)
|
||||
_ = finalizer(&digest, context)
|
||||
return digest
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
335
Pods/BlueCryptor/Sources/Cryptor/HMAC.swift
generated
Executable file
335
Pods/BlueCryptor/Sources/Cryptor/HMAC.swift
generated
Executable file
@ -0,0 +1,335 @@
|
||||
//
|
||||
// HMAC.swift
|
||||
// Cryptor
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
import CommonCrypto
|
||||
#elseif os(Linux)
|
||||
import OpenSSL
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Calculates a cryptographic Hash-Based Message Authentication Code (HMAC).
|
||||
///
|
||||
public class HMAC: Updatable {
|
||||
|
||||
///
|
||||
/// Enumerates available algorithms.
|
||||
///
|
||||
public enum Algorithm {
|
||||
|
||||
/// Message Digest 5
|
||||
case md5
|
||||
|
||||
/// Secure Hash Algorithm 1
|
||||
case sha1
|
||||
|
||||
/// Secure Hash Algorithm 2 224-bit
|
||||
case sha224
|
||||
|
||||
/// Secure Hash Algorithm 2 256-bit
|
||||
case sha256
|
||||
|
||||
/// Secure Hash Algorithm 2 384-bit
|
||||
case sha384
|
||||
|
||||
/// Secure Hash Algorithm 2 512-bit
|
||||
case sha512
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
|
||||
static let fromNative: [CCHmacAlgorithm: Algorithm] = [
|
||||
CCHmacAlgorithm(kCCHmacAlgSHA1): .sha1,
|
||||
CCHmacAlgorithm(kCCHmacAlgSHA1): .md5,
|
||||
CCHmacAlgorithm(kCCHmacAlgSHA256): .sha256,
|
||||
CCHmacAlgorithm(kCCHmacAlgSHA384): .sha384,
|
||||
CCHmacAlgorithm(kCCHmacAlgSHA512): .sha512,
|
||||
CCHmacAlgorithm(kCCHmacAlgSHA224): .sha224
|
||||
]
|
||||
|
||||
static func fromNativeValue(nativeAlg: CCHmacAlgorithm) -> Algorithm? {
|
||||
|
||||
return fromNative[nativeAlg]
|
||||
}
|
||||
|
||||
func nativeValue() -> CCHmacAlgorithm {
|
||||
|
||||
switch self {
|
||||
|
||||
case .sha1:
|
||||
return CCHmacAlgorithm(kCCHmacAlgSHA1)
|
||||
case .md5:
|
||||
return CCHmacAlgorithm(kCCHmacAlgMD5)
|
||||
case .sha224:
|
||||
return CCHmacAlgorithm(kCCHmacAlgSHA224)
|
||||
case .sha256:
|
||||
return CCHmacAlgorithm(kCCHmacAlgSHA256)
|
||||
case .sha384:
|
||||
return CCHmacAlgorithm(kCCHmacAlgSHA384)
|
||||
case .sha512:
|
||||
return CCHmacAlgorithm(kCCHmacAlgSHA512)
|
||||
}
|
||||
}
|
||||
|
||||
#elseif os(Linux)
|
||||
|
||||
func nativeValue() -> OpaquePointer? {
|
||||
|
||||
switch self {
|
||||
|
||||
case .sha1:
|
||||
return .init(EVP_sha1())
|
||||
case .md5:
|
||||
return .init(EVP_md5())
|
||||
case .sha224:
|
||||
return .init(EVP_sha224())
|
||||
case .sha256:
|
||||
return .init(EVP_sha256())
|
||||
case .sha384:
|
||||
return .init(EVP_sha384())
|
||||
case .sha512:
|
||||
return .init(EVP_sha512())
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Obtains the digest length produced by this algorithm (in bytes).
|
||||
///
|
||||
public func digestLength() -> Int {
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
|
||||
switch self {
|
||||
|
||||
case .sha1:
|
||||
return Int(CC_SHA1_DIGEST_LENGTH)
|
||||
case .md5:
|
||||
return Int(CC_MD5_DIGEST_LENGTH)
|
||||
case .sha224:
|
||||
return Int(CC_SHA224_DIGEST_LENGTH)
|
||||
case .sha256:
|
||||
return Int(CC_SHA256_DIGEST_LENGTH)
|
||||
case .sha384:
|
||||
return Int(CC_SHA384_DIGEST_LENGTH)
|
||||
case .sha512:
|
||||
return Int(CC_SHA512_DIGEST_LENGTH)
|
||||
}
|
||||
|
||||
#elseif os(Linux)
|
||||
|
||||
switch self {
|
||||
|
||||
case .sha1:
|
||||
return Int(SHA_DIGEST_LENGTH)
|
||||
case .md5:
|
||||
return Int(MD5_DIGEST_LENGTH)
|
||||
case .sha224:
|
||||
return Int(SHA224_DIGEST_LENGTH)
|
||||
case .sha256:
|
||||
return Int(SHA256_DIGEST_LENGTH)
|
||||
case .sha384:
|
||||
return Int(SHA384_DIGEST_LENGTH)
|
||||
case .sha512:
|
||||
return Int(SHA512_DIGEST_LENGTH)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// Context
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
|
||||
typealias Context = UnsafeMutablePointer<CCHmacContext>
|
||||
|
||||
#elseif os(Linux)
|
||||
|
||||
typealias Context = OpaquePointer?
|
||||
|
||||
#endif
|
||||
|
||||
/// Status of the calculation
|
||||
public internal(set) var status: Status = .success
|
||||
|
||||
#if os(Linux)
|
||||
private let context = HMAC_CTX_new_wrapper()
|
||||
#else
|
||||
private let context = Context.allocate(capacity: 1)
|
||||
#endif
|
||||
private var algorithm: Algorithm
|
||||
|
||||
// MARK: Lifecycle Methods
|
||||
|
||||
///
|
||||
/// Creates a new HMAC instance with the specified algorithm and key.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - algorithm: Selects the algorithm
|
||||
/// - keyBuffer: Specifies pointer to the key
|
||||
/// - keyByteCount: Number of bytes on keyBuffer
|
||||
///
|
||||
init(using algorithm: Algorithm, keyBuffer: UnsafeRawPointer, keyByteCount: Int) {
|
||||
|
||||
self.algorithm = algorithm
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
CCHmacInit(context, algorithm.nativeValue(), keyBuffer, size_t(keyByteCount))
|
||||
#elseif os(Linux)
|
||||
HMAC_Init_wrapper(context, keyBuffer, Int32(keyByteCount), .make(optional: algorithm.nativeValue()))
|
||||
#endif
|
||||
}
|
||||
|
||||
///
|
||||
/// Creates a new HMAC instance with the specified algorithm and key.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - algorithm: Selects the algorithm
|
||||
/// - key: Specifies the key as Data
|
||||
///
|
||||
public init(using algorithm: Algorithm, key: Data) {
|
||||
|
||||
self.algorithm = algorithm
|
||||
#if swift(>=5.0)
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
key.withUnsafeBytes() {
|
||||
CCHmacInit(context, algorithm.nativeValue(), $0.baseAddress, size_t(key.count))
|
||||
}
|
||||
#elseif os(Linux)
|
||||
_ = key.withUnsafeBytes() {
|
||||
HMAC_Init_wrapper(context, $0.baseAddress, Int32(key.count), .make(optional: algorithm.nativeValue()))
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
key.withUnsafeBytes() { (buffer: UnsafePointer<UInt8>) in
|
||||
CCHmacInit(context, algorithm.nativeValue(), buffer, size_t(key.count))
|
||||
}
|
||||
#elseif os(Linux)
|
||||
_ = key.withUnsafeBytes() { (buffer: UnsafePointer<UInt8>) in
|
||||
HMAC_Init_wrapper(context, buffer, Int32(key.count), .make(optional: algorithm.nativeValue()))
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
///
|
||||
/// Creates a new HMAC instance with the specified algorithm and key.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - algorithm: Selects the algorithm
|
||||
/// - key: Specifies the key as NSData
|
||||
///
|
||||
public init(using algorithm: Algorithm, key: NSData) {
|
||||
|
||||
self.algorithm = algorithm
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
CCHmacInit(context, algorithm.nativeValue(), key.bytes, size_t(key.length))
|
||||
#elseif os(Linux)
|
||||
HMAC_Init_wrapper(context, key.bytes, Int32(key.length), .make(optional: algorithm.nativeValue()))
|
||||
#endif
|
||||
}
|
||||
|
||||
///
|
||||
/// Creates a new HMAC instance with the specified algorithm and key.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - algorithm: Selects the algorithm
|
||||
/// - key: Specifies the key as byte array.
|
||||
///
|
||||
public init(using algorithm: Algorithm, key: [UInt8]) {
|
||||
|
||||
self.algorithm = algorithm
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
CCHmacInit(context, algorithm.nativeValue(), key, size_t(key.count))
|
||||
#elseif os(Linux)
|
||||
HMAC_Init_wrapper(context, key, Int32(key.count), .make(optional: algorithm.nativeValue()))
|
||||
#endif
|
||||
}
|
||||
|
||||
///
|
||||
/// Creates a new HMAC instance with the specified algorithm and key string.
|
||||
/// The key string is converted to bytes using UTF8 encoding.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - algorithm: Selects the algorithm
|
||||
/// - key: Specifies the key as String
|
||||
///
|
||||
public init(using algorithm: Algorithm, key: String) {
|
||||
|
||||
self.algorithm = algorithm
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
CCHmacInit(context, algorithm.nativeValue(), key, size_t(key.lengthOfBytes(using: String.Encoding.utf8)))
|
||||
#elseif os(Linux)
|
||||
HMAC_Init_wrapper(context, key, Int32(key.utf8.count), .make(optional: algorithm.nativeValue()))
|
||||
#endif
|
||||
}
|
||||
|
||||
///
|
||||
/// Cleanup
|
||||
///
|
||||
deinit {
|
||||
#if os(Linux)
|
||||
HMAC_CTX_free_wrapper(.make(optional: context))
|
||||
#else
|
||||
#if swift(>=4.1)
|
||||
context.deallocate()
|
||||
#else
|
||||
context.deallocate(capacity: 1)
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
// MARK: Public Methods
|
||||
|
||||
///
|
||||
/// Updates the calculation of the HMAC with the contents of a buffer.
|
||||
///
|
||||
/// - Parameter buffer: Update buffer
|
||||
///
|
||||
/// - Returns: The 'in-progress' calculated HMAC
|
||||
///
|
||||
public func update(from buffer: UnsafeRawPointer, byteCount: size_t) -> Self? {
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
CCHmacUpdate(context, buffer, byteCount)
|
||||
#elseif os(Linux)
|
||||
HMAC_Update(context, buffer.assumingMemoryBound(to: UInt8.self), byteCount)
|
||||
#endif
|
||||
return self
|
||||
}
|
||||
|
||||
///
|
||||
/// Finalizes the HMAC calculation
|
||||
///
|
||||
/// - Returns: The final calculated HMAC
|
||||
///
|
||||
public func final() -> [UInt8] {
|
||||
|
||||
var hmac = Array<UInt8>(repeating: 0, count:algorithm.digestLength())
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
CCHmacFinal(context, &hmac)
|
||||
#elseif os(Linux)
|
||||
var length: UInt32 = 0
|
||||
HMAC_Final(context, &hmac, &length)
|
||||
#endif
|
||||
return hmac
|
||||
}
|
||||
}
|
||||
|
||||
211
Pods/BlueCryptor/Sources/Cryptor/KeyDerivation.swift
generated
Executable file
211
Pods/BlueCryptor/Sources/Cryptor/KeyDerivation.swift
generated
Executable file
@ -0,0 +1,211 @@
|
||||
//
|
||||
// KeyDerivation.swift
|
||||
// Cryptor
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
import CommonCrypto
|
||||
#elseif os(Linux)
|
||||
import OpenSSL
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Derives key material from a password or passphrase.
|
||||
///
|
||||
public class PBKDF {
|
||||
|
||||
/// Enumerates available pseudo random algorithms
|
||||
public enum PseudoRandomAlgorithm {
|
||||
|
||||
/// Secure Hash Algorithm 1
|
||||
case sha1
|
||||
|
||||
/// Secure Hash Algorithm 2 224-bit
|
||||
case sha224
|
||||
|
||||
/// Secure Hash Algorithm 2 256-bit
|
||||
case sha256
|
||||
|
||||
/// Secure Hash Algorithm 2 384-bit
|
||||
case sha384
|
||||
|
||||
/// Secure Hash Algorithm 2 512-bit
|
||||
case sha512
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
/// Return the OS native value
|
||||
func nativeValue() -> CCPseudoRandomAlgorithm {
|
||||
|
||||
switch self {
|
||||
|
||||
case .sha1:
|
||||
return CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1)
|
||||
case .sha224:
|
||||
return CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA224)
|
||||
case .sha256:
|
||||
return CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256)
|
||||
case .sha384:
|
||||
return CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA384)
|
||||
case .sha512:
|
||||
return CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA512)
|
||||
}
|
||||
}
|
||||
|
||||
#elseif os(Linux)
|
||||
|
||||
/// Return the OS native value
|
||||
func nativeValue() -> OpaquePointer? {
|
||||
|
||||
switch self {
|
||||
|
||||
case .sha1:
|
||||
return .init(EVP_sha1())
|
||||
case .sha224:
|
||||
return .init(EVP_sha224())
|
||||
case .sha256:
|
||||
return .init(EVP_sha256())
|
||||
case .sha384:
|
||||
return .init(EVP_sha384())
|
||||
case .sha512:
|
||||
return .init(EVP_sha512())
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
///
|
||||
/// Determines the (approximate) number of iterations of the key derivation algorithm that need
|
||||
/// to be run to achieve a particular delay (or calculation time).
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - passwordLength: Password length in bytes
|
||||
/// - saltLength: Salt length in bytes
|
||||
/// - algorithm: The PseudoRandomAlgorithm to use
|
||||
/// - derivedKeyLength: The desired key length
|
||||
/// - msec: The desired calculation time
|
||||
///
|
||||
/// - Returns: The number of times the algorithm should be run
|
||||
///
|
||||
public class func calibrate(passwordLength: Int, saltLength: Int, algorithm: PseudoRandomAlgorithm, derivedKeyLength: Int, msec: UInt32) -> UInt {
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
return UInt(CCCalibratePBKDF(CCPBKDFAlgorithm(kCCPBKDF2), passwordLength, saltLength, algorithm.nativeValue(), derivedKeyLength, msec))
|
||||
#elseif os(Linux)
|
||||
// Value as per RFC 2898.
|
||||
return UInt(1000 * UInt(msec))
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Derives key material from a password and salt.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - password: The password string, will be converted using UTF8
|
||||
/// - salt: The salt string will be converted using UTF8
|
||||
/// - prf: The pseudo random function
|
||||
/// - round: The number of rounds
|
||||
/// - derivedKeyLength: The length of the desired derived key, in bytes.
|
||||
///
|
||||
/// - Returns: The derived key
|
||||
///
|
||||
public class func deriveKey(fromPassword password: String, salt: String, prf: PseudoRandomAlgorithm, rounds: uint, derivedKeyLength: UInt) throws -> [UInt8] {
|
||||
|
||||
var derivedKey = Array<UInt8>(repeating: 0, count:Int(derivedKeyLength))
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
let status: Int32 = CCKeyDerivationPBKDF(CCPBKDFAlgorithm(kCCPBKDF2), password, password.utf8.count, salt, salt.utf8.count, prf.nativeValue(), rounds, &derivedKey, derivedKey.count)
|
||||
if status != Int32(kCCSuccess) {
|
||||
|
||||
throw CryptorError.fail(status, "ERROR: CCKeyDerivationPBDK failed with status \(status).")
|
||||
}
|
||||
#elseif os(Linux)
|
||||
let status = PKCS5_PBKDF2_HMAC(password, Int32(password.utf8.count), salt, Int32(salt.utf8.count), Int32(rounds), .make(optional: prf.nativeValue()), Int32(derivedKey.count), &derivedKey)
|
||||
if status != 1 {
|
||||
let error = ERR_get_error()
|
||||
|
||||
throw CryptorError.fail(Int32(error), "ERROR: PKCS5_PBKDF2_HMAC failed, reason: \(errToString(ERR_error_string(error, nil)))")
|
||||
}
|
||||
#endif
|
||||
return derivedKey
|
||||
}
|
||||
|
||||
///
|
||||
/// Derives key material from a password and salt.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - password: The password string, will be converted using UTF8
|
||||
/// - salt: The salt array of bytes
|
||||
/// - prf: The pseudo random function
|
||||
/// - round: The number of rounds
|
||||
/// - derivedKeyLength: The length of the desired derived key, in bytes.
|
||||
///
|
||||
/// - Returns: The derived key
|
||||
///
|
||||
public class func deriveKey(fromPassword password: String, salt: [UInt8], prf: PseudoRandomAlgorithm, rounds: uint, derivedKeyLength: UInt) throws -> [UInt8] {
|
||||
|
||||
var derivedKey = Array<UInt8>(repeating: 0, count:Int(derivedKeyLength))
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
let status: Int32 = CCKeyDerivationPBKDF(CCPBKDFAlgorithm(kCCPBKDF2), password, password.utf8.count, salt, salt.count, prf.nativeValue(), rounds, &derivedKey, derivedKey.count)
|
||||
if status != Int32(kCCSuccess) {
|
||||
|
||||
throw CryptorError.fail(status, "ERROR: CCKeyDerivationPBDK failed with status \(status).")
|
||||
}
|
||||
#elseif os(Linux)
|
||||
let status = PKCS5_PBKDF2_HMAC(password, Int32(password.utf8.count), salt, Int32(salt.count), Int32(rounds), .make(optional: prf.nativeValue()), Int32(derivedKey.count), &derivedKey)
|
||||
if status != 1 {
|
||||
let error = ERR_get_error()
|
||||
|
||||
throw CryptorError.fail(Int32(error), "ERROR: PKCS5_PBKDF2_HMAC failed, reason: \(errToString(ERR_error_string(error, nil)))")
|
||||
}
|
||||
#endif
|
||||
return derivedKey
|
||||
}
|
||||
|
||||
///
|
||||
/// Derives key material from a password buffer.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - password: Pointer to the password buffer
|
||||
/// - passwordLength: Password length in bytes
|
||||
/// - salt: Pointer to the salt buffer
|
||||
/// - saltLength: Salt length in bytes
|
||||
/// - prf: The PseudoRandomAlgorithm to use
|
||||
/// - rounds: The number of rounds of the algorithm to use
|
||||
/// - derivedKey: Pointer to the derived key buffer.
|
||||
/// - derivedKeyLength: The desired key length
|
||||
///
|
||||
/// - Returns: The number of times the algorithm should be run
|
||||
///
|
||||
public class func deriveKey(fromPassword password: UnsafePointer<Int8>, passwordLen: Int, salt: UnsafePointer<UInt8>, saltLen: Int, prf: PseudoRandomAlgorithm, rounds: uint, derivedKey: UnsafeMutablePointer<UInt8>, derivedKeyLen: Int) throws {
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
let status: Int32 = CCKeyDerivationPBKDF(CCPBKDFAlgorithm(kCCPBKDF2), password, passwordLen, salt, saltLen, prf.nativeValue(), rounds, derivedKey, derivedKeyLen)
|
||||
if status != Int32(kCCSuccess) {
|
||||
|
||||
throw CryptorError.fail(status, "ERROR: CCKeyDerivationPBDK failed with status \(status).")
|
||||
}
|
||||
#elseif os(Linux)
|
||||
let status = PKCS5_PBKDF2_HMAC(password, Int32(passwordLen), salt, Int32(saltLen), Int32(rounds), .make(optional: prf.nativeValue()), Int32(derivedKeyLen), derivedKey)
|
||||
if status != 1 {
|
||||
let error = ERR_get_error()
|
||||
|
||||
throw CryptorError.fail(Int32(error), "ERROR: PKCS5_PBKDF2_HMAC failed, reason: \(errToString(ERR_error_string(error, nil)))")
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
106
Pods/BlueCryptor/Sources/Cryptor/Random.swift
generated
Executable file
106
Pods/BlueCryptor/Sources/Cryptor/Random.swift
generated
Executable file
@ -0,0 +1,106 @@
|
||||
//
|
||||
// Random.swift
|
||||
// Cryptor
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
import CommonCrypto
|
||||
#elseif os(Linux)
|
||||
import OpenSSL
|
||||
#endif
|
||||
|
||||
public typealias RNGStatus = Status
|
||||
|
||||
///
|
||||
/// Generates buffers of random bytes.
|
||||
///
|
||||
public class Random {
|
||||
|
||||
///
|
||||
/// Wraps native call.
|
||||
///
|
||||
/// - Note: CCRNGStatus is typealiased to CCStatus but this routine can only return kCCSuccess or kCCRNGFailure
|
||||
///
|
||||
/// - Parameter bytes: A pointer to the buffer that will receive the bytes
|
||||
///
|
||||
/// - Returns: `.success` or `.rngFailure` as appropriate.
|
||||
///
|
||||
public class func generate(bytes: UnsafeMutablePointer<UInt8>, byteCount: Int) -> RNGStatus {
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
let statusCode = CCRandomGenerateBytes(bytes, byteCount)
|
||||
guard let status = Status(rawValue: statusCode) else {
|
||||
fatalError("CCRandomGenerateBytes returned unexpected status code: \(statusCode)")
|
||||
}
|
||||
return status
|
||||
#elseif os(Linux)
|
||||
let statusCode = RAND_bytes(bytes, Int32(byteCount))
|
||||
if statusCode != 1 {
|
||||
|
||||
let errCode = ERR_get_error()
|
||||
return Status.rngFailure(errCode)
|
||||
}
|
||||
return Status.success
|
||||
#endif
|
||||
}
|
||||
|
||||
///
|
||||
/// Generates an array of random bytes.
|
||||
///
|
||||
/// - Parameter bytesCount: Number of random bytes to generate
|
||||
///
|
||||
/// - Returns: an array of random bytes
|
||||
///
|
||||
/// - Throws: `.success` or an `.rngFailure` on failure
|
||||
///
|
||||
public class func generate(byteCount: Int) throws -> [UInt8] {
|
||||
|
||||
guard byteCount > 0 else {
|
||||
throw RNGStatus.paramError
|
||||
}
|
||||
|
||||
var bytes = Array(repeating: UInt8(0), count:byteCount)
|
||||
let status = generate(bytes: &bytes, byteCount: byteCount)
|
||||
|
||||
if status != .success {
|
||||
throw status
|
||||
}
|
||||
|
||||
return bytes
|
||||
}
|
||||
|
||||
///
|
||||
/// A version of generateBytes that always throws an error.
|
||||
///
|
||||
/// Use it to test that code handles this.
|
||||
///
|
||||
/// - Parameter bytesCount: Number of random bytes to generate
|
||||
///
|
||||
/// - Returns: An array of random bytes
|
||||
///
|
||||
public class func generateBytesThrow(byteCount: Int) throws -> [UInt8] {
|
||||
|
||||
if byteCount <= 0 {
|
||||
|
||||
fatalError("generate: byteCount must be positve and non-zero")
|
||||
}
|
||||
var bytes: [UInt8] = Array(repeating: UInt8(0), count:byteCount)
|
||||
let status = generate(bytes: &bytes, byteCount: byteCount)
|
||||
throw status
|
||||
//return bytes
|
||||
}
|
||||
}
|
||||
100
Pods/BlueCryptor/Sources/Cryptor/SSLPointerTricks.swift
generated
Normal file
100
Pods/BlueCryptor/Sources/Cryptor/SSLPointerTricks.swift
generated
Normal file
@ -0,0 +1,100 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This source file is taken from SwiftNIO open source project
|
||||
//
|
||||
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
|
||||
// Licensed under Apache License v2.0
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// MARK:- Awful code begins here
|
||||
// Hello dear reader. Let me explain what we're doing here.
|
||||
//
|
||||
// From OpenSSL 1.0 to OpenSSL 1.1 one of the major breaking changes was the so-called
|
||||
// "great opaquifiying". Essentially, OpenSSL took all of its public structures and made
|
||||
// them opaque, such that they cannot be introspected from client code. This is a great
|
||||
// forward step, and brings them more in line with modern C library practices.
|
||||
//
|
||||
// However, it's an *enormous* inconvenience from Swift code. This is because the Swift
|
||||
// translation of the C type `SSL_CTX *` changed from `UnsafeMutablePointer<SSL_CTX>` to
|
||||
// `OpaquePointer`.
|
||||
//
|
||||
// This change exists for reasonable enough reasons in Swift land (see
|
||||
// https://forums.swift.org/t/opaque-pointers-in-swift/6875 for a discussion), but
|
||||
// nonetheless causes enormous problems in our codebase.
|
||||
//
|
||||
// Our cheap way out is to make everything an OpaquePointer, and then provide initializers
|
||||
// between OpaquePointer and the typed pointers. This allows us to tolerate either pointer
|
||||
// type in our Swift code by bridging them over to OpaquePointer and back, and lets the
|
||||
// compiler worry about how exactly to make that work.
|
||||
//
|
||||
// Now, in fact, Swift already has initializers between the pointer types. What it does
|
||||
// not have is self-initializers: the ability to create an `OpaquePointer` from an `OpaquePointer`,
|
||||
// or an `UnsafePointer<T>` from an `UnsafePointer<T>`. We add those two initializers here.
|
||||
// We also add a special "make" function that exists to handle the special case of optional pointer
|
||||
// values, which we mostly encounter in the ALPN callbacks.
|
||||
//
|
||||
// The *downside* of this approach is that we totally break the pointer type system. It becomes
|
||||
// trivially possible to alias a pointer of type T to type U through two calls to init. This
|
||||
// is not a thing we want to widely promote. For this reason, these extensions are hidden in
|
||||
// this file, where we can laugh and jeer at them and generally make them feel bad about
|
||||
// themselves.
|
||||
//
|
||||
// Hopefully, in time, these extensions can be removed.
|
||||
|
||||
extension UnsafePointer {
|
||||
init(_ ptr: UnsafePointer<Pointee>) {
|
||||
self = ptr
|
||||
}
|
||||
|
||||
static func make(optional ptr: UnsafePointer<Pointee>?) -> UnsafePointer<Pointee>? {
|
||||
return ptr.map(UnsafePointer<Pointee>.init)
|
||||
}
|
||||
|
||||
static func make(optional ptr: OpaquePointer?) -> UnsafePointer<Pointee>? {
|
||||
return ptr.map(UnsafePointer<Pointee>.init)
|
||||
}
|
||||
}
|
||||
|
||||
extension UnsafeMutablePointer {
|
||||
init(_ ptr: UnsafeMutableRawPointer) {
|
||||
let x = UnsafeMutablePointer<Pointee>(bitPattern: UInt(bitPattern: ptr))!
|
||||
self = x
|
||||
}
|
||||
|
||||
static func make(optional ptr: UnsafeMutablePointer<Pointee>?) -> UnsafeMutablePointer<Pointee>? {
|
||||
return ptr.map(UnsafeMutablePointer<Pointee>.init)
|
||||
}
|
||||
|
||||
static func make(optional ptr: UnsafeMutableRawPointer?) -> UnsafeMutablePointer<Pointee>? {
|
||||
return ptr.map(UnsafeMutablePointer<Pointee>.init)
|
||||
}
|
||||
|
||||
static func make(optional ptr: OpaquePointer?) -> UnsafeMutablePointer<Pointee>? {
|
||||
return ptr.map(UnsafeMutablePointer<Pointee>.init)
|
||||
}
|
||||
}
|
||||
|
||||
extension UnsafeMutableRawPointer {
|
||||
static func make(optional ptr: OpaquePointer?) -> UnsafeMutableRawPointer? {
|
||||
return ptr.map(UnsafeMutableRawPointer.init)
|
||||
}
|
||||
}
|
||||
|
||||
extension OpaquePointer {
|
||||
init(_ ptr: OpaquePointer) {
|
||||
self = ptr
|
||||
}
|
||||
|
||||
static func make(optional ptr: OpaquePointer?) -> OpaquePointer? {
|
||||
return ptr.map(OpaquePointer.init)
|
||||
}
|
||||
|
||||
static func make(optional ptr: UnsafeMutableRawPointer?) -> OpaquePointer? {
|
||||
return ptr.map(OpaquePointer.init)
|
||||
}
|
||||
|
||||
static func make<Pointee>(optional ptr: UnsafeMutablePointer<Pointee>?) -> OpaquePointer? {
|
||||
return ptr.map(OpaquePointer.init)
|
||||
}
|
||||
}
|
||||
288
Pods/BlueCryptor/Sources/Cryptor/Status.swift
generated
Executable file
288
Pods/BlueCryptor/Sources/Cryptor/Status.swift
generated
Executable file
@ -0,0 +1,288 @@
|
||||
//
|
||||
// Status.swift
|
||||
// Cryptor
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
import CommonCrypto
|
||||
#elseif os(Linux)
|
||||
import OpenSSL
|
||||
#endif
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
///
|
||||
/// Links the native CommonCryptoStatus enumeration to Swift versions.
|
||||
///
|
||||
public enum Status: CCCryptorStatus, Swift.Error, CustomStringConvertible {
|
||||
|
||||
/// Successful
|
||||
case success
|
||||
|
||||
/// Parameter Error
|
||||
case paramError
|
||||
|
||||
/// Buffer too Small
|
||||
case bufferTooSmall
|
||||
|
||||
/// Memory Failure
|
||||
case memoryFailure
|
||||
|
||||
/// Alignment Error
|
||||
case alignmentError
|
||||
|
||||
/// Decode Error
|
||||
case decodeError
|
||||
|
||||
/// Unimplemented
|
||||
case unimplemented
|
||||
|
||||
/// Overflow
|
||||
case overflow
|
||||
|
||||
/// Random Number Generator Err
|
||||
case rngFailure
|
||||
|
||||
///
|
||||
/// Converts this value to a native `CCCryptorStatus` value.
|
||||
///
|
||||
public func toRaw() -> CCCryptorStatus {
|
||||
|
||||
switch self {
|
||||
|
||||
case .success:
|
||||
return CCCryptorStatus(kCCSuccess)
|
||||
case .paramError:
|
||||
return CCCryptorStatus(kCCParamError)
|
||||
case .bufferTooSmall:
|
||||
return CCCryptorStatus(kCCBufferTooSmall)
|
||||
case .memoryFailure:
|
||||
return CCCryptorStatus(kCCMemoryFailure)
|
||||
case .alignmentError:
|
||||
return CCCryptorStatus(kCCAlignmentError)
|
||||
case .decodeError:
|
||||
return CCCryptorStatus(kCCDecodeError)
|
||||
case .unimplemented:
|
||||
return CCCryptorStatus(kCCUnimplemented)
|
||||
case .overflow:
|
||||
return CCCryptorStatus(kCCOverflow)
|
||||
case .rngFailure:
|
||||
return CCCryptorStatus(kCCRNGFailure)
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Human readable descriptions of the values. (Not needed in Swift 2.0?)
|
||||
///
|
||||
static let descriptions = [
|
||||
success: "Success",
|
||||
paramError: "ParamError",
|
||||
bufferTooSmall: "BufferTooSmall",
|
||||
memoryFailure: "MemoryFailure",
|
||||
alignmentError: "AlignmentError",
|
||||
decodeError: "DecodeError",
|
||||
unimplemented: "Unimplemented",
|
||||
overflow: "Overflow",
|
||||
rngFailure: "RNGFailure"
|
||||
]
|
||||
|
||||
///
|
||||
/// Obtain human-readable string from enum value.
|
||||
///
|
||||
public var description: String {
|
||||
|
||||
return (Status.descriptions[self] != nil) ? Status.descriptions[self]! : ""
|
||||
}
|
||||
|
||||
///
|
||||
/// Create enum value from raw `CCCryptorStatus` value.
|
||||
///
|
||||
public static func fromRaw(status: CCCryptorStatus) -> Status? {
|
||||
|
||||
let from = [
|
||||
kCCSuccess: success,
|
||||
kCCParamError: paramError,
|
||||
kCCBufferTooSmall: bufferTooSmall,
|
||||
kCCMemoryFailure: memoryFailure,
|
||||
kCCAlignmentError: alignmentError,
|
||||
kCCDecodeError: decodeError,
|
||||
kCCUnimplemented: unimplemented,
|
||||
kCCOverflow: overflow,
|
||||
kCCRNGFailure: rngFailure
|
||||
]
|
||||
|
||||
return from[Int(status)]
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#elseif os(Linux)
|
||||
|
||||
///
|
||||
/// Error status
|
||||
///
|
||||
public enum Status: Swift.Error, CustomStringConvertible {
|
||||
|
||||
/// Success
|
||||
case success
|
||||
|
||||
/// Unimplemented with reason
|
||||
case unimplemented(String)
|
||||
|
||||
/// Not supported with reason
|
||||
case notSupported(String)
|
||||
|
||||
/// Parameter Error
|
||||
case paramError
|
||||
|
||||
/// Failure with error code
|
||||
case fail(UInt)
|
||||
|
||||
/// Random Byte Generator Failure with error code
|
||||
case rngFailure(UInt)
|
||||
|
||||
/// The error code itself
|
||||
public var code: Int {
|
||||
|
||||
switch self {
|
||||
|
||||
case .success:
|
||||
return 0
|
||||
|
||||
case .notSupported:
|
||||
return -1
|
||||
|
||||
case .unimplemented:
|
||||
return -2
|
||||
|
||||
case .paramError:
|
||||
return -3
|
||||
|
||||
case .fail(let code):
|
||||
return Int(code)
|
||||
|
||||
case .rngFailure(let code):
|
||||
return Int(code)
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Create enum value from raw `SSL error code` value.
|
||||
///
|
||||
public static func fromRaw(status: UInt) -> Status? {
|
||||
|
||||
return Status.fail(status)
|
||||
}
|
||||
|
||||
///
|
||||
/// Obtain human-readable string for the error code.
|
||||
///
|
||||
public var description: String {
|
||||
|
||||
switch self {
|
||||
|
||||
case .success:
|
||||
return "No error"
|
||||
|
||||
case .notSupported(let reason):
|
||||
return "Not supported: \(reason)"
|
||||
|
||||
case .unimplemented(let reason):
|
||||
return "Not implemented: \(reason)"
|
||||
|
||||
case .paramError:
|
||||
return "Invalid parameters passed"
|
||||
|
||||
case .fail(let errorCode):
|
||||
return "ERROR: code: \(errorCode), reason: \(errToString(ERR_error_string(UInt(errorCode), nil)))"
|
||||
|
||||
case .rngFailure(let errorCode):
|
||||
return "Random Byte Generator ERROR: code: \(errorCode), reason: \(errToString(ERR_error_string(UInt(errorCode), nil)))"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Operators
|
||||
|
||||
func == (lhs: Status, rhs: Status) -> Bool {
|
||||
|
||||
return lhs.code == rhs.code
|
||||
}
|
||||
|
||||
func != (lhs: Status, rhs: Status) -> Bool {
|
||||
|
||||
return lhs.code != rhs.code
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
///
|
||||
/// CryptorError
|
||||
/// Thrown in caaes where a _fatalError()_ is **NOT** appropriate.
|
||||
///
|
||||
public enum CryptorError: Swift.Error, CustomStringConvertible {
|
||||
|
||||
/// Success
|
||||
case success
|
||||
|
||||
/// Invalid key size
|
||||
case invalidKeySize
|
||||
|
||||
/// Invalid IV size
|
||||
case invalidIVSizeOrLength
|
||||
|
||||
/// Fail with code and string
|
||||
case fail(Int32, String)
|
||||
|
||||
/// The error code itself
|
||||
public var errCode: Int32 {
|
||||
|
||||
switch self {
|
||||
|
||||
case .success:
|
||||
return 0
|
||||
|
||||
case .invalidKeySize:
|
||||
return -1
|
||||
|
||||
case .invalidIVSizeOrLength:
|
||||
return -2
|
||||
|
||||
case .fail(let errCode, _):
|
||||
return Int32(errCode)
|
||||
}
|
||||
}
|
||||
|
||||
/// Error Description
|
||||
public var description: String {
|
||||
|
||||
switch self {
|
||||
|
||||
case .success:
|
||||
return "Success"
|
||||
|
||||
case .invalidKeySize:
|
||||
return "Invalid key size."
|
||||
|
||||
case .invalidIVSizeOrLength:
|
||||
return "Invalid IV size or length."
|
||||
|
||||
case .fail(_, let reason):
|
||||
return reason
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
939
Pods/BlueCryptor/Sources/Cryptor/StreamCryptor.swift
generated
Executable file
939
Pods/BlueCryptor/Sources/Cryptor/StreamCryptor.swift
generated
Executable file
@ -0,0 +1,939 @@
|
||||
//
|
||||
// StreamCryptor.swift
|
||||
// Cryptor
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
import CommonCrypto
|
||||
#elseif os(Linux)
|
||||
import OpenSSL
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Encrypts or decrypts return results as they become available.
|
||||
///
|
||||
/// - Note: The underlying cipher may be a block or a stream cipher.
|
||||
///
|
||||
/// Use for large files or network streams.
|
||||
///
|
||||
/// For small, in-memory buffers Cryptor may be easier to use.
|
||||
///
|
||||
public class StreamCryptor {
|
||||
|
||||
#if os(Linux)
|
||||
|
||||
//
|
||||
// Key sizes
|
||||
//
|
||||
static let kCCKeySizeAES128 = 16
|
||||
static let kCCKeySizeAES192 = 24
|
||||
static let kCCKeySizeAES256 = 32
|
||||
static let kCCKeySizeDES = 8
|
||||
static let kCCKeySize3DES = 24
|
||||
static let kCCKeySizeMinCAST = 5
|
||||
static let kCCKeySizeMaxCAST = 16
|
||||
static let kCCKeySizeMinRC2 = 1
|
||||
static let kCCKeySizeMaxRC2 = 128
|
||||
static let kCCKeySizeMinBlowfish = 8
|
||||
static let kCCKeySizeMaxBlowfish = 56
|
||||
|
||||
//
|
||||
// Block sizes
|
||||
//
|
||||
static let kCCBlockSizeAES128 = 16
|
||||
static let kCCBlockSizeDES = 8
|
||||
static let kCCBlockSize3DES = 8
|
||||
static let kCCBlockSizeCAST = 8
|
||||
static let kCCBlockSizeRC2 = 8
|
||||
static let kCCBlockSizeBlowfish = 8
|
||||
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Enumerates Cryptor operations
|
||||
///
|
||||
public enum Operation {
|
||||
|
||||
/// Encrypting
|
||||
case encrypt
|
||||
|
||||
/// Decrypting
|
||||
case decrypt
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
|
||||
/// Convert to native `CCOperation`
|
||||
func nativeValue() -> CCOperation {
|
||||
|
||||
switch self {
|
||||
|
||||
case .encrypt:
|
||||
return CCOperation(kCCEncrypt)
|
||||
|
||||
case .decrypt:
|
||||
return CCOperation(kCCDecrypt)
|
||||
}
|
||||
}
|
||||
|
||||
#elseif os(Linux)
|
||||
|
||||
/// Convert to native value
|
||||
func nativeValue() -> UInt32 {
|
||||
|
||||
switch self {
|
||||
|
||||
case .encrypt:
|
||||
return 0
|
||||
|
||||
case .decrypt:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
///
|
||||
/// Enumerates valid key sizes.
|
||||
///
|
||||
public enum ValidKeySize {
|
||||
|
||||
case fixed(Int)
|
||||
case discrete([Int])
|
||||
case range(Int, Int)
|
||||
|
||||
///
|
||||
/// Determines if a given `keySize` is valid for this algorithm.
|
||||
///
|
||||
/// - Parameter keySize: The size to test for validity.
|
||||
///
|
||||
/// - Returns: True if valid, false otherwise.
|
||||
///
|
||||
func isValidKeySize(keySize: Int) -> Bool {
|
||||
|
||||
switch self {
|
||||
|
||||
case .fixed(let fixed):
|
||||
return (fixed == keySize)
|
||||
|
||||
case .range(let min, let max):
|
||||
return ((keySize >= min) && (keySize <= max))
|
||||
|
||||
case .discrete(let values):
|
||||
return values.contains(keySize)
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Determines the next valid key size; that is, the first valid key size larger
|
||||
/// than the given value.
|
||||
///
|
||||
/// - Parameter keySize: The size for which the `next` size is desired.
|
||||
///
|
||||
/// - Returns: Will return `nil` if the passed in `keySize` is greater than the max.
|
||||
///
|
||||
func paddedKeySize(keySize: Int) -> Int? {
|
||||
|
||||
switch self {
|
||||
|
||||
case .fixed(let fixed):
|
||||
return (keySize <= fixed) ? fixed : nil
|
||||
|
||||
case .range(let min, let max):
|
||||
return (keySize > max) ? nil : ((keySize < min) ? min : keySize)
|
||||
|
||||
case .discrete(let values):
|
||||
return values.sorted().reduce(nil) { answer, current in
|
||||
return answer ?? ((current >= keySize) ? current : nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
///
|
||||
/// Maps CommonCryptoOptions onto a Swift struct.
|
||||
///
|
||||
public struct Options: OptionSet {
|
||||
|
||||
public typealias RawValue = Int
|
||||
public let rawValue: RawValue
|
||||
|
||||
/// Convert from a native value (i.e. `0`, `kCCOptionpkcs7Padding`, `kCCOptionECBMode`)
|
||||
public init(rawValue: RawValue) {
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
|
||||
/// Convert from a native value (i.e. `0`, `kCCOptionpkcs7Padding`, `kCCOptionECBMode`)
|
||||
public init(_ rawValue: RawValue) {
|
||||
self.init(rawValue: rawValue)
|
||||
}
|
||||
|
||||
/// No options
|
||||
public static let none = Options(rawValue: 0)
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
|
||||
/// Use padding. Needed unless the input is a integral number of blocks long.
|
||||
public static var pkcs7Padding = Options(rawValue:kCCOptionPKCS7Padding)
|
||||
|
||||
/// Electronic Code Book Mode. Don't use this.
|
||||
public static var ecbMode = Options(rawValue:kCCOptionECBMode)
|
||||
|
||||
#elseif os(Linux)
|
||||
|
||||
/// Use padding. Needed unless the input is a integral number of blocks long.
|
||||
public static var pkcs7Padding = Options(rawValue:0x0001)
|
||||
|
||||
/// Electronic Code Book Mode. Don't use this.
|
||||
public static var ecbMode = Options(rawValue:0x0002)
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
///
|
||||
/// Enumerates available algorithms
|
||||
///
|
||||
public enum Algorithm {
|
||||
|
||||
/// Advanced Encryption Standard
|
||||
/// - Note: aes and aes128 are equivalent.
|
||||
case aes, aes128, aes192, aes256
|
||||
|
||||
/// Data Encryption Standard
|
||||
case des
|
||||
|
||||
/// Triple des
|
||||
case tripleDes
|
||||
|
||||
/// cast
|
||||
case cast
|
||||
|
||||
/// rc2
|
||||
case rc2
|
||||
|
||||
/// blowfish
|
||||
case blowfish
|
||||
|
||||
/// Blocksize, in bytes, of algorithm.
|
||||
public var blockSize: Int {
|
||||
|
||||
switch self {
|
||||
|
||||
case .aes, .aes128, .aes192, .aes256:
|
||||
return kCCBlockSizeAES128
|
||||
|
||||
case .des:
|
||||
return kCCBlockSizeDES
|
||||
|
||||
case .tripleDes:
|
||||
return kCCBlockSize3DES
|
||||
|
||||
case .cast:
|
||||
return kCCBlockSizeCAST
|
||||
|
||||
case .rc2:
|
||||
return kCCBlockSizeRC2
|
||||
|
||||
case .blowfish:
|
||||
return kCCBlockSizeBlowfish
|
||||
}
|
||||
}
|
||||
|
||||
public var defaultKeySize: Int {
|
||||
|
||||
switch self {
|
||||
|
||||
case .aes, .aes128:
|
||||
return kCCKeySizeAES128
|
||||
|
||||
case .aes192:
|
||||
return kCCKeySizeAES192
|
||||
|
||||
case .aes256:
|
||||
return kCCKeySizeAES256
|
||||
|
||||
case .des:
|
||||
return kCCKeySizeDES
|
||||
|
||||
case .tripleDes:
|
||||
return kCCKeySize3DES
|
||||
|
||||
case .cast:
|
||||
return kCCKeySizeMinCAST
|
||||
|
||||
case .rc2:
|
||||
return kCCKeySizeMinRC2
|
||||
|
||||
case .blowfish:
|
||||
return kCCKeySizeMinBlowfish
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
|
||||
/// Native, CommonCrypto constant for algorithm.
|
||||
func nativeValue() -> CCAlgorithm {
|
||||
|
||||
switch self {
|
||||
|
||||
case .aes, .aes128, .aes192, .aes256:
|
||||
return CCAlgorithm(kCCAlgorithmAES)
|
||||
|
||||
case .des:
|
||||
return CCAlgorithm(kCCAlgorithmDES)
|
||||
|
||||
case .tripleDes:
|
||||
return CCAlgorithm(kCCAlgorithm3DES)
|
||||
|
||||
case .cast:
|
||||
return CCAlgorithm(kCCAlgorithmCAST)
|
||||
|
||||
case .rc2:
|
||||
return CCAlgorithm(kCCAlgorithmRC2)
|
||||
|
||||
case .blowfish:
|
||||
return CCAlgorithm(kCCAlgorithmBlowfish)
|
||||
}
|
||||
}
|
||||
|
||||
#elseif os(Linux)
|
||||
|
||||
/// Native, OpenSSL function for algorithm.
|
||||
func nativeValue(options: Options) -> OpaquePointer? {
|
||||
|
||||
if options == .pkcs7Padding || options == .none {
|
||||
|
||||
switch self {
|
||||
|
||||
case .aes, .aes128:
|
||||
return .init(EVP_aes_128_cbc())
|
||||
|
||||
case .aes192:
|
||||
return .init(EVP_aes_192_cbc())
|
||||
|
||||
case .aes256:
|
||||
return .init(EVP_aes_256_cbc())
|
||||
|
||||
case .des:
|
||||
return .init(EVP_des_cbc())
|
||||
|
||||
case .tripleDes:
|
||||
return .init(EVP_des_ede3_cbc())
|
||||
|
||||
case .cast:
|
||||
return .init(EVP_cast5_cbc())
|
||||
|
||||
case .rc2:
|
||||
return .init(EVP_rc2_cbc())
|
||||
|
||||
case .blowfish:
|
||||
return .init(EVP_bf_cbc())
|
||||
}
|
||||
}
|
||||
|
||||
if options == .ecbMode {
|
||||
|
||||
switch self {
|
||||
|
||||
case .aes, .aes128:
|
||||
return .init(EVP_aes_128_ecb())
|
||||
|
||||
case .aes192:
|
||||
return .init(EVP_aes_192_ecb())
|
||||
|
||||
case .aes256:
|
||||
return .init(EVP_aes_256_ecb())
|
||||
|
||||
case .des:
|
||||
return .init(EVP_des_ecb())
|
||||
|
||||
case .tripleDes:
|
||||
return .init(EVP_des_ede3_ecb())
|
||||
|
||||
case .cast:
|
||||
return .init(EVP_cast5_ecb())
|
||||
|
||||
case .rc2:
|
||||
return .init(EVP_rc2_ecb())
|
||||
|
||||
case .blowfish:
|
||||
return .init(EVP_bf_ecb())
|
||||
}
|
||||
}
|
||||
|
||||
fatalError("Unsupported options and/or algorithm.")
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Determines the valid key size for this algorithm
|
||||
///
|
||||
/// - Returns: Valid key size for this algorithm.
|
||||
///
|
||||
func validKeySize() -> ValidKeySize {
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
|
||||
switch self {
|
||||
|
||||
case .aes, .aes128, .aes192, .aes256:
|
||||
return .discrete([kCCKeySizeAES128, kCCKeySizeAES192, kCCKeySizeAES256])
|
||||
|
||||
case .des:
|
||||
return .fixed(kCCKeySizeDES)
|
||||
|
||||
case .tripleDes:
|
||||
return .fixed(kCCKeySize3DES)
|
||||
|
||||
case .cast:
|
||||
return .range(kCCKeySizeMinCAST, kCCKeySizeMaxCAST)
|
||||
|
||||
case .rc2:
|
||||
return .range(kCCKeySizeMinRC2, kCCKeySizeMaxRC2)
|
||||
|
||||
case .blowfish:
|
||||
return .range(kCCKeySizeMinBlowfish, kCCKeySizeMaxBlowfish)
|
||||
}
|
||||
|
||||
#elseif os(Linux)
|
||||
|
||||
switch self {
|
||||
|
||||
case .aes, .aes128:
|
||||
return .fixed(kCCKeySizeAES128)
|
||||
|
||||
case .aes192:
|
||||
return .fixed(kCCKeySizeAES192)
|
||||
|
||||
case .aes256:
|
||||
return .fixed(kCCKeySizeAES256)
|
||||
|
||||
case .des:
|
||||
return .fixed(kCCKeySizeDES)
|
||||
|
||||
case .tripleDes:
|
||||
return .fixed(kCCKeySize3DES)
|
||||
|
||||
case .cast:
|
||||
return .range(kCCKeySizeMinCAST, kCCKeySizeMaxCAST)
|
||||
|
||||
case .rc2:
|
||||
return .range(kCCKeySizeMinRC2, kCCKeySizeMaxRC2)
|
||||
|
||||
case .blowfish:
|
||||
return .range(kCCKeySizeMinBlowfish, kCCKeySizeMaxBlowfish)
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
///
|
||||
/// Tests if a given keySize is valid for this algorithm
|
||||
///
|
||||
/// - Parameter keySize: The key size to be validated.
|
||||
///
|
||||
/// - Returns: True if valid, false otherwise.
|
||||
///
|
||||
func isValidKeySize(keySize: Int) -> Bool {
|
||||
return self.validKeySize().isValidKeySize(keySize: keySize)
|
||||
}
|
||||
|
||||
///
|
||||
/// Calculates the next, if any, valid keySize greater or equal to a given `keySize` for this algorithm
|
||||
///
|
||||
/// - Parameter keySize: Key size for which the next size is requested.
|
||||
///
|
||||
/// - Returns: Next key size or nil
|
||||
///
|
||||
func paddedKeySize(keySize: Int) -> Int? {
|
||||
return self.validKeySize().paddedKeySize(keySize: keySize)
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// The status code resulting from the last method call to this Cryptor.
|
||||
/// Used to get additional information when optional chaining collapes.
|
||||
///
|
||||
public internal(set) var status: Status = .success
|
||||
|
||||
///
|
||||
/// Context obtained. True if we have it, false otherwise.
|
||||
///
|
||||
private var haveContext: Bool = false
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
|
||||
/// CommonCrypto Context
|
||||
private var context = UnsafeMutablePointer<CCCryptorRef?>.allocate(capacity: 1)
|
||||
|
||||
#elseif os(Linux)
|
||||
|
||||
/// OpenSSL Cipher Context
|
||||
private let context: OpaquePointer? = .init(EVP_CIPHER_CTX_new())
|
||||
|
||||
/// Operation
|
||||
private var operation: Operation = .encrypt
|
||||
|
||||
/// The algorithm
|
||||
private var algorithm: Algorithm
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// MARK: Lifecycle Methods
|
||||
|
||||
///
|
||||
/// Default Initializer
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - operation: The operation to perform see Operation (Encrypt, Decrypt)
|
||||
/// - algorithm: The algorithm to use see Algorithm (AES, des, tripleDes, cast, rc2, blowfish)
|
||||
/// - keyBuffer: Pointer to key buffer
|
||||
/// - keyByteCount: Number of bytes in the key
|
||||
/// - ivBuffer: Initialization vector buffer
|
||||
/// - ivLength: Length of the ivBuffer
|
||||
///
|
||||
/// - Returns: New StreamCryptor instance.
|
||||
///
|
||||
public init(operation: Operation, algorithm: Algorithm, options: Options, keyBuffer: [UInt8], keyByteCount: Int, ivBuffer: UnsafePointer<UInt8>, ivLength: Int = 0) throws {
|
||||
|
||||
guard algorithm.isValidKeySize(keySize: keyByteCount) else {
|
||||
throw CryptorError.invalidKeySize
|
||||
}
|
||||
|
||||
guard options.contains(.ecbMode) || ivLength == algorithm.blockSize else {
|
||||
throw CryptorError.invalidIVSizeOrLength
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
|
||||
let rawStatus = CCCryptorCreate(operation.nativeValue(), algorithm.nativeValue(), CCOptions(options.rawValue), keyBuffer, keyByteCount, ivBuffer, self.context)
|
||||
|
||||
if let status = Status.fromRaw(status: rawStatus) {
|
||||
|
||||
self.status = status
|
||||
|
||||
} else {
|
||||
|
||||
throw CryptorError.fail(rawStatus, "Cryptor init returned unexpected status.")
|
||||
}
|
||||
|
||||
self.haveContext = true
|
||||
|
||||
#elseif os(Linux)
|
||||
|
||||
self.algorithm = algorithm
|
||||
self.operation = operation
|
||||
|
||||
var rawStatus: Int32
|
||||
|
||||
switch self.operation {
|
||||
|
||||
case .encrypt:
|
||||
rawStatus = EVP_EncryptInit_ex(.make(optional: self.context), .make(optional: algorithm.nativeValue(options: options)), nil, keyBuffer, ivBuffer)
|
||||
|
||||
case .decrypt:
|
||||
rawStatus = EVP_DecryptInit_ex(.make(optional: self.context), .make(optional: algorithm.nativeValue(options: options)), nil, keyBuffer, ivBuffer)
|
||||
}
|
||||
|
||||
if rawStatus == 0 {
|
||||
|
||||
let errorCode = ERR_get_error()
|
||||
if let status = Status.fromRaw(status: errorCode) {
|
||||
self.status = status
|
||||
} else {
|
||||
|
||||
throw CryptorError.fail(Int32(errorCode), "Cryptor init returned unexpected status.")
|
||||
}
|
||||
}
|
||||
|
||||
self.haveContext = true
|
||||
|
||||
// Default to no padding...
|
||||
var needPadding: Int32 = 0
|
||||
if options == .pkcs7Padding {
|
||||
needPadding = 1
|
||||
}
|
||||
|
||||
// Note: This call must be AFTER the init call above...
|
||||
EVP_CIPHER_CTX_set_padding(.make(optional: self.context), needPadding)
|
||||
|
||||
self.status = Status.success
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
///
|
||||
/// Creates a new StreamCryptor
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - operation: The operation to perform see Operation (Encrypt, Decrypt)
|
||||
/// - algorithm: The algorithm to use see Algorithm (AES, des, tripleDes, cast, rc2, blowfish)
|
||||
/// - key: A byte array containing key data
|
||||
/// - iv: A byte array containing initialization vector
|
||||
///
|
||||
/// - Returns: New StreamCryptor instance.
|
||||
///
|
||||
public convenience init(operation: Operation, algorithm: Algorithm, options: Options, key: [UInt8], iv: [UInt8]) throws {
|
||||
|
||||
guard let paddedKeySize = algorithm.paddedKeySize(keySize: key.count) else {
|
||||
throw CryptorError.invalidKeySize
|
||||
}
|
||||
|
||||
try self.init(operation:operation,
|
||||
algorithm:algorithm,
|
||||
options:options,
|
||||
keyBuffer:CryptoUtils.zeroPad(byteArray:key, blockSize: paddedKeySize),
|
||||
keyByteCount:paddedKeySize,
|
||||
ivBuffer:iv,
|
||||
ivLength:iv.count)
|
||||
}
|
||||
|
||||
///
|
||||
/// Creates a new StreamCryptor
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - operation: The operation to perform see Operation (Encrypt, Decrypt)
|
||||
/// - algorithm: The algorithm to use see Algorithm (AES, des, tripleDes, cast, rc2, blowfish)
|
||||
/// - key: A string containing key data (will be interpreted as UTF8)
|
||||
/// - iv: A string containing initialization vector data (will be interpreted as UTF8)
|
||||
///
|
||||
/// - Returns: New StreamCryptor instance.
|
||||
///
|
||||
public convenience init(operation: Operation, algorithm: Algorithm, options: Options, key: String, iv: String) throws {
|
||||
|
||||
let keySize = key.utf8.count
|
||||
guard let paddedKeySize = algorithm.paddedKeySize(keySize: keySize) else {
|
||||
throw CryptorError.invalidKeySize
|
||||
}
|
||||
|
||||
try self.init(operation:operation,
|
||||
algorithm:algorithm,
|
||||
options:options,
|
||||
keyBuffer:CryptoUtils.zeroPad(string: key, blockSize: paddedKeySize),
|
||||
keyByteCount:paddedKeySize,
|
||||
ivBuffer:iv,
|
||||
ivLength:iv.utf8.count)
|
||||
}
|
||||
|
||||
///
|
||||
/// Cleanup
|
||||
///
|
||||
deinit {
|
||||
|
||||
// Ensure we've got a context before attempting to get rid of it...
|
||||
if self.haveContext == false {
|
||||
return
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
|
||||
// Ensure we've got a context before attempting to get rid of it...
|
||||
if self.context.pointee == nil {
|
||||
return
|
||||
}
|
||||
|
||||
let rawStatus = CCCryptorRelease(self.context.pointee)
|
||||
if let status = Status.fromRaw(status: rawStatus) {
|
||||
|
||||
if status != .success {
|
||||
|
||||
NSLog("WARNING: CCCryptoRelease failed with status \(rawStatus).")
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
fatalError("CCCryptorUpdate returned unexpected status.")
|
||||
}
|
||||
|
||||
#if swift(>=4.1)
|
||||
context.deallocate()
|
||||
#else
|
||||
context.deallocate(capacity: 1)
|
||||
#endif
|
||||
|
||||
self.haveContext = false
|
||||
|
||||
#elseif os(Linux)
|
||||
|
||||
EVP_CIPHER_CTX_free(.make(optional: self.context))
|
||||
self.haveContext = false
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// MARK: Public Methods
|
||||
|
||||
///
|
||||
/// Add the contents of an Data buffer to the current encryption/decryption operation.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - dataIn: The input data
|
||||
/// - byteArrayOut: Output data
|
||||
///
|
||||
/// - Returns: A tuple containing the number of output bytes produced and the status (see Status)
|
||||
///
|
||||
public func update(dataIn: Data, byteArrayOut: inout [UInt8]) -> (Int, Status) {
|
||||
|
||||
let dataOutAvailable = byteArrayOut.count
|
||||
var dataOutMoved = 0
|
||||
#if swift(>=5.0)
|
||||
dataIn.withUnsafeBytes() {
|
||||
_ = update(bufferIn: $0.baseAddress!, byteCountIn: dataIn.count, bufferOut: &byteArrayOut, byteCapacityOut: dataOutAvailable, byteCountOut: &dataOutMoved)
|
||||
}
|
||||
#else
|
||||
dataIn.withUnsafeBytes() { (buffer: UnsafePointer<UInt8>) in
|
||||
_ = update(bufferIn: buffer, byteCountIn: dataIn.count, bufferOut: &byteArrayOut, byteCapacityOut: dataOutAvailable, byteCountOut: &dataOutMoved)
|
||||
}
|
||||
#endif
|
||||
return (dataOutMoved, self.status)
|
||||
}
|
||||
|
||||
///
|
||||
/// Add the contents of an NSData buffer to the current encryption/decryption operation.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - dataIn: The input data
|
||||
/// - byteArrayOut: Output data
|
||||
///
|
||||
/// - Returns: A tuple containing the number of output bytes produced and the status (see Status)
|
||||
///
|
||||
public func update(dataIn: NSData, byteArrayOut: inout [UInt8]) -> (Int, Status) {
|
||||
|
||||
let dataOutAvailable = byteArrayOut.count
|
||||
var dataOutMoved = 0
|
||||
var ptr = dataIn.bytes.assumingMemoryBound(to: UInt8.self).pointee
|
||||
_ = update(bufferIn: &ptr, byteCountIn: dataIn.length, bufferOut: &byteArrayOut, byteCapacityOut: dataOutAvailable, byteCountOut: &dataOutMoved)
|
||||
return (dataOutMoved, self.status)
|
||||
}
|
||||
|
||||
///
|
||||
/// Add the contents of a byte array to the current encryption/decryption operation.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - byteArrayIn: The input data
|
||||
/// - byteArrayOut: Output data
|
||||
///
|
||||
/// - Returns: A tuple containing the number of output bytes produced and the status (see Status)
|
||||
///
|
||||
public func update(byteArrayIn: [UInt8], byteArrayOut: inout [UInt8]) -> (Int, Status) {
|
||||
|
||||
let dataOutAvailable = byteArrayOut.count
|
||||
var dataOutMoved = 0
|
||||
_ = update(bufferIn: byteArrayIn, byteCountIn: byteArrayIn.count, bufferOut: &byteArrayOut, byteCapacityOut: dataOutAvailable, byteCountOut: &dataOutMoved)
|
||||
return (dataOutMoved, self.status)
|
||||
}
|
||||
|
||||
///
|
||||
/// Add the contents of a string (interpreted as UTF8) to the current encryption/decryption operation.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - byteArrayIn: The input data
|
||||
/// - byteArrayOut: Output data
|
||||
///
|
||||
/// - Returns: A tuple containing the number of output bytes produced and the status (see Status)
|
||||
///
|
||||
public func update(stringIn: String, byteArrayOut: inout [UInt8]) -> (Int, Status) {
|
||||
|
||||
let dataOutAvailable = byteArrayOut.count
|
||||
var dataOutMoved = 0
|
||||
_ = update(bufferIn: stringIn, byteCountIn: stringIn.utf8.count, bufferOut: &byteArrayOut, byteCapacityOut: dataOutAvailable, byteCountOut: &dataOutMoved)
|
||||
return (dataOutMoved, self.status)
|
||||
}
|
||||
|
||||
///
|
||||
/// Retrieves all remaining encrypted or decrypted data from this cryptor.
|
||||
///
|
||||
/// - Note: If the underlying algorithm is an block cipher and the padding option has
|
||||
/// not been specified and the cumulative input to the cryptor has not been an integral
|
||||
/// multiple of the block length this will fail with an alignment error.
|
||||
///
|
||||
/// - Note: This method updates the status property
|
||||
///
|
||||
/// - Parameter byteArrayOut: The output bffer
|
||||
///
|
||||
/// - Returns: a tuple containing the number of output bytes produced and the status (see Status)
|
||||
///
|
||||
public func final(byteArrayOut: inout [UInt8]) -> (Int, Status) {
|
||||
|
||||
let dataOutAvailable = byteArrayOut.count
|
||||
var dataOutMoved = 0
|
||||
_ = final(bufferOut: &byteArrayOut, byteCapacityOut: dataOutAvailable, byteCountOut: &dataOutMoved)
|
||||
return (dataOutMoved, self.status)
|
||||
}
|
||||
|
||||
// MARK: - Low-level interface
|
||||
|
||||
///
|
||||
/// Update the buffer
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - bufferIn: Pointer to input buffer
|
||||
/// - inByteCount: Number of bytes contained in input buffer
|
||||
/// - bufferOut: Pointer to output buffer
|
||||
/// - outByteCapacity: Capacity of the output buffer in bytes
|
||||
/// - outByteCount: On successful completion, the number of bytes written to the output buffer
|
||||
///
|
||||
/// - Returns: Status of the update
|
||||
///
|
||||
public func update(bufferIn: UnsafeRawPointer, byteCountIn: Int, bufferOut: UnsafeMutablePointer<UInt8>, byteCapacityOut: Int, byteCountOut: inout Int) -> Status {
|
||||
|
||||
if self.status == .success {
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
|
||||
let rawStatus = CCCryptorUpdate(self.context.pointee, bufferIn, byteCountIn, bufferOut, byteCapacityOut, &byteCountOut)
|
||||
if let status = Status.fromRaw(status: rawStatus) {
|
||||
self.status = status
|
||||
} else {
|
||||
fatalError("CCCryptorUpdate returned unexpected status.")
|
||||
}
|
||||
|
||||
#elseif os(Linux)
|
||||
|
||||
var rawStatus: Int32
|
||||
var outLength: Int32 = 0
|
||||
|
||||
switch self.operation {
|
||||
|
||||
case .encrypt:
|
||||
rawStatus = EVP_EncryptUpdate(.make(optional: self.context), bufferOut, &outLength, bufferIn.assumingMemoryBound(to: UInt8.self), Int32(byteCountIn))
|
||||
|
||||
case .decrypt:
|
||||
rawStatus = EVP_DecryptUpdate(.make(optional: self.context), bufferOut, &outLength, bufferIn.assumingMemoryBound(to: UInt8.self), Int32(byteCountIn))
|
||||
}
|
||||
|
||||
byteCountOut = Int(outLength)
|
||||
|
||||
if rawStatus == 0 {
|
||||
|
||||
let errorCode = ERR_get_error()
|
||||
if let status = Status.fromRaw(status: errorCode) {
|
||||
self.status = status
|
||||
} else {
|
||||
fatalError("Cryptor update returned unexpected status.")
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
self.status = Status.success
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return self.status
|
||||
}
|
||||
|
||||
///
|
||||
/// Retrieves all remaining encrypted or decrypted data from this cryptor.
|
||||
///
|
||||
/// - Note: If the underlying algorithm is an block cipher and the padding option has
|
||||
/// not been specified and the cumulative input to the cryptor has not been an integral
|
||||
/// multiple of the block length this will fail with an alignment error.
|
||||
///
|
||||
/// - Note: This method updates the status property
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - bufferOut: Pointer to output buffer
|
||||
/// - outByteCapacity: Capacity of the output buffer in bytes
|
||||
/// - outByteCount: On successful completion, the number of bytes written to the output buffer
|
||||
///
|
||||
/// - Returns: Status of the update
|
||||
///
|
||||
public func final(bufferOut: UnsafeMutablePointer<UInt8>, byteCapacityOut: Int, byteCountOut: inout Int) -> Status {
|
||||
|
||||
if self.status == Status.success {
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
|
||||
let rawStatus = CCCryptorFinal(self.context.pointee, bufferOut, byteCapacityOut, &byteCountOut)
|
||||
if let status = Status.fromRaw(status: rawStatus) {
|
||||
self.status = status
|
||||
} else {
|
||||
fatalError("CCCryptorUpdate returned unexpected status.")
|
||||
}
|
||||
|
||||
#elseif os(Linux)
|
||||
|
||||
var rawStatus: Int32
|
||||
var outLength: Int32 = Int32(byteCapacityOut)
|
||||
|
||||
switch self.operation {
|
||||
|
||||
case .encrypt:
|
||||
rawStatus = EVP_EncryptFinal_ex(.make(optional: self.context), bufferOut, &outLength)
|
||||
|
||||
case .decrypt:
|
||||
rawStatus = EVP_DecryptFinal_ex(.make(optional: self.context), bufferOut, &outLength)
|
||||
}
|
||||
|
||||
byteCountOut = Int(outLength)
|
||||
|
||||
if rawStatus == 0 {
|
||||
|
||||
let errorCode = ERR_get_error()
|
||||
if let status = Status.fromRaw(status: errorCode) {
|
||||
self.status = status
|
||||
} else {
|
||||
fatalError("Cryptor final returned unexpected status.")
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
self.status = Status.success
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
return self.status
|
||||
}
|
||||
|
||||
///
|
||||
/// Determines the number of bytes that will be output by this Cryptor if inputBytes of additional
|
||||
/// data is input.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - inputByteCount: Number of bytes that will be input.
|
||||
/// - isFinal: True if buffer to be input will be the last input buffer, false otherwise.
|
||||
///
|
||||
/// - Returns: The final output length
|
||||
///
|
||||
public func getOutputLength(inputByteCount: Int, isFinal: Bool = false) -> Int {
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
|
||||
return CCCryptorGetOutputLength(self.context.pointee, inputByteCount, isFinal)
|
||||
|
||||
#elseif os(Linux)
|
||||
|
||||
if inputByteCount == 0 {
|
||||
return self.algorithm.blockSize
|
||||
}
|
||||
|
||||
return (inputByteCount + self.algorithm.blockSize - (inputByteCount % self.algorithm.blockSize))
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
107
Pods/BlueCryptor/Sources/Cryptor/Updatable.swift
generated
Executable file
107
Pods/BlueCryptor/Sources/Cryptor/Updatable.swift
generated
Executable file
@ -0,0 +1,107 @@
|
||||
//
|
||||
// Updateable.swift
|
||||
// Cryptor
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
///
|
||||
/// A protocol for calculations that can be updated with incremental data buffers.
|
||||
///
|
||||
public protocol Updatable {
|
||||
|
||||
/// Status of the calculation.
|
||||
var status: Status { get }
|
||||
|
||||
///
|
||||
/// Low-level update routine.
|
||||
/// Updates the calculation with the contents of a data buffer.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - buffer: Pointer to the data buffer
|
||||
/// - byteCount: Length of the buffer in bytes
|
||||
///
|
||||
/// - Returns: `Self` if no error for optional chaining, nil otherwise
|
||||
///
|
||||
func update(from buffer: UnsafeRawPointer, byteCount: size_t) -> Self?
|
||||
}
|
||||
|
||||
///
|
||||
/// Factors out common update code from Digest, HMAC and Cryptor.
|
||||
///
|
||||
extension Updatable {
|
||||
///
|
||||
/// Updates the current calculation with data contained in an `NSData` object.
|
||||
///
|
||||
/// - Parameter data: The `NSData` object
|
||||
///
|
||||
/// - Returns: Optional `Self` or nil
|
||||
///
|
||||
public func update(data: NSData) -> Self? {
|
||||
|
||||
_ = update(from: data.bytes, byteCount: size_t(data.length))
|
||||
return self.status == .success ? self : nil
|
||||
}
|
||||
|
||||
///
|
||||
/// Updates the current calculation with data contained in an `Data` object.
|
||||
///
|
||||
/// - Parameters data: The `Data` object
|
||||
///
|
||||
/// - Returns: Optional `Self` or nil
|
||||
///
|
||||
public func update(data: Data) -> Self? {
|
||||
|
||||
#if swift(>=5.0)
|
||||
_ = data.withUnsafeBytes() {
|
||||
|
||||
_ = update(from: $0.baseAddress!, byteCount: size_t(data.count))
|
||||
}
|
||||
#else
|
||||
_ = data.withUnsafeBytes() { (buffer: UnsafePointer<UInt8>) in
|
||||
|
||||
_ = update(from: buffer, byteCount: size_t(data.count))
|
||||
}
|
||||
#endif
|
||||
return self.status == .success ? self : nil
|
||||
}
|
||||
|
||||
///
|
||||
/// Updates the current calculation with data contained in a byte array.
|
||||
///
|
||||
/// - Parameter byteArray: The byte array
|
||||
///
|
||||
/// - Returns: Optional `Self` or nil
|
||||
///
|
||||
public func update(byteArray: [UInt8]) -> Self? {
|
||||
|
||||
_ = update(from: byteArray, byteCount: size_t(byteArray.count))
|
||||
return self.status == .success ? self : nil
|
||||
}
|
||||
|
||||
///
|
||||
/// Updates the current calculation with data contained in a String.
|
||||
/// The corresponding data will be generated using UTF8 encoding.
|
||||
///
|
||||
/// - Parameter string: The string of data
|
||||
///
|
||||
/// - Returns: Optional `Self` or nil
|
||||
///
|
||||
public func update(string: String) -> Self? {
|
||||
|
||||
_ = update(from: string, byteCount: size_t(string.utf8.count))
|
||||
return self.status == .success ? self : nil
|
||||
}
|
||||
}
|
||||
262
Pods/BlueCryptor/Sources/Cryptor/Utilities.swift
generated
Executable file
262
Pods/BlueCryptor/Sources/Cryptor/Utilities.swift
generated
Executable file
@ -0,0 +1,262 @@
|
||||
//
|
||||
// Utilities.swift
|
||||
// Cryptor
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
//
|
||||
// Replaces Swift's native `fatalError` function to allow redirection
|
||||
// For more details about how this all works see:
|
||||
// https://marcosantadev.com/test-swift-fatalerror/
|
||||
//
|
||||
func fatalError(_ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) -> Never {
|
||||
|
||||
FatalErrorUtil.fatalErrorClosure(message(), file, line)
|
||||
}
|
||||
|
||||
// Convert an UnsafeMutablePointer<Int8>? to a String, providing a
|
||||
// default value of empty string if the pointer is nil.
|
||||
//
|
||||
// - Parameter ptr: Pointer to string to be converted.
|
||||
//
|
||||
// - Returns: Converted string.
|
||||
//
|
||||
func errToString(_ ptr: UnsafeMutablePointer<Int8>?) -> String {
|
||||
if let ptr = ptr {
|
||||
return String(cString: ptr)
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Allows redirection of `fatalError` for Unit Testing or for
|
||||
/// library users that want to handle such errors in another way.
|
||||
///
|
||||
struct FatalErrorUtil {
|
||||
|
||||
static var fatalErrorClosure: (String, StaticString, UInt) -> Never = defaultFatalErrorClosure
|
||||
private static let defaultFatalErrorClosure = { Swift.fatalError($0, file: $1, line: $2) }
|
||||
static func replaceFatalError(closure: @escaping (String, StaticString, UInt) -> Never) {
|
||||
fatalErrorClosure = closure
|
||||
}
|
||||
static func restoreFatalError() {
|
||||
fatalErrorClosure = defaultFatalErrorClosure
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///
|
||||
/// Various utility functions for conversions
|
||||
///
|
||||
public struct CryptoUtils {
|
||||
|
||||
///
|
||||
/// Converts a single hexadecimal digit encoded as a Unicode Scalar to it's corresponding value.
|
||||
///
|
||||
/// - Parameter digit: A Unicode scalar in the set 0..9a..fA..F
|
||||
///
|
||||
/// - Returns: The hexadecimal value of the digit
|
||||
///
|
||||
static func convert(hexDigit digit: UnicodeScalar) -> UInt8? {
|
||||
|
||||
switch digit {
|
||||
|
||||
case UnicodeScalar(unicodeScalarLiteral:"0")...UnicodeScalar(unicodeScalarLiteral:"9"):
|
||||
return UInt8(digit.value - UnicodeScalar(unicodeScalarLiteral:"0").value)
|
||||
|
||||
case UnicodeScalar(unicodeScalarLiteral:"a")...UnicodeScalar(unicodeScalarLiteral:"f"):
|
||||
return UInt8(digit.value - UnicodeScalar(unicodeScalarLiteral:"a").value + 0xa)
|
||||
|
||||
case UnicodeScalar(unicodeScalarLiteral:"A")...UnicodeScalar(unicodeScalarLiteral:"F"):
|
||||
return UInt8(digit.value - UnicodeScalar(unicodeScalarLiteral:"A").value + 0xa)
|
||||
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Converts a string of hexadecimal digits to a byte array.
|
||||
///
|
||||
/// - Parameter string: The hex string (must contain an even number of digits)
|
||||
///
|
||||
/// - Returns: A byte array or [] if the input is not valid hexadecimal
|
||||
///
|
||||
public static func byteArray(fromHex string: String) -> [UInt8] {
|
||||
|
||||
var iterator = string.unicodeScalars.makeIterator()
|
||||
var byteArray: [UInt8] = []
|
||||
while let msn = iterator.next() {
|
||||
|
||||
if let lsn = iterator.next(),
|
||||
let hexMSN = convert(hexDigit: msn) ,
|
||||
let hexLSN = convert(hexDigit: lsn) {
|
||||
|
||||
byteArray += [ (hexMSN << 4 | hexLSN) ]
|
||||
|
||||
} else {
|
||||
|
||||
// @TODO: In the next major release this function should throw instead of returning an empty array.
|
||||
return []
|
||||
}
|
||||
}
|
||||
return byteArray
|
||||
}
|
||||
|
||||
///
|
||||
/// Converts a UTF-8 String to a byte array.
|
||||
///
|
||||
/// - Parameter string: the string
|
||||
///
|
||||
/// - Returns: A byte array
|
||||
///
|
||||
public static func byteArray(from string: String) -> [UInt8] {
|
||||
|
||||
let array = [UInt8](string.utf8)
|
||||
return array
|
||||
}
|
||||
|
||||
///
|
||||
/// Converts a string of hexadecimal digits to an `NSData` object.
|
||||
///
|
||||
/// - Parameter string: The hex string (must contain an even number of digits)
|
||||
///
|
||||
/// - Returns: An `NSData` object
|
||||
///
|
||||
public static func data(fromHex string: String) -> NSData {
|
||||
|
||||
let a = byteArray(fromHex: string)
|
||||
return NSData(bytes:a, length:a.count)
|
||||
}
|
||||
|
||||
///
|
||||
/// Converts a string of hexadecimal digits to an `Data` object.
|
||||
///
|
||||
/// - Parameter string: The hex string (must contain an even number of digits)
|
||||
///
|
||||
/// - Returns: An `Data` object
|
||||
///
|
||||
public static func data(fromHex string: String) -> Data {
|
||||
|
||||
let a = byteArray(fromHex: string)
|
||||
return Data(bytes: a, count: a.count)
|
||||
}
|
||||
|
||||
///
|
||||
/// Converts a byte array to an `NSData` object.
|
||||
///
|
||||
/// - Parameter byteArray: The byte array
|
||||
///
|
||||
/// - Returns: An `NSData` object
|
||||
///
|
||||
public static func data(from byteArray: [UInt8]) -> NSData {
|
||||
|
||||
return NSData(bytes:byteArray, length:byteArray.count)
|
||||
}
|
||||
|
||||
///
|
||||
/// Converts a byte array to an `Data` object.
|
||||
///
|
||||
/// - Parameter byteArray: The byte array
|
||||
///
|
||||
/// - Returns: An `Data` object
|
||||
///
|
||||
public static func data(from byteArray: [UInt8]) -> Data {
|
||||
|
||||
return Data(bytes: byteArray, count: byteArray.count)
|
||||
}
|
||||
|
||||
///
|
||||
/// Converts a byte array to a string of hexadecimal digits.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - byteArray: The Swift array
|
||||
/// - uppercase: True to use uppercase for letter digits, lowercase otherwise
|
||||
///
|
||||
/// - Returns: A String
|
||||
///
|
||||
public static func hexString(from byteArray: [UInt8], uppercase: Bool = false) -> String {
|
||||
|
||||
return byteArray.map() { String(format: (uppercase) ? "%02X" : "%02x", $0) }.reduce("", +)
|
||||
}
|
||||
|
||||
///
|
||||
/// Converts a Swift array to an `NSString` object.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - byteArray: The Swift array
|
||||
/// - uppercase: True to use uppercase for letter digits, lowercase otherwise
|
||||
///
|
||||
/// - Returns: An `NSString` object
|
||||
///
|
||||
public static func hexNSString(from byteArray: [UInt8], uppercase: Bool = false) -> NSString {
|
||||
|
||||
let formatString = (uppercase) ? "%02X" : "%02x"
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
return byteArray.map() { String(format: formatString, $0) }.reduce("", +) as NSString
|
||||
#else
|
||||
let aString = byteArray.map() { String(format: formatString, $0) }.reduce("", +)
|
||||
return NSString(string: aString)
|
||||
#endif
|
||||
}
|
||||
|
||||
///
|
||||
/// Converts a byte array to a String containing a comma separated list of bytes.
|
||||
/// This is used to generate test data programmatically.
|
||||
///
|
||||
/// - Parameter byteArray: The byte array
|
||||
///
|
||||
/// - Returns: A String
|
||||
///
|
||||
public static func hexList(from byteArray: [UInt8]) -> String {
|
||||
|
||||
return byteArray.map() { String(format:"0x%02x, ", $0) }.reduce("", +)
|
||||
}
|
||||
|
||||
///
|
||||
/// Zero pads a byte array such that it is an integral number of `blockSizeinBytes` long.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - byteArray: The byte array
|
||||
/// - blockSizeInBytes: The block size in bytes.
|
||||
///
|
||||
/// - Returns: A Swift string
|
||||
///
|
||||
public static func zeroPad(byteArray: [UInt8], blockSize: Int) -> [UInt8] {
|
||||
|
||||
let pad = blockSize - (byteArray.count % blockSize)
|
||||
guard pad != 0 else {
|
||||
return byteArray
|
||||
}
|
||||
return byteArray + Array<UInt8>(repeating: 0, count: pad)
|
||||
}
|
||||
|
||||
///
|
||||
/// Zero pads a String (after UTF8 conversion) such that it is an integral number of `blockSizeinBytes` long.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - string: The String
|
||||
/// - blockSizeInBytes: The block size in bytes
|
||||
///
|
||||
/// - Returns: A byte array
|
||||
///
|
||||
public static func zeroPad(string: String, blockSize: Int) -> [UInt8] {
|
||||
|
||||
return zeroPad(byteArray: Array<UInt8>(string.utf8), blockSize: blockSize)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user