Files
swiftGrammar/Pods/BlueRSA/Sources/CryptorRSA/CryptorRSADigest.swift
2024-08-12 10:49:20 +08:00

330 lines
7.2 KiB
Swift

//
// CryptorRSADigest.swift
// CryptorRSA
//
// Created by Bill Abt on 1/18/17.
//
//
// 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.
//
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
import CommonCrypto
#elseif os(Linux)
import OpenSSL
public typealias CC_LONG = size_t
#endif
import Foundation
// MARK: -- RSA Digest Extension for Data
///
/// Digest Handling Extension
///
extension Data {
// MARK: Enums
///
/// Enumerates available Digest algorithms
///
public enum Algorithm {
/// 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
/// Secure Hash Algorithm 1 using AES-GCM envelope encryption.
/// use this algorithm for cross platform encryption/decryption.
case gcm
/// Digest Length
public var length: CC_LONG {
#if os(Linux)
switch self {
case .sha1:
return CC_LONG(SHA_DIGEST_LENGTH)
case .sha224:
return CC_LONG(SHA224_DIGEST_LENGTH)
case .sha256:
return CC_LONG(SHA256_DIGEST_LENGTH)
case .sha384:
return CC_LONG(SHA384_DIGEST_LENGTH)
case .sha512:
return CC_LONG(SHA512_DIGEST_LENGTH)
case .gcm:
return CC_LONG(SHA_DIGEST_LENGTH)
}
#else
switch self {
case .sha1:
return CC_LONG(CC_SHA1_DIGEST_LENGTH)
case .sha224:
return CC_LONG(CC_SHA224_DIGEST_LENGTH)
case .sha256:
return CC_LONG(CC_SHA256_DIGEST_LENGTH)
case .sha384:
return CC_LONG(CC_SHA384_DIGEST_LENGTH)
case .sha512:
return CC_LONG(CC_SHA512_DIGEST_LENGTH)
case .gcm:
return CC_LONG(CC_SHA1_DIGEST_LENGTH)
}
#endif
}
#if os(Linux)
// Hash, padding type
public var algorithmForSignature: (OpaquePointer?, Int32) {
switch self {
case .sha1:
return (.init(EVP_sha1()), RSA_PKCS1_PADDING)
case .sha224:
return (.init(EVP_sha224()), RSA_PKCS1_PADDING)
case .sha256:
return (.init(EVP_sha256()), RSA_PKCS1_PADDING)
case .sha384:
return (.init(EVP_sha384()), RSA_PKCS1_PADDING)
case .sha512:
return (.init(EVP_sha512()), RSA_PKCS1_PADDING)
case .gcm:
return (.init(EVP_sha1()), RSA_PKCS1_PADDING)
}
}
// HMAC type, symmetric encryption, padding type
public var alogrithmForEncryption: (OpaquePointer?, OpaquePointer?, Int32) {
switch self {
case .sha1:
return (.init(EVP_sha1()), .init(EVP_aes_256_cbc()), RSA_PKCS1_OAEP_PADDING)
case .sha224:
return (.init(EVP_sha224()), .init(EVP_aes_256_cbc()), RSA_PKCS1_OAEP_PADDING)
case .sha256:
return (.init(EVP_sha256()), .init(EVP_aes_256_cbc()), RSA_PKCS1_OAEP_PADDING)
case .sha384:
return (.init(EVP_sha384()), .init(EVP_aes_256_cbc()), RSA_PKCS1_OAEP_PADDING)
case .sha512:
return (.init(EVP_sha512()), .init(EVP_aes_128_gcm()), RSA_PKCS1_OAEP_PADDING)
case .gcm:
return (.init(EVP_sha1()), .init(EVP_aes_128_gcm()), RSA_PKCS1_OAEP_PADDING)
}
}
#else
@available(macOS 10.12, iOS 10.0, watchOS 3.3, tvOS 12.0, *)
public var algorithmForSignature: SecKeyAlgorithm {
switch self {
case .sha1:
return .rsaSignatureMessagePKCS1v15SHA1
case .sha224:
return .rsaSignatureMessagePKCS1v15SHA224
case .sha256:
return .rsaSignatureMessagePKCS1v15SHA256
case .sha384:
return .rsaSignatureMessagePKCS1v15SHA384
case .sha512:
return .rsaSignatureMessagePKCS1v15SHA512
case .gcm:
return .rsaSignatureMessagePKCS1v15SHA1
}
}
@available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
var algorithmForPssSignature: SecKeyAlgorithm {
switch self {
case .sha1:
return .rsaSignatureMessagePSSSHA1
case .sha224:
return .rsaSignatureMessagePSSSHA224
case .sha256:
return .rsaSignatureMessagePSSSHA256
case .sha384:
return .rsaSignatureMessagePSSSHA384
case .sha512:
return .rsaSignatureMessagePSSSHA512
case .gcm:
return .rsaSignatureMessagePSSSHA1
}
}
@available(macOS 10.12, iOS 10.0, watchOS 3.3, tvOS 12.0, *)
public var alogrithmForEncryption: SecKeyAlgorithm {
switch self {
case .sha1:
return .rsaEncryptionOAEPSHA1AESGCM
case .sha224:
return .rsaEncryptionOAEPSHA224AESGCM
case .sha256:
return .rsaEncryptionOAEPSHA256AESGCM
case .sha384:
return .rsaEncryptionOAEPSHA384AESGCM
case .sha512:
return .rsaEncryptionOAEPSHA512AESGCM
case .gcm:
return .rsaEncryptionOAEPSHA1AESGCM
}
}
#endif
/// The platform/alogorithm dependent function to be used.
/// (UnsafePointer<UInt8>!, Int, UnsafeMutablePointer<UInt8>!) -> UnsafeMutablePointer<UInt8>!
#if os(Linux)
public var engine: (_ data: UnsafePointer<UInt8>, _ len: CC_LONG, _ md: UnsafeMutablePointer<UInt8>) -> UnsafeMutablePointer<UInt8>? {
switch self {
case .sha1:
return SHA1
case .sha224:
return SHA224
case .sha256:
return SHA256
case .sha384:
return SHA384
case .sha512:
return SHA512
case .gcm:
return SHA1
}
}
#else
public var engine: (_ data: UnsafeRawPointer, _ len: CC_LONG, _ md: UnsafeMutablePointer<UInt8>) -> UnsafeMutablePointer<UInt8>? {
switch self {
case .sha1:
return CC_SHA1
case .sha224:
return CC_SHA224
case .sha256:
return CC_SHA256
case .sha384:
return CC_SHA384
case .sha512:
return CC_SHA512
case .gcm:
return CC_SHA1
}
}
#endif
}
// MARK: Functions
///
/// Return a digest of the data based on the alogorithm selected.
///
/// - Parameters:
/// - alogorithm: The digest `Alogorithm` to use.
///
/// - Returns: `Data` containing the data in digest form.
///
public func digest(using alogorithm: Algorithm) throws -> Data {
var hash = [UInt8](repeating: 0, count: Int(alogorithm.length))
self.withUnsafeBytes { ptr in
guard let baseAddress = ptr.baseAddress else { return }
_ = alogorithm.engine(baseAddress.assumingMemoryBound(to: UInt8.self), CC_LONG(self.count), &hash)
}
return Data(hash)
}
}