Change swift-crypto to CryptoSwift.

This commit is contained in:
Marek Fořt 2020-03-15 09:32:14 +01:00
parent 7512361395
commit 7cf75f3583
3 changed files with 67 additions and 26 deletions

View File

@ -37,6 +37,15 @@
"version": "0.2.1"
}
},
{
"package": "CryptoSwift",
"repositoryURL": "https://github.com/krzyzanowskim/CryptoSwift",
"state": {
"branch": null,
"revision": "a44caef0550c346e0ab9172f7c9a3852c1833599",
"version": "1.3.0"
}
},
{
"package": "Guaka",
"repositoryURL": "https://github.com/nsomar/Guaka.git",
@ -82,15 +91,6 @@
"version": "0.4.1"
}
},
{
"package": "swift-crypto",
"repositoryURL": "https://github.com/apple/swift-crypto",
"state": {
"branch": null,
"revision": "9be4a93a76d4b80105044747b35d456de7289c87",
"version": "1.0.0"
}
},
{
"package": "llbuild",
"repositoryURL": "https://github.com/apple/swift-llbuild.git",

View File

@ -33,7 +33,7 @@ let package = Package(
.package(url: "https://github.com/ReactiveX/RxSwift.git", .upToNextMajor(from: "5.0.1")),
.package(url: "https://github.com/rnine/Checksum.git", .upToNextMajor(from: "1.0.2")),
.package(url: "https://github.com/thii/xcbeautify.git", .upToNextMajor(from: "0.7.3")),
.package(url: "https://github.com/apple/swift-crypto", .upToNextMajor(from: "1.0.0")),
.package(url: "https://github.com/krzyzanowskim/CryptoSwift", .upToNextMajor(from: "1.3.0")),
],
targets: [
.target(
@ -150,7 +150,7 @@ let package = Package(
),
.target(
name: "TuistSigning",
dependencies: ["TuistCore", "TuistSupport", "Crypto"]
dependencies: ["TuistCore", "TuistSupport", "CryptoSwift"]
),
.testTarget(
name: "TuistSigningTests",

View File

@ -1,8 +1,22 @@
import Basic
import Crypto
import Foundation
import CryptoSwift
import TuistSupport
import TuistLoader
enum SigningCipherError: FatalError {
case failedToEncrypt
var type: ErrorType { .abort }
var description: String {
switch self {
case .failedToEncrypt:
return "Encryption failed"
}
}
}
public protocol SigningCiphering {
func encryptSigning(at path: AbsolutePath) throws
func decryptSigning(at path: AbsolutePath) throws
@ -15,16 +29,10 @@ public final class SigningCipher: SigningCiphering {
let (signingKeyFiles, masterKey) = try signingData(at: path)
let cipheredKeys = try signingKeyFiles
.map(FileHandler.shared.readFile)
.map {
try AES.GCM.seal($0, using: masterKey)
}
.map { try encryptData($0, masterKey: masterKey) }
try zip(cipheredKeys, signingKeyFiles).forEach {
guard let combinedData = $0.combined else {
Printer.shared.print(warning: "Could not encode file at: \($1.pathString)")
return
}
try combinedData.write(to: $1.url)
try $0.write(to: $1.url)
}
}
@ -32,9 +40,8 @@ public final class SigningCipher: SigningCiphering {
let (signingKeyFiles, masterKey) = try signingData(at: path)
let decipheredKeys = try signingKeyFiles
.map(FileHandler.shared.readFile)
.map(AES.GCM.SealedBox.init)
.map {
try AES.GCM.open($0, using: masterKey)
try decryptData($0, masterKey: masterKey)
}
try zip(decipheredKeys, signingKeyFiles).forEach {
@ -44,7 +51,30 @@ public final class SigningCipher: SigningCiphering {
// MARK: - Helpers
private func signingData(at path: AbsolutePath) throws -> (signingKeyFiles: [AbsolutePath], masterKey: SymmetricKey) {
private func encryptData(_ data: Data, masterKey: Data) throws -> Data {
let iv = try generateIv()
let aesCipher = try AES(key: masterKey.bytes, blockMode: CTR(iv: iv.bytes), padding: .noPadding)
guard
let encryptedBase64String = try aesCipher.encrypt(data.bytes).toBase64(),
let data = (iv.base64EncodedString() + "-" + encryptedBase64String).data(using: .utf8)
else { throw SigningCipherError.failedToEncrypt }
return data
}
private func decryptData(_ data: Data, masterKey: Data) throws -> Data {
guard
let encodedString = String(data: data, encoding: .utf8),
let dividerIndex = encodedString.firstIndex(of: "-"),
let iv = Data(base64Encoded: String(encodedString.prefix(upTo: dividerIndex)))
else { throw SigningCipherError.failedToEncrypt }
let dataToDecrypt = Data(base64Encoded: String(encodedString.suffix(from: dividerIndex).dropFirst()))
let aesCipher = try AES(key: masterKey.bytes, blockMode: CTR(iv: iv.bytes), padding: .noPadding)
guard let decryptedData = try dataToDecrypt?.decrypt(cipher: aesCipher) else { throw SigningCipherError.failedToEncrypt }
return decryptedData
}
private func signingData(at path: AbsolutePath) throws -> (signingKeyFiles: [AbsolutePath], masterKey: Data) {
guard let rootDirectory = RootDirectoryLocator.shared.locate(from: path) else { fatalError() }
let signingDirectory = rootDirectory.appending(components: Constants.tuistDirectoryName, Constants.signingDirectoryName)
let masterKey = try self.masterKey(from: signingDirectory)
@ -54,8 +84,19 @@ public final class SigningCipher: SigningCiphering {
return (signingKeyFiles: signingKeyFiles, masterKey: masterKey)
}
private func masterKey(from signingDirectory: AbsolutePath) throws -> SymmetricKey {
let plainMasterKey = try FileHandler.shared.readTextFile(signingDirectory.appending(component: "master.key"))
return SymmetricKey(data: SHA256(plainMasterKey).digest())
private func masterKey(from signingDirectory: AbsolutePath) throws -> Data {
let plainMasterKey = try FileHandler.shared.readFile(signingDirectory.appending(component: "master.key"))
return plainMasterKey.sha256()
}
private func generateIv() throws -> Data {
let blockSize = 16
var iv = Data(repeating: 0, count: blockSize)
let result = iv.withUnsafeMutableBytes { bytes -> Int32 in
guard let baseAddress = bytes.baseAddress else { return 0 }
return SecRandomCopyBytes(kSecRandomDefault, blockSize, baseAddress)
}
guard result == errSecSuccess else { throw SigningCipherError.failedToEncrypt }
return iv
}
}