project start
10
Friendvatars.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:/Users/dawidkubicki/Documents/uczelnia/bsm/bsm-project/bsmZadanie.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
BIN
Friendvatars.xcworkspace/xcuserdata/critz.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
BIN
Friendvatars.xcworkspace/xcuserdata/dawidkubicki.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
BIN
Friendvatars.xcworkspace/xcuserdata/jeffro.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
46
Friendvatars/AppController.swift
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
final class AppController {
|
||||
|
||||
static let shared = AppController()
|
||||
|
||||
var window: UIWindow!
|
||||
var rootViewController: UIViewController? {
|
||||
didSet {
|
||||
if let vc = rootViewController {
|
||||
window.rootViewController = vc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
NotificationCenter.default.addObserver(
|
||||
self,
|
||||
selector: #selector(handleAuthState),
|
||||
name: .loginStatusChanged,
|
||||
object: nil
|
||||
)
|
||||
}
|
||||
|
||||
func show(in window: UIWindow?) {
|
||||
guard let window = window else {
|
||||
fatalError("Cannot layout app with a nil window.")
|
||||
}
|
||||
|
||||
window.backgroundColor = .black
|
||||
self.window = window
|
||||
|
||||
rootViewController = SplashViewController()
|
||||
window.makeKeyAndVisible()
|
||||
}
|
||||
|
||||
@objc func handleAuthState() {
|
||||
if AuthController.isSignedIn {
|
||||
rootViewController = NavigationController(rootViewController: FriendsViewController())
|
||||
} else {
|
||||
rootViewController = AuthViewController()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
14
Friendvatars/AppDelegate.swift
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
import UIKit
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
|
||||
AppController.shared.show(in: UIWindow(frame: UIScreen.main.bounds))
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
182
Friendvatars/Assets.xcassets/AppIcon.appiconset/Contents.json
Executable file
@ -0,0 +1,182 @@
|
||||
{
|
||||
"images":[
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"20x20",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-20x20@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"20x20",
|
||||
"scale":"3x",
|
||||
"filename":"Icon-App-20x20@3x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"29x29",
|
||||
"scale":"1x",
|
||||
"filename":"Icon-App-29x29@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"29x29",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-29x29@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"29x29",
|
||||
"scale":"3x",
|
||||
"filename":"Icon-App-29x29@3x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"40x40",
|
||||
"scale":"1x",
|
||||
"filename":"Icon-App-40x40@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"40x40",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-40x40@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"40x40",
|
||||
"scale":"3x",
|
||||
"filename":"Icon-App-40x40@3x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"57x57",
|
||||
"scale":"1x",
|
||||
"filename":"Icon-App-57x57@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"57x57",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-57x57@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"60x60",
|
||||
"scale":"1x",
|
||||
"filename":"Icon-App-60x60@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"60x60",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-60x60@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"60x60",
|
||||
"scale":"3x",
|
||||
"filename":"Icon-App-60x60@3x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"76x76",
|
||||
"scale":"1x",
|
||||
"filename":"Icon-App-76x76@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"20x20",
|
||||
"scale":"1x",
|
||||
"filename":"Icon-App-20x20@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"20x20",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-20x20@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"29x29",
|
||||
"scale":"1x",
|
||||
"filename":"Icon-App-29x29@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"29x29",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-29x29@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"40x40",
|
||||
"scale":"1x",
|
||||
"filename":"Icon-App-40x40@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"40x40",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-40x40@2x.png"
|
||||
},
|
||||
{
|
||||
"size" : "50x50",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-Small-50x50@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "50x50",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-Small-50x50@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"72x72",
|
||||
"scale":"1x",
|
||||
"filename":"Icon-App-72x72@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"72x72",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-72x72@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"76x76",
|
||||
"scale":"1x",
|
||||
"filename":"Icon-App-76x76@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"76x76",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-76x76@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"76x76",
|
||||
"scale":"3x",
|
||||
"filename":"Icon-App-76x76@3x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"83.5x83.5",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-83.5x83.5@2x.png"
|
||||
},
|
||||
{
|
||||
"size" : "1024x1024",
|
||||
"idiom" : "ios-marketing",
|
||||
"filename" : "ItunesArtwork@2x.png",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info":{
|
||||
"version":1,
|
||||
"author":"makeappicon"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 26 KiB |
6
Friendvatars/Assets.xcassets/Contents.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
21
Friendvatars/Assets.xcassets/FaceID.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "FaceID.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
Friendvatars/Assets.xcassets/FaceID.imageset/FaceID.png
vendored
Normal file
After Width: | Height: | Size: 2.1 KiB |
21
Friendvatars/Assets.xcassets/TouchID.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "TouchID.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
Friendvatars/Assets.xcassets/TouchID.imageset/TouchID.png
vendored
Normal file
After Width: | Height: | Size: 42 KiB |
21
Friendvatars/Assets.xcassets/rw-logo.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Razewarelogo_1024.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
Friendvatars/Assets.xcassets/rw-logo.imageset/Razewarelogo_1024.png
vendored
Normal file
After Width: | Height: | Size: 80 KiB |
21
Friendvatars/Assets.xcassets/rwdevcon-bg.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "rwdevcon-bg.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
Friendvatars/Assets.xcassets/rwdevcon-bg.imageset/rwdevcon-bg.png
vendored
Normal file
After Width: | Height: | Size: 415 KiB |
52
Friendvatars/AuthController.swift
Normal file
@ -0,0 +1,52 @@
|
||||
|
||||
import Foundation
|
||||
import CryptoSwift
|
||||
|
||||
final class AuthController {
|
||||
|
||||
static let serviceName = "FriendvatarsService"
|
||||
|
||||
static var isSignedIn: Bool {
|
||||
guard let currentUser = Settings.currentUser else {
|
||||
return false
|
||||
}
|
||||
|
||||
do {
|
||||
let password = try KeychainPasswordItem(service: serviceName, account: currentUser.email).readPassword()
|
||||
return password.count > 0
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
class func passwordHash(from email: String, password: String) -> String {
|
||||
let salt = "x4vV8bGgqqmQwgCoyXFQj+(o.nUNQhVP7ND"
|
||||
return "\(password).\(email).\(salt)".sha256()
|
||||
}
|
||||
|
||||
class func signIn(_ user: User, password: String) throws {
|
||||
let finalHash = passwordHash(from: user.email, password: password)
|
||||
try KeychainPasswordItem(service: serviceName, account: user.email).savePassword(finalHash)
|
||||
|
||||
Settings.currentUser = user
|
||||
NotificationCenter.default.post(name: .loginStatusChanged, object: nil)
|
||||
}
|
||||
|
||||
class func signOut() throws {
|
||||
guard let currentUser = Settings.currentUser else {
|
||||
return
|
||||
}
|
||||
|
||||
try KeychainPasswordItem(service: serviceName, account: currentUser.email).deleteItem()
|
||||
|
||||
Settings.currentUser = nil
|
||||
NotificationCenter.default.post(name: .loginStatusChanged, object: nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension Notification.Name {
|
||||
|
||||
static let loginStatusChanged = Notification.Name("com.razeware.auth.changed")
|
||||
|
||||
}
|
220
Friendvatars/AuthViewController.swift
Normal file
@ -0,0 +1,220 @@
|
||||
|
||||
import UIKit
|
||||
import KeychainAccess
|
||||
|
||||
final class AuthViewController: UIViewController {
|
||||
|
||||
override var prefersStatusBarHidden: Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
private enum TextFieldTag: Int {
|
||||
case email
|
||||
case password
|
||||
}
|
||||
|
||||
@IBOutlet weak var txtSecret: UITextField!
|
||||
@IBOutlet weak var imgBio: UIImageView!
|
||||
@IBOutlet weak var lblSecret: UILabel!
|
||||
@IBOutlet weak var containerView: UIView!
|
||||
@IBOutlet weak var emailField: UITextField!
|
||||
@IBOutlet weak var passwordField: UITextField!
|
||||
@IBOutlet weak var titleLabel: UILabel!
|
||||
@IBOutlet weak var signInButton: UIButton!
|
||||
@IBOutlet weak var bottomConstraint: NSLayoutConstraint!
|
||||
|
||||
let keychain = Keychain(service: "com.zadanie.bsm")
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
if(biometricType == .touchID) {
|
||||
imgBio.image = UIImage(named: "TouchID")
|
||||
} else if(biometricType == .faceID) {
|
||||
imgBio.image = UIImage(named: "FaceID")
|
||||
} else if(biometricType == .none) {
|
||||
print("Nie ma biometrycznego czytnika")
|
||||
}
|
||||
|
||||
containerView.transform = CGAffineTransform(scaleX: 0, y: 0)
|
||||
containerView.backgroundColor = .rwGreen
|
||||
containerView.layer.cornerRadius = 7
|
||||
|
||||
emailField.delegate = self
|
||||
emailField.tintColor = .rwGreen
|
||||
emailField.tag = TextFieldTag.email.rawValue
|
||||
|
||||
passwordField.delegate = self
|
||||
passwordField.tintColor = .rwGreen
|
||||
passwordField.tag = TextFieldTag.password.rawValue
|
||||
|
||||
titleLabel.isHidden = true
|
||||
|
||||
view.addGestureRecognizer(
|
||||
UITapGestureRecognizer(
|
||||
target: self,
|
||||
action: #selector(handleTap(_:))
|
||||
)
|
||||
)
|
||||
|
||||
registerForKeyboardNotifications()
|
||||
}
|
||||
|
||||
|
||||
@IBAction func storeSecret(_ sender: Any) {
|
||||
DispatchQueue.global().async {
|
||||
do {
|
||||
try self.keychain
|
||||
.accessibility(.whenPasscodeSetThisDeviceOnly, authenticationPolicy: .userPresence)
|
||||
.set(self.txtSecret.text!, key: "secret")
|
||||
} catch let error {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func getSecret(_ sender: Any) {
|
||||
DispatchQueue.global().async {
|
||||
do {
|
||||
let secret = try self.keychain
|
||||
.authenticationPrompt("Użyj czynnika biometrycznego, żeby zobaczyć sekret")
|
||||
.get("secret")
|
||||
self.lblSecret.text = "Sekret to \(secret!)"
|
||||
} catch let error {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
let animation = CABasicAnimation(keyPath: "transform.scale")
|
||||
|
||||
animation.duration = 0.3
|
||||
animation.fromValue = 0
|
||||
animation.toValue = 1
|
||||
|
||||
CATransaction.begin()
|
||||
CATransaction.setCompletionBlock {
|
||||
self.emailField.becomeFirstResponder()
|
||||
self.titleLabel.isHidden = false
|
||||
}
|
||||
containerView.layer.add(animation, forKey: "scale")
|
||||
containerView.transform = CGAffineTransform(scaleX: 1, y: 1)
|
||||
CATransaction.commit()
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@objc private func handleTap(_ gesture: UITapGestureRecognizer) {
|
||||
view.endEditing(true)
|
||||
}
|
||||
|
||||
@IBAction func signInButtonPressed() {
|
||||
signIn()
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
private func registerForKeyboardNotifications() {
|
||||
NotificationCenter.default.addObserver(
|
||||
self,
|
||||
selector: #selector(keyboardWillShow(_:)),
|
||||
name: NSNotification.Name.UIKeyboardWillShow,
|
||||
object: nil
|
||||
)
|
||||
NotificationCenter.default.addObserver(
|
||||
self,
|
||||
selector: #selector(keyboardWillHide(_:)),
|
||||
name: NSNotification.Name.UIKeyboardWillHide,
|
||||
object: nil
|
||||
)
|
||||
}
|
||||
|
||||
private func signIn() {
|
||||
view.endEditing(true)
|
||||
|
||||
guard let email = emailField.text, email.count > 0 else {
|
||||
return
|
||||
}
|
||||
guard let password = passwordField.text, password.count > 0 else {
|
||||
return
|
||||
}
|
||||
|
||||
let name = UIDevice.current.name
|
||||
let user = User(name: name, email: email)
|
||||
|
||||
do {
|
||||
try AuthController.signIn(user, password: password)
|
||||
} catch {
|
||||
print("Error signing in: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Notifications
|
||||
|
||||
@objc internal func keyboardWillShow(_ notification: Notification) {
|
||||
guard let userInfo = notification.userInfo else {
|
||||
return
|
||||
}
|
||||
guard let keyboardHeight = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height else {
|
||||
return
|
||||
}
|
||||
guard let keyboardAnimationDuration = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue else {
|
||||
return
|
||||
}
|
||||
guard let keyboardAnimationCurve = (userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.uintValue else {
|
||||
return
|
||||
}
|
||||
|
||||
let options = UIViewAnimationOptions(rawValue: keyboardAnimationCurve << 16)
|
||||
bottomConstraint.constant = keyboardHeight + 32
|
||||
|
||||
UIView.animate(withDuration: keyboardAnimationDuration, delay: 0, options: options, animations: {
|
||||
self.view.layoutIfNeeded()
|
||||
}, completion: nil)
|
||||
}
|
||||
|
||||
@objc internal func keyboardWillHide(_ notification: Notification) {
|
||||
guard let userInfo = notification.userInfo else {
|
||||
return
|
||||
}
|
||||
guard let keyboardAnimationDuration = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue else {
|
||||
return
|
||||
}
|
||||
guard let keyboardAnimationCurve = (userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.uintValue else {
|
||||
return
|
||||
}
|
||||
|
||||
let options = UIViewAnimationOptions(rawValue: keyboardAnimationCurve << 16)
|
||||
bottomConstraint.constant = 0
|
||||
|
||||
UIView.animate(withDuration: keyboardAnimationDuration, delay: 0, options: options, animations: {
|
||||
self.view.layoutIfNeeded()
|
||||
}, completion: nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension AuthViewController: UITextFieldDelegate {
|
||||
|
||||
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
||||
guard let text = textField.text, text.count > 0 else {
|
||||
return false
|
||||
}
|
||||
|
||||
switch textField.tag {
|
||||
case TextFieldTag.email.rawValue:
|
||||
passwordField.becomeFirstResponder()
|
||||
case TextFieldTag.password.rawValue:
|
||||
signIn()
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
201
Friendvatars/AuthViewController.xib
Normal file
@ -0,0 +1,201 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="AuthViewController" customModule="Friendvatars" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="bottomConstraint" destination="nvR-sM-xyu" id="sfO-yG-bij"/>
|
||||
<outlet property="containerView" destination="fIM-wX-ThP" id="MCr-wf-hth"/>
|
||||
<outlet property="emailField" destination="vrM-BE-Sxz" id="yN0-VF-tnI"/>
|
||||
<outlet property="imgBio" destination="aiB-UR-Quk" id="Rf6-w3-c9d"/>
|
||||
<outlet property="lblSecret" destination="SIk-oO-kOD" id="8c0-hE-Wb2"/>
|
||||
<outlet property="passwordField" destination="XnE-em-cB7" id="I2k-JM-vRu"/>
|
||||
<outlet property="signInButton" destination="hSR-Ry-zgR" id="67R-L3-h8e"/>
|
||||
<outlet property="titleLabel" destination="WHD-fd-dhU" id="y4p-7Q-Mwd"/>
|
||||
<outlet property="txtSecret" destination="NYv-x5-X0G" id="967-mt-IUu"/>
|
||||
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="rwdevcon-bg" translatesAutoresizingMaskIntoConstraints="NO" id="tFe-fM-7UZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="UKRYTE WIADOMOŚCI" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WHD-fd-dhU">
|
||||
<rect key="frame" x="32" y="69" width="311" height="31.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="31.5" id="Hl5-V5-oUY"/>
|
||||
<constraint firstAttribute="width" constant="311" id="O3M-ll-ype"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle1"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="NYv-x5-X0G">
|
||||
<rect key="frame" x="83.5" y="400" width="208" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="Kc5-kK-ceQ"/>
|
||||
<constraint firstAttribute="width" constant="208" id="Z2q-C8-b0N"/>
|
||||
</constraints>
|
||||
<nil key="textColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
</textField>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fIM-wX-ThP">
|
||||
<rect key="frame" x="32" y="112.5" width="311" height="256"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="47J-gQ-72v">
|
||||
<rect key="frame" x="12" y="12" width="287" height="232"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="249" text="Login lub mail" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="jBg-ue-wfi">
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="40"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Podaj swoj login/hasło" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="vrM-BE-Sxz">
|
||||
<rect key="frame" x="0.0" y="48" width="287" height="40"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="40" id="o9g-dR-A9f"/>
|
||||
</constraints>
|
||||
<nil key="textColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" keyboardType="emailAddress" keyboardAppearance="alert" enablesReturnKeyAutomatically="YES" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no" textContentType="email"/>
|
||||
</textField>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Hasło" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AMS-r7-phX">
|
||||
<rect key="frame" x="0.0" y="96" width="287" height="40"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Podaj swoje hasło" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="XnE-em-cB7">
|
||||
<rect key="frame" x="0.0" y="144" width="287" height="40"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="40" id="r71-Sl-CjK"/>
|
||||
</constraints>
|
||||
<nil key="textColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<textInputTraits key="textInputTraits" keyboardAppearance="alert" secureTextEntry="YES"/>
|
||||
</textField>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hSR-Ry-zgR">
|
||||
<rect key="frame" x="0.0" y="192" width="287" height="40"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="17"/>
|
||||
<state key="normal" title="Zobacz zaszyfrowaną wiadomość">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="signInButtonPressed" destination="-1" eventType="touchUpInside" id="tdM-du-QeO"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="vrM-BE-Sxz" secondAttribute="trailing" id="1Z2-xc-gAX"/>
|
||||
<constraint firstItem="XnE-em-cB7" firstAttribute="leading" secondItem="47J-gQ-72v" secondAttribute="leading" id="7b3-lJ-Ouz"/>
|
||||
<constraint firstItem="vrM-BE-Sxz" firstAttribute="leading" secondItem="47J-gQ-72v" secondAttribute="leading" id="AFS-11-IhR"/>
|
||||
<constraint firstAttribute="trailing" secondItem="XnE-em-cB7" secondAttribute="trailing" id="sJh-f6-THo"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="scrollViewTexturedBackgroundColor"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="256" id="7Lf-Jc-Y1f"/>
|
||||
<constraint firstAttribute="trailing" secondItem="47J-gQ-72v" secondAttribute="trailing" constant="12" id="WkR-AZ-hfk"/>
|
||||
<constraint firstItem="47J-gQ-72v" firstAttribute="centerY" secondItem="fIM-wX-ThP" secondAttribute="centerY" id="Yml-f5-C1g"/>
|
||||
<constraint firstAttribute="width" constant="311" id="eHP-rK-M2p"/>
|
||||
<constraint firstItem="47J-gQ-72v" firstAttribute="top" secondItem="fIM-wX-ThP" secondAttribute="top" constant="12" id="lYI-As-5gY"/>
|
||||
<constraint firstAttribute="bottom" secondItem="47J-gQ-72v" secondAttribute="bottom" constant="12" id="pTj-6w-3fL"/>
|
||||
<constraint firstItem="47J-gQ-72v" firstAttribute="leading" secondItem="fIM-wX-ThP" secondAttribute="leading" constant="12" id="tLY-wi-TIE"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="eHu-E9-yMk">
|
||||
<rect key="frame" x="141" y="438" width="93" height="30"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="93" id="WtV-69-tY5"/>
|
||||
<constraint firstAttribute="height" constant="30" id="pYP-ke-zF0"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Zapisz sekret">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="storeSecret:" destination="-1" eventType="touchUpInside" id="sVO-a8-q7z"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0xi-uO-9hm">
|
||||
<rect key="frame" x="143.5" y="476" width="88" height="30"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="sbM-9x-AyV"/>
|
||||
<constraint firstAttribute="width" constant="88" id="uiH-pa-VyX"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Pokaż sekret">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="getSecret:" destination="-1" eventType="touchUpInside" id="cye-aX-2am"/>
|
||||
</connections>
|
||||
</button>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="aiB-UR-Quk">
|
||||
<rect key="frame" x="152.5" y="514" width="70" height="70"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="70" id="B0t-Rd-p9j"/>
|
||||
<constraint firstAttribute="width" constant="70" id="LJW-QK-sy1"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SIk-oO-kOD">
|
||||
<rect key="frame" x="32" y="620" width="311" height="0.0"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="311" id="KVE-6x-sQC"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="fIM-wX-ThP" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="32" id="0Uu-L2-f41"/>
|
||||
<constraint firstItem="fIM-wX-ThP" firstAttribute="top" secondItem="WHD-fd-dhU" secondAttribute="bottom" constant="7.5" id="0zh-0H-6hl"/>
|
||||
<constraint firstItem="fIM-wX-ThP" firstAttribute="centerY" relation="lessThanOrEqual" secondItem="i5M-Pr-FkT" secondAttribute="centerY" id="6Ln-YA-ghi"/>
|
||||
<constraint firstItem="NYv-x5-X0G" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="9SD-Fn-k8d"/>
|
||||
<constraint firstItem="0xi-uO-9hm" firstAttribute="top" secondItem="eHu-E9-yMk" secondAttribute="bottom" constant="8" id="Q8W-5c-khU"/>
|
||||
<constraint firstItem="SIk-oO-kOD" firstAttribute="top" secondItem="aiB-UR-Quk" secondAttribute="bottom" constant="36" id="QFy-ww-vht"/>
|
||||
<constraint firstItem="SIk-oO-kOD" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="QgF-DT-GKx"/>
|
||||
<constraint firstItem="0xi-uO-9hm" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="UeN-Ml-sk1"/>
|
||||
<constraint firstItem="aiB-UR-Quk" firstAttribute="top" secondItem="0xi-uO-9hm" secondAttribute="bottom" constant="8" id="WKd-0t-34H"/>
|
||||
<constraint firstItem="fIM-wX-ThP" firstAttribute="top" secondItem="WHD-fd-dhU" secondAttribute="bottom" constant="12" id="aP2-gg-QM4"/>
|
||||
<constraint firstItem="WHD-fd-dhU" firstAttribute="top" secondItem="fnl-2z-Ty3" secondAttribute="top" constant="49" id="buf-vK-MV1"/>
|
||||
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="fIM-wX-ThP" secondAttribute="trailing" constant="32" id="eeV-zF-hQt"/>
|
||||
<constraint firstItem="tFe-fM-7UZ" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" id="feS-0C-4ss"/>
|
||||
<constraint firstItem="fnl-2z-Ty3" firstAttribute="bottom" secondItem="SIk-oO-kOD" secondAttribute="bottom" constant="47" id="gPG-53-d0t"/>
|
||||
<constraint firstAttribute="bottom" secondItem="tFe-fM-7UZ" secondAttribute="bottom" id="lKC-qE-CTz"/>
|
||||
<constraint firstItem="WHD-fd-dhU" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="mjr-Xm-Z79"/>
|
||||
<constraint firstItem="WHD-fd-dhU" firstAttribute="leading" secondItem="fIM-wX-ThP" secondAttribute="leading" id="n92-TL-EOh"/>
|
||||
<constraint firstAttribute="bottom" secondItem="fIM-wX-ThP" secondAttribute="bottom" priority="750" constant="100" id="nvR-sM-xyu"/>
|
||||
<constraint firstItem="fIM-wX-ThP" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="pxi-l5-vSk"/>
|
||||
<constraint firstItem="tFe-fM-7UZ" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="qHd-7e-hwP"/>
|
||||
<constraint firstItem="aiB-UR-Quk" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="rok-Oz-Hfe"/>
|
||||
<constraint firstItem="eHu-E9-yMk" firstAttribute="top" secondItem="NYv-x5-X0G" secondAttribute="bottom" constant="8" id="sHf-0Z-bMJ"/>
|
||||
<constraint firstItem="WHD-fd-dhU" firstAttribute="trailing" secondItem="fIM-wX-ThP" secondAttribute="trailing" id="sMj-GC-DPU"/>
|
||||
<constraint firstItem="eHu-E9-yMk" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="tmc-q1-o9K"/>
|
||||
<constraint firstAttribute="trailing" secondItem="tFe-fM-7UZ" secondAttribute="trailing" id="zYh-8O-PJL"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
|
||||
<point key="canvasLocation" x="138.40000000000001" y="152.47376311844079"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="rwdevcon-bg" width="1440" height="2880"/>
|
||||
</resources>
|
||||
</document>
|
9
Friendvatars/BiometricTest.swift
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
import Foundation
|
||||
import LocalAuthentication
|
||||
|
||||
var biometricType: LABiometryType {
|
||||
let authContext = LAContext()
|
||||
return authContext.biometryType
|
||||
}
|
13
Friendvatars/DispatchQueue+Delay.swift
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
extension DispatchQueue {
|
||||
|
||||
class func delay(_ delay: Double, closure: @escaping ()->()) {
|
||||
DispatchQueue.main.asyncAfter(
|
||||
deadline: DispatchTime.now() + delay,
|
||||
execute: closure
|
||||
)
|
||||
}
|
||||
|
||||
}
|
22
Friendvatars/FriendCell.swift
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
class FriendCell: UITableViewCell {
|
||||
|
||||
@IBOutlet var nameLabel: UILabel!
|
||||
@IBOutlet var avatarImageView: UIImageView!
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
avatarImageView.clipsToBounds = true
|
||||
avatarImageView.layer.cornerRadius = avatarImageView.bounds.width / 2
|
||||
}
|
||||
|
||||
override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
|
||||
avatarImageView.image = nil
|
||||
}
|
||||
|
||||
}
|
54
Friendvatars/FriendCell.xib
Normal file
@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
|
||||
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="64" id="KGk-i7-Jjw" customClass="FriendCell" customModule="Friendvatars" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="64"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="63.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="hKH-Xg-NJn">
|
||||
<rect key="frame" x="16" y="8" width="47.5" height="47.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="hKH-Xg-NJn" secondAttribute="height" multiplier="1:1" id="RU9-aU-BaN"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Name label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mxB-ad-p9W">
|
||||
<rect key="frame" x="71.5" y="21" width="224.5" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="mxB-ad-p9W" firstAttribute="leading" secondItem="hKH-Xg-NJn" secondAttribute="trailing" constant="8" id="6Lv-Ir-hCs"/>
|
||||
<constraint firstItem="mxB-ad-p9W" firstAttribute="centerY" secondItem="H2p-sc-9uM" secondAttribute="centerY" id="Gfd-3v-WBE"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="mxB-ad-p9W" secondAttribute="trailing" constant="8" id="MMg-vQ-Zwg"/>
|
||||
<constraint firstAttribute="bottom" secondItem="hKH-Xg-NJn" secondAttribute="bottom" constant="8" id="hY6-Ld-eLy"/>
|
||||
<constraint firstItem="hKH-Xg-NJn" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="16" id="prX-yv-ZMz"/>
|
||||
<constraint firstItem="hKH-Xg-NJn" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="8" id="xem-fJ-fj3"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
|
||||
<connections>
|
||||
<outlet property="avatarImageView" destination="hKH-Xg-NJn" id="397-KH-M7f"/>
|
||||
<outlet property="nameLabel" destination="mxB-ad-p9W" id="kXC-oB-eTA"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="-120" y="-75"/>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
103
Friendvatars/FriendsViewController.swift
Normal file
@ -0,0 +1,103 @@
|
||||
|
||||
import UIKit
|
||||
import CryptoSwift
|
||||
|
||||
final class FriendsViewController: UITableViewController {
|
||||
|
||||
var friends: [User] = []
|
||||
var imageCache = NSCache<NSString, UIImage>()
|
||||
|
||||
init() {
|
||||
super.init(style: .grouped)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
title = "Zabezpieczona wiadomość"
|
||||
|
||||
let reuseIdentifier = String(describing: FriendCell.self)
|
||||
tableView.register(
|
||||
UINib(nibName: reuseIdentifier, bundle: nil),
|
||||
forCellReuseIdentifier: reuseIdentifier
|
||||
)
|
||||
|
||||
navigationItem.leftBarButtonItem = UIBarButtonItem(
|
||||
title: "Wyloguj się",
|
||||
style: .plain,
|
||||
target: self,
|
||||
action: #selector(signOut)
|
||||
)
|
||||
|
||||
friends = [
|
||||
User(name: "Zakodowana1", email: "ukryty tekst1"),
|
||||
User(name: "Zakodowana2", email: "ukryty tekst2"),
|
||||
User(name: "Zakodowana3", email: "ukryty tekst3"),
|
||||
User(name: "Zakodowana4", email: "ukryty tekst4")
|
||||
]
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@objc private func signOut() {
|
||||
try? AuthController.signOut()
|
||||
}
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return friends.isEmpty ? 1 : 2
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return section == 0 ? 1 : friends.count
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||
return 64
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
return section == 0 ? "Ja" : "Ukryte wiadomości"
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: FriendCell.self)) as? FriendCell else {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
let user = indexPath.section == 0 ? Settings.currentUser! : friends[indexPath.row]
|
||||
cell.nameLabel.text = user.name
|
||||
|
||||
if let image = imageCache.object(forKey: user.email as NSString) {
|
||||
cell.avatarImageView.image = image
|
||||
} else {
|
||||
let emailHash = user.email.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
.lowercased()
|
||||
.sha1()
|
||||
|
||||
if let url = URL(string: "https://www.gravatar.com/avatar/" + emailHash) {
|
||||
URLSession.shared.dataTask(with: url) { data, response, error in
|
||||
guard let data = data, let image = UIImage(data: data) else {
|
||||
return
|
||||
}
|
||||
|
||||
self.imageCache.setObject(image, forKey: user.email as NSString)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.tableView.reloadRows(at: [indexPath], with: .automatic)
|
||||
}
|
||||
}.resume()
|
||||
}
|
||||
}
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
}
|
||||
|
||||
}
|
43
Friendvatars/Info.plist
Normal file
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<true/>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
178
Friendvatars/KeychainPasswordItem.swift
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
Copyright (C) 2016 Apple Inc. All Rights Reserved.
|
||||
See LICENSE.txt for this sample’s licensing information
|
||||
|
||||
Abstract:
|
||||
A struct for accessing generic password keychain items.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
struct KeychainPasswordItem {
|
||||
// MARK: Types
|
||||
|
||||
enum KeychainError: Error {
|
||||
case noPassword
|
||||
case unexpectedPasswordData
|
||||
case unexpectedItemData
|
||||
case unhandledError(status: OSStatus)
|
||||
}
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
let service: String
|
||||
|
||||
private(set) var account: String
|
||||
|
||||
let accessGroup: String?
|
||||
|
||||
// MARK: Intialization
|
||||
|
||||
init(service: String, account: String, accessGroup: String? = nil) {
|
||||
self.service = service
|
||||
self.account = account
|
||||
self.accessGroup = accessGroup
|
||||
}
|
||||
|
||||
// MARK: Keychain access
|
||||
|
||||
func readPassword() throws -> String {
|
||||
/*
|
||||
Build a query to find the item that matches the service, account and
|
||||
access group.
|
||||
*/
|
||||
var query = KeychainPasswordItem.keychainQuery(withService: service, account: account, accessGroup: accessGroup)
|
||||
query[kSecMatchLimit as String] = kSecMatchLimitOne
|
||||
query[kSecReturnAttributes as String] = kCFBooleanTrue
|
||||
query[kSecReturnData as String] = kCFBooleanTrue
|
||||
|
||||
// Try to fetch the existing keychain item that matches the query.
|
||||
var queryResult: AnyObject?
|
||||
let status = withUnsafeMutablePointer(to: &queryResult) {
|
||||
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
|
||||
}
|
||||
|
||||
// Check the return status and throw an error if appropriate.
|
||||
guard status != errSecItemNotFound else { throw KeychainError.noPassword }
|
||||
guard status == noErr else { throw KeychainError.unhandledError(status: status) }
|
||||
|
||||
// Parse the password string from the query result.
|
||||
guard let existingItem = queryResult as? [String : AnyObject],
|
||||
let passwordData = existingItem[kSecValueData as String] as? Data,
|
||||
let password = String(data: passwordData, encoding: String.Encoding.utf8)
|
||||
else {
|
||||
throw KeychainError.unexpectedPasswordData
|
||||
}
|
||||
|
||||
return password
|
||||
}
|
||||
|
||||
func savePassword(_ password: String) throws {
|
||||
// Encode the password into an Data object.
|
||||
let encodedPassword = password.data(using: String.Encoding.utf8)!
|
||||
|
||||
do {
|
||||
// Check for an existing item in the keychain.
|
||||
try _ = readPassword()
|
||||
|
||||
// Update the existing item with the new password.
|
||||
var attributesToUpdate = [String : AnyObject]()
|
||||
attributesToUpdate[kSecValueData as String] = encodedPassword as AnyObject?
|
||||
|
||||
let query = KeychainPasswordItem.keychainQuery(withService: service, account: account, accessGroup: accessGroup)
|
||||
let status = SecItemUpdate(query as CFDictionary, attributesToUpdate as CFDictionary)
|
||||
|
||||
// Throw an error if an unexpected status was returned.
|
||||
guard status == noErr else { throw KeychainError.unhandledError(status: status) }
|
||||
}
|
||||
catch KeychainError.noPassword {
|
||||
/*
|
||||
No password was found in the keychain. Create a dictionary to save
|
||||
as a new keychain item.
|
||||
*/
|
||||
var newItem = KeychainPasswordItem.keychainQuery(withService: service, account: account, accessGroup: accessGroup)
|
||||
newItem[kSecValueData as String] = encodedPassword as AnyObject?
|
||||
|
||||
// Add a the new item to the keychain.
|
||||
let status = SecItemAdd(newItem as CFDictionary, nil)
|
||||
|
||||
// Throw an error if an unexpected status was returned.
|
||||
guard status == noErr else { throw KeychainError.unhandledError(status: status) }
|
||||
}
|
||||
}
|
||||
|
||||
mutating func renameAccount(_ newAccountName: String) throws {
|
||||
// Try to update an existing item with the new account name.
|
||||
var attributesToUpdate = [String : AnyObject]()
|
||||
attributesToUpdate[kSecAttrAccount as String] = newAccountName as AnyObject?
|
||||
|
||||
let query = KeychainPasswordItem.keychainQuery(withService: service, account: self.account, accessGroup: accessGroup)
|
||||
let status = SecItemUpdate(query as CFDictionary, attributesToUpdate as CFDictionary)
|
||||
|
||||
// Throw an error if an unexpected status was returned.
|
||||
guard status == noErr || status == errSecItemNotFound else { throw KeychainError.unhandledError(status: status) }
|
||||
|
||||
self.account = newAccountName
|
||||
}
|
||||
|
||||
func deleteItem() throws {
|
||||
// Delete the existing item from the keychain.
|
||||
let query = KeychainPasswordItem.keychainQuery(withService: service, account: account, accessGroup: accessGroup)
|
||||
let status = SecItemDelete(query as CFDictionary)
|
||||
|
||||
// Throw an error if an unexpected status was returned.
|
||||
guard status == noErr || status == errSecItemNotFound else { throw KeychainError.unhandledError(status: status) }
|
||||
}
|
||||
|
||||
static func passwordItems(forService service: String, accessGroup: String? = nil) throws -> [KeychainPasswordItem] {
|
||||
// Build a query for all items that match the service and access group.
|
||||
var query = KeychainPasswordItem.keychainQuery(withService: service, accessGroup: accessGroup)
|
||||
query[kSecMatchLimit as String] = kSecMatchLimitAll
|
||||
query[kSecReturnAttributes as String] = kCFBooleanTrue
|
||||
query[kSecReturnData as String] = kCFBooleanFalse
|
||||
|
||||
// Fetch matching items from the keychain.
|
||||
var queryResult: AnyObject?
|
||||
let status = withUnsafeMutablePointer(to: &queryResult) {
|
||||
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
|
||||
}
|
||||
|
||||
// If no items were found, return an empty array.
|
||||
guard status != errSecItemNotFound else { return [] }
|
||||
|
||||
// Throw an error if an unexpected status was returned.
|
||||
guard status == noErr else { throw KeychainError.unhandledError(status: status) }
|
||||
|
||||
// Cast the query result to an array of dictionaries.
|
||||
guard let resultData = queryResult as? [[String : AnyObject]] else { throw KeychainError.unexpectedItemData }
|
||||
|
||||
// Create a `KeychainPasswordItem` for each dictionary in the query result.
|
||||
var passwordItems = [KeychainPasswordItem]()
|
||||
for result in resultData {
|
||||
guard let account = result[kSecAttrAccount as String] as? String else { throw KeychainError.unexpectedItemData }
|
||||
|
||||
let passwordItem = KeychainPasswordItem(service: service, account: account, accessGroup: accessGroup)
|
||||
passwordItems.append(passwordItem)
|
||||
}
|
||||
|
||||
return passwordItems
|
||||
}
|
||||
|
||||
// MARK: Convenience
|
||||
|
||||
private static func keychainQuery(withService service: String, account: String? = nil, accessGroup: String? = nil) -> [String : AnyObject] {
|
||||
var query = [String : AnyObject]()
|
||||
query[kSecClass as String] = kSecClassGenericPassword
|
||||
query[kSecAttrService as String] = service as AnyObject?
|
||||
|
||||
if let account = account {
|
||||
query[kSecAttrAccount as String] = account as AnyObject?
|
||||
}
|
||||
|
||||
if let accessGroup = accessGroup {
|
||||
query[kSecAttrAccessGroup as String] = accessGroup as AnyObject?
|
||||
}
|
||||
|
||||
return query
|
||||
}
|
||||
}
|
57
Friendvatars/LaunchScreen.storyboard
Normal file
@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13196" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13173"/>
|
||||
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="rwdevcon-bg" translatesAutoresizingMaskIntoConstraints="NO" id="thr-yb-z25">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
</imageView>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="rw-logo" translatesAutoresizingMaskIntoConstraints="NO" id="skm-4Q-SEq">
|
||||
<rect key="frame" x="20" y="166" width="335" height="335"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="skm-4Q-SEq" secondAttribute="height" multiplier="1:1" id="F6J-6J-J5s"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="thr-yb-z25" secondAttribute="trailing" id="0Yk-op-Sbr"/>
|
||||
<constraint firstItem="skm-4Q-SEq" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="0tf-Kh-S2U"/>
|
||||
<constraint firstItem="skm-4Q-SEq" firstAttribute="top" relation="greaterThanOrEqual" secondItem="Bcu-3y-fUS" secondAttribute="top" constant="20" id="45c-ps-A1j"/>
|
||||
<constraint firstAttribute="trailing" secondItem="skm-4Q-SEq" secondAttribute="trailing" constant="20" id="Aji-Ek-k2q"/>
|
||||
<constraint firstItem="Bcu-3y-fUS" firstAttribute="bottom" secondItem="thr-yb-z25" secondAttribute="bottom" id="FXS-f4-xfH"/>
|
||||
<constraint firstItem="skm-4Q-SEq" firstAttribute="width" secondItem="skm-4Q-SEq" secondAttribute="height" multiplier="1:1" id="Q4h-h8-kju"/>
|
||||
<constraint firstItem="Bcu-3y-fUS" firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="skm-4Q-SEq" secondAttribute="bottom" constant="20" id="TPw-KF-H85"/>
|
||||
<constraint firstItem="thr-yb-z25" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="bHm-5w-uXH"/>
|
||||
<constraint firstItem="thr-yb-z25" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="mnU-3N-lrW"/>
|
||||
<constraint firstItem="skm-4Q-SEq" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Ze5-6b-2t3" secondAttribute="leading" constant="20" id="uY3-7w-Cr7"/>
|
||||
<constraint firstItem="skm-4Q-SEq" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="wkC-oo-tPK"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="rw-logo" width="512" height="512"/>
|
||||
<image name="rwdevcon-bg" width="1104" height="1104"/>
|
||||
</resources>
|
||||
</document>
|
22
Friendvatars/NavigationController.swift
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
final class NavigationController: UINavigationController {
|
||||
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return .lightContent
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
navigationBar.tintColor = .white
|
||||
navigationBar.barTintColor = .rwGreen
|
||||
navigationBar.prefersLargeTitles = true
|
||||
navigationBar.titleTextAttributes = [
|
||||
NSAttributedStringKey.foregroundColor: UIColor.white
|
||||
]
|
||||
navigationBar.largeTitleTextAttributes = navigationBar.titleTextAttributes
|
||||
}
|
||||
|
||||
}
|
28
Friendvatars/Settings.swift
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
|
||||
import Foundation
|
||||
|
||||
final class Settings {
|
||||
|
||||
private enum Keys: String {
|
||||
case user = "current_user"
|
||||
}
|
||||
|
||||
static var currentUser: User? {
|
||||
get {
|
||||
guard let data = UserDefaults.standard.data(forKey: Keys.user.rawValue) else {
|
||||
return nil
|
||||
}
|
||||
return try? JSONDecoder().decode(User.self, from: data)
|
||||
}
|
||||
set {
|
||||
if let data = try? JSONEncoder().encode(newValue) {
|
||||
UserDefaults.standard.set(data, forKey: Keys.user.rawValue)
|
||||
} else {
|
||||
UserDefaults.standard.removeObject(forKey: Keys.user.rawValue)
|
||||
}
|
||||
UserDefaults.standard.synchronize()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
72
Friendvatars/SplashViewController.swift
Normal file
@ -0,0 +1,72 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
final class SplashViewController: UIViewController {
|
||||
|
||||
override var prefersStatusBarHidden: Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
private let backgroundImageView = UIImageView()
|
||||
private let logoImageView = UIImageView()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
setupView()
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
if AuthController.isSignedIn {
|
||||
AppController.shared.handleAuthState()
|
||||
} else {
|
||||
DispatchQueue.delay(1) {
|
||||
self.animateAndDismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func setupView() {
|
||||
backgroundImageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
backgroundImageView.contentMode = .scaleAspectFill
|
||||
backgroundImageView.image = #imageLiteral(resourceName: "rwdevcon-bg")
|
||||
|
||||
logoImageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
logoImageView.contentMode = .scaleAspectFit
|
||||
logoImageView.image = #imageLiteral(resourceName: "rw-logo")
|
||||
|
||||
view.addSubview(backgroundImageView)
|
||||
view.addSubview(logoImageView)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
backgroundImageView.topAnchor.constraint(equalTo: view.topAnchor),
|
||||
backgroundImageView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
||||
backgroundImageView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||
backgroundImageView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||||
logoImageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
|
||||
logoImageView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
|
||||
logoImageView.heightAnchor.constraint(equalTo: logoImageView.widthAnchor),
|
||||
logoImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
|
||||
logoImageView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
|
||||
])
|
||||
}
|
||||
|
||||
private func animateAndDismiss() {
|
||||
let animation = CABasicAnimation(keyPath: "transform.scale")
|
||||
|
||||
animation.duration = 0.3
|
||||
animation.fromValue = 1
|
||||
animation.toValue = 0
|
||||
|
||||
CATransaction.begin()
|
||||
CATransaction.setCompletionBlock {
|
||||
AppController.shared.handleAuthState()
|
||||
}
|
||||
logoImageView.layer.add(animation, forKey: "scale")
|
||||
logoImageView.transform = CGAffineTransform(scaleX: 0, y: 0)
|
||||
CATransaction.commit()
|
||||
}
|
||||
|
||||
}
|
8
Friendvatars/UIColor+Additions.swift
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
extension UIColor {
|
||||
|
||||
static let rwGreen = UIColor(red: 0.0/255.0, green: 104.0/255.0, blue: 55.0/255.0, alpha: 1.0)
|
||||
|
||||
}
|
9
Friendvatars/User.swift
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
struct User: Codable {
|
||||
|
||||
let name: String
|
||||
let email: String
|
||||
|
||||
}
|
7
Podfile
Normal file
@ -0,0 +1,7 @@
|
||||
platform :ios, '8.0'
|
||||
use_frameworks!
|
||||
|
||||
target 'Friendvatars' do
|
||||
pod 'CryptoSwift'
|
||||
pod 'KeychainAccess'
|
||||
end
|
20
Podfile.lock
Normal file
@ -0,0 +1,20 @@
|
||||
PODS:
|
||||
- CryptoSwift (0.8.1)
|
||||
- KeychainAccess (3.1.2)
|
||||
|
||||
DEPENDENCIES:
|
||||
- CryptoSwift
|
||||
- KeychainAccess
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/cocoapods/specs.git:
|
||||
- CryptoSwift
|
||||
- KeychainAccess
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
CryptoSwift: 4b07d5b508c1eb67bfa314a727b705f8048a85de
|
||||
KeychainAccess: b3816fddcf28aa29d94b10ec305cd52be14c472b
|
||||
|
||||
PODFILE CHECKSUM: 2ccd80ba9984103c7eb7f1175a88d0a90df6c731
|
||||
|
||||
COCOAPODS: 1.5.3
|
10
Pods/CryptoSwift/LICENSE
generated
Normal file
@ -0,0 +1,10 @@
|
||||
Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin.krzyzanowski@gmail.com>
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
|
||||
- The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
- Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
- This notice may not be removed or altered from any source or binary distribution.
|
431
Pods/CryptoSwift/README.md
generated
Normal file
@ -0,0 +1,431 @@
|
||||
[![Platform](https://img.shields.io/badge/Platforms-ios%20%7C%20macos%20%7C%20watchos%20%7C%20tvos%20%7C%20linux-4E4E4E.svg?colorA=EF5138)](http://cocoadocs.org/docsets/CryptoSwift)
|
||||
[![Swift support](https://img.shields.io/badge/Swift-3.1%20%7C%203.2%20%7C%204.0-lightgrey.svg?colorA=EF5138&colorB=4E4E4E)](#swift-versions-support)
|
||||
[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/CryptoSwift.svg?style=flat&label=CocoaPods)](https://cocoapods.org/pods/CryptoSwift)
|
||||
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-brightgreen.svg?style=flat&colorB=64A5DE)](https://github.com/apple/swift-package-manager)
|
||||
[![Swift Package Manager compatible](https://img.shields.io/badge/SPM-compatible-brightgreen.svg?style=flat&colorB=64A5DE)](https://github.com/apple/swift-package-manager)
|
||||
[![Twitter](https://img.shields.io/badge/twitter-@krzyzanowskim-blue.svg?style=flat&colorB=64A5DE&label=Twitter)](http://twitter.com/krzyzanowskim)
|
||||
|
||||
# CryptoSwift
|
||||
|
||||
Crypto related functions and helpers for [Swift](https://swift.org) implemented in Swift. ([#PureSwift](https://twitter.com/hashtag/pureswift))
|
||||
|
||||
# Table of Contents
|
||||
- [Requirements](#requirements)
|
||||
- [Features](#features)
|
||||
- [Contribution](#contribution)
|
||||
- [Installation](#installation)
|
||||
- [Swift versions](#swift-versions-support)
|
||||
- [Usage](#usage)
|
||||
- [Author](#author)
|
||||
- [License](#license)
|
||||
- [Changelog](#changelog)
|
||||
|
||||
## Requirements
|
||||
Good mood
|
||||
|
||||
## Features
|
||||
|
||||
- Easy to use
|
||||
- Convenient extensions for String and Data
|
||||
- Support for incremental updates (stream, ...)
|
||||
- iOS, macOS, AppleTV, watchOS, Linux support
|
||||
|
||||
## Donation
|
||||
[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=92Z6U3LBHF9J4) to make the CryptoSwift awesome! Thank you.
|
||||
|
||||
#### Hash (Digest)
|
||||
- [MD5](http://tools.ietf.org/html/rfc1321)
|
||||
- [SHA1](http://tools.ietf.org/html/rfc3174)
|
||||
- [SHA224](http://tools.ietf.org/html/rfc6234)
|
||||
- [SHA256](http://tools.ietf.org/html/rfc6234)
|
||||
- [SHA384](http://tools.ietf.org/html/rfc6234)
|
||||
- [SHA512](http://tools.ietf.org/html/rfc6234)
|
||||
- [SHA3](http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf)
|
||||
|
||||
#### Cyclic Redundancy Check (CRC)
|
||||
- [CRC32](http://en.wikipedia.org/wiki/Cyclic_redundancy_check)
|
||||
- [CRC16](http://en.wikipedia.org/wiki/Cyclic_redundancy_check)
|
||||
|
||||
#### Cipher
|
||||
- [AES-128, AES-192, AES-256](http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf)
|
||||
- [ChaCha20](http://cr.yp.to/chacha/chacha-20080128.pdf)
|
||||
- [Rabbit](https://tools.ietf.org/html/rfc4503)
|
||||
- [Blowfish](https://www.schneier.com/academic/blowfish/)
|
||||
|
||||
#### Message authenticators
|
||||
- [Poly1305](http://cr.yp.to/mac/poly1305-20050329.pdf)
|
||||
- [HMAC](https://www.ietf.org/rfc/rfc2104.txt) MD5, SHA1, SHA256
|
||||
|
||||
#### Cipher block mode
|
||||
- Electronic codebook ([ECB](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_.28ECB.29))
|
||||
- Cipher-block chaining ([CBC](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher-block_chaining_.28CBC.29))
|
||||
- Propagating Cipher Block Chaining ([PCBC](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Propagating_Cipher_Block_Chaining_.28PCBC.29))
|
||||
- Cipher feedback ([CFB](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_feedback_.28CFB.29))
|
||||
- Output Feedback ([OFB](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Output_Feedback_.28OFB.29))
|
||||
- Counter ([CTR](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_.28CTR.29))
|
||||
|
||||
#### Password-Based Key Derivation Function
|
||||
- [PBKDF1](http://tools.ietf.org/html/rfc2898#section-5.1) (Password-Based Key Derivation Function 1)
|
||||
- [PBKDF2](http://tools.ietf.org/html/rfc2898#section-5.2) (Password-Based Key Derivation Function 2)
|
||||
- [HKDF](https://tools.ietf.org/html/rfc5869) (HMAC-based Extract-and-Expand Key Derivation Function)
|
||||
|
||||
#### Data padding
|
||||
- PKCS#5
|
||||
- [PKCS#7](http://tools.ietf.org/html/rfc5652#section-6.3)
|
||||
- [Zero padding](https://en.wikipedia.org/wiki/Padding_(cryptography)#Zero_padding)
|
||||
- No padding
|
||||
|
||||
## Why
|
||||
[Why?](https://github.com/krzyzanowskim/CryptoSwift/issues/5) [Because I can](https://github.com/krzyzanowskim/CryptoSwift/issues/5#issuecomment-53379391).
|
||||
|
||||
## Contribution
|
||||
|
||||
For the latest version, please check [develop](https://github.com/krzyzanowskim/CryptoSwift/tree/develop) branch. Changes from this branch will be merged into the [master](https://github.com/krzyzanowskim/CryptoSwift/tree/master) branch at some point.
|
||||
|
||||
- If you want to contribute, submit a [pull request](https://github.com/krzyzanowskim/CryptoSwift/pulls) against a development `develop` branch.
|
||||
- If you found a bug, [open an issue](https://github.com/krzyzanowskim/CryptoSwift/issues).
|
||||
- If you have a feature request, [open an issue](https://github.com/krzyzanowskim/CryptoSwift/issues).
|
||||
|
||||
## Installation
|
||||
|
||||
To install CryptoSwift, add it as a submodule to your project (on the top level project directory):
|
||||
|
||||
git submodule add https://github.com/krzyzanowskim/CryptoSwift.git
|
||||
|
||||
It is recommended to enable [Whole-Module Optimization](https://swift.org/blog/whole-module-optimizations/) to gain better performance. Non-optimized build results in significantly worse performance.
|
||||
|
||||
#### Embedded Framework
|
||||
|
||||
Embedded frameworks require a minimum deployment target of iOS 8 or OS X Mavericks (10.9). Drag the `CryptoSwift.xcodeproj` file into your Xcode project, and add appropriate framework as a dependency to your target. Now select your App and choose the General tab for the app target. Find *Embedded Binaries* and press "+", then select `CryptoSwift.framework` (iOS, OS X, watchOS or tvOS)
|
||||
|
||||
![](https://cloud.githubusercontent.com/assets/758033/10834511/25a26852-7e9a-11e5-8c01-6cc8f1838459.png)
|
||||
|
||||
Sometimes "embedded framework" option is not available. In that case, you have to add new build phase for the target
|
||||
|
||||
![](https://cloud.githubusercontent.com/assets/758033/18415615/d5edabb0-77f8-11e6-8c94-f41d9fc2b8cb.png)
|
||||
|
||||
##### iOS, macOS, watchOS, tvOS
|
||||
|
||||
In the project, you'll find [single scheme](http://promisekit.org/news/2016/08/Multiplatform-Single-Scheme-Xcode-Projects/) for all platforms:
|
||||
- CryptoSwift
|
||||
|
||||
#### Swift versions support
|
||||
|
||||
- Swift 1.2: branch [swift12](https://github.com/krzyzanowskim/CryptoSwift/tree/swift12) version <= 0.0.13
|
||||
- Swift 2.1: branch [swift21](https://github.com/krzyzanowskim/CryptoSwift/tree/swift21) version <= 0.2.3
|
||||
- Swift 2.2, 2.3: branch [swift2](https://github.com/krzyzanowskim/CryptoSwift/tree/swift2) version <= 0.5.2
|
||||
- Swift 3.1, branch [swift3](https://github.com/krzyzanowskim/CryptoSwift/tree/swift3) version <= 0.6.9
|
||||
- Swift 3.2, branch [swift32](https://github.com/krzyzanowskim/CryptoSwift/tree/swift32) version = 0.7.0
|
||||
- Swift 4.0, branch [master](https://github.com/krzyzanowskim/CryptoSwift/tree/master) version >= 0.7.1
|
||||
|
||||
#### CocoaPods
|
||||
|
||||
You can use [CocoaPods](http://cocoapods.org/?q=cryptoSwift).
|
||||
|
||||
```ruby
|
||||
platform :ios, '8.0'
|
||||
use_frameworks!
|
||||
|
||||
target 'MyApp' do
|
||||
pod 'CryptoSwift'
|
||||
end
|
||||
```
|
||||
|
||||
or for newest version from specified branch of code:
|
||||
|
||||
```ruby
|
||||
pod 'CryptoSwift', :git => "https://github.com/krzyzanowskim/CryptoSwift", :branch => "master"
|
||||
```
|
||||
|
||||
Bear in mind that CocoaPods will build CryptoSwift without [Whole-Module Optimization](https://swift.org/blog/whole-module-optimizations/) that my impact performance. You can change it manually after installation, or use [cocoapods-wholemodule](https://github.com/jedlewison/cocoapods-wholemodule) plugin.
|
||||
|
||||
#### Carthage
|
||||
You can use [Carthage](https://github.com/Carthage/Carthage).
|
||||
Specify in Cartfile:
|
||||
|
||||
```ruby
|
||||
github "krzyzanowskim/CryptoSwift"
|
||||
```
|
||||
|
||||
Run `carthage` to build the framework and drag the built CryptoSwift.framework into your Xcode project. Follow [build instructions](https://github.com/Carthage/Carthage#getting-started). [Common issues](https://github.com/krzyzanowskim/CryptoSwift/issues/492#issuecomment-330822874).
|
||||
|
||||
#### Swift Package Manager
|
||||
|
||||
You can use [Swift Package Manager](https://swift.org/package-manager/) and specify dependency in `Package.swift` by adding this:
|
||||
|
||||
```swift
|
||||
dependencies: [
|
||||
.Package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", majorVersion: 0)
|
||||
]
|
||||
```
|
||||
|
||||
or more strict
|
||||
|
||||
```swift
|
||||
dependencies: [
|
||||
.Package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", "0.7.2"),
|
||||
]
|
||||
```
|
||||
|
||||
See: [Package.swift - manual](http://blog.krzyzanowskim.com/2016/08/09/package-swift-manual/)
|
||||
|
||||
## Usage
|
||||
|
||||
* [Basics (data types, conversion, ...)](#basics)
|
||||
* [Digest (MD5, SHA...)](#calculate-digest)
|
||||
* [Message authenticators (HMAC...)](#message-authenticators-1)
|
||||
* [Password-Based Key Derivation Function (PBKDF2, ...)](#password-based-key-derivation-functions)
|
||||
* [HMAC-based Key Derivation Function (HKDF)](#hmac-based-key-derivation-function)
|
||||
* [Data Padding](#data-padding)
|
||||
* [ChaCha20](#chacha20)
|
||||
* [Rabbit](#rabbit)
|
||||
* [Blowfish](#blowfish)
|
||||
* [Advanced Encryption Standard (AES)](#aes)
|
||||
|
||||
|
||||
also check [Playground](/CryptoSwift.playground/Contents.swift)
|
||||
|
||||
##### Basics
|
||||
|
||||
```swift
|
||||
import CryptoSwift
|
||||
```
|
||||
|
||||
CryptoSwift uses array of bytes aka `Array<UInt8>` as a base type for all operations. Every data may be converted to a stream of bytes. You will find convenience functions that accept `String` or `Data`, and it will be internally converted to the array of bytes.
|
||||
|
||||
##### Data types conversion
|
||||
|
||||
For you convenience **CryptoSwift** provides two functions to easily convert array of bytes to `Data` and another way around:
|
||||
|
||||
Data from bytes:
|
||||
|
||||
```swift
|
||||
let data = Data(bytes: [0x01, 0x02, 0x03])
|
||||
```
|
||||
|
||||
`Data` to `Array<UInt8>`
|
||||
|
||||
```swift
|
||||
let bytes = data.bytes // [1,2,3]
|
||||
```
|
||||
|
||||
[Hexadecimal](https://en.wikipedia.org/wiki/Hexadecimal) encoding:
|
||||
|
||||
```swift
|
||||
let bytes = Array<UInt8>(hex: "0x010203") // [1,2,3]
|
||||
let hex = bytes.toHexString() // "010203"
|
||||
```
|
||||
|
||||
Build bytes out of `String`
|
||||
```swift
|
||||
let bytes: Array<UInt8> = "password".bytes // Array("password".utf8)
|
||||
```
|
||||
|
||||
Also... check out helpers that work with **Base64** encoded data:
|
||||
```swift
|
||||
"aPf/i9th9iX+vf49eR7PYk2q7S5xmm3jkRLejgzHNJs=".decryptBase64ToString(cipher)
|
||||
"aPf/i9th9iX+vf49eR7PYk2q7S5xmm3jkRLejgzHNJs=".decryptBase64(cipher)
|
||||
bytes.toBase64()
|
||||
```
|
||||
|
||||
##### Calculate Digest
|
||||
|
||||
Hashing a data or array of bytes (aka `Array<UInt8>`)
|
||||
```swift
|
||||
/* Hash struct usage */
|
||||
let bytes:Array<UInt8> = [0x01, 0x02, 0x03]
|
||||
let digest = input.md5()
|
||||
let digest = Digest.md5(bytes)
|
||||
```
|
||||
|
||||
```swift
|
||||
let data = Data(bytes: [0x01, 0x02, 0x03])
|
||||
|
||||
let hash = data.md5()
|
||||
let hash = data.sha1()
|
||||
let hash = data.sha224()
|
||||
let hash = data.sha256()
|
||||
let hash = data.sha384()
|
||||
let hash = data.sha512()
|
||||
```
|
||||
```swift
|
||||
do {
|
||||
var digest = MD5()
|
||||
let partial1 = try digest.update(withBytes: [0x31, 0x32])
|
||||
let partial2 = try digest.update(withBytes: [0x33])
|
||||
let result = try digest.finish()
|
||||
} catch { }
|
||||
```
|
||||
|
||||
Hashing a String and printing result
|
||||
|
||||
```swift
|
||||
let hash = "123".md5() // "123".bytes.md5()
|
||||
```
|
||||
|
||||
##### Calculate CRC
|
||||
|
||||
```swift
|
||||
bytes.crc16()
|
||||
data.crc16()
|
||||
|
||||
bytes.crc32()
|
||||
data.crc32()
|
||||
```
|
||||
|
||||
##### Message authenticators
|
||||
|
||||
```swift
|
||||
// Calculate Message Authentication Code (MAC) for message
|
||||
let key:Array<UInt8> = [1,2,3,4,5,6,7,8,9,10,...]
|
||||
|
||||
try Poly1305(key: key).authenticate(bytes)
|
||||
try HMAC(key: key, variant: .sha256).authenticate(bytes)
|
||||
```
|
||||
|
||||
##### Password-Based Key Derivation Functions
|
||||
|
||||
```swift
|
||||
let password: Array<UInt8> = Array("s33krit".utf8)
|
||||
let salt: Array<UInt8> = Array("nacllcan".utf8)
|
||||
|
||||
try PKCS5.PBKDF2(password: password, salt: salt, iterations: 4096, variant: .sha256).calculate()
|
||||
```
|
||||
|
||||
##### HMAC-based Key Derivation Function
|
||||
|
||||
```swift
|
||||
let password: Array<UInt8> = Array("s33krit".utf8)
|
||||
let salt: Array<UInt8> = Array("nacllcan".utf8)
|
||||
|
||||
try HKDF(password: password, salt: salt, variant: .sha256).calculate()
|
||||
```
|
||||
|
||||
##### Data Padding
|
||||
|
||||
Some content-encryption algorithms assume the input length is a multiple of `k` octets, where `k` is greater than one. For such algorithms, the input shall be padded.
|
||||
|
||||
```swift
|
||||
Padding.pkcs7.add(to: bytes, blockSize: AES.blockSize)
|
||||
```
|
||||
|
||||
#### Working with Ciphers
|
||||
##### ChaCha20
|
||||
|
||||
```swift
|
||||
let encrypted = try ChaCha20(key: key, iv: iv).encrypt(message)
|
||||
let decrypted = try ChaCha20(key: key, iv: iv).decrypt(encrypted)
|
||||
```
|
||||
|
||||
##### Rabbit
|
||||
|
||||
```swift
|
||||
let encrypted = try Rabbit(key: key, iv: iv).encrypt(message)
|
||||
let decrypted = try Rabbit(key: key, iv: iv).decrypt(encrypted)
|
||||
```
|
||||
##### Blowfish
|
||||
|
||||
```swift
|
||||
let encrypted = try Blowfish(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7).encrypt(message)
|
||||
let decrypted = try Blowfish(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7).decrypt(encrypted)
|
||||
```
|
||||
|
||||
##### AES
|
||||
|
||||
Notice regarding padding: *Manual padding of data is optional, and CryptoSwift is using PKCS7 padding by default. If you need manually disable/enable padding, you can do this by setting parameter for __AES__ class*
|
||||
|
||||
Variant of AES encryption (AES-128, AES-192, AES-256) depends on given key length:
|
||||
|
||||
- AES-128 = 16 bytes
|
||||
- AES-192 = 24 bytes
|
||||
- AES-256 = 32 bytes
|
||||
|
||||
AES-256 example
|
||||
```swift
|
||||
try AES(key: [1,2,3,...,32], blockMode: .CBC(iv: [1,2,3,...,16]), padding: .pkcs7)
|
||||
```
|
||||
|
||||
###### All at once
|
||||
```swift
|
||||
do {
|
||||
let aes = try AES(key: "passwordpassword", iv: "drowssapdrowssap") // aes128
|
||||
let ciphertext = try aes.encrypt(Array("Nullam quis risus eget urna mollis ornare vel eu leo.".utf8))
|
||||
} catch { }
|
||||
```
|
||||
|
||||
###### Incremental updates
|
||||
|
||||
Incremental operations use instance of Cryptor and encrypt/decrypt one part at a time, this way you can save on memory for large files.
|
||||
|
||||
```swift
|
||||
do {
|
||||
var encryptor = try AES(key: "passwordpassword", iv: "drowssapdrowssap").makeEncryptor()
|
||||
|
||||
var ciphertext = Array<UInt8>()
|
||||
// aggregate partial results
|
||||
ciphertext += try encryptor.update(withBytes: Array("Nullam quis risus ".utf8))
|
||||
ciphertext += try encryptor.update(withBytes: Array("eget urna mollis ".utf8))
|
||||
ciphertext += try encryptor.update(withBytes: Array("ornare vel eu leo.".utf8))
|
||||
// finish at the end
|
||||
ciphertext += try encryptor.finish()
|
||||
|
||||
print(ciphertext.toHexString())
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
```
|
||||
|
||||
See [Playground](/CryptoSwift.playground/Contents.swift) for sample code that work with stream.
|
||||
|
||||
###### AES Advanced usage
|
||||
```swift
|
||||
let input: Array<UInt8> = [0,1,2,3,4,5,6,7,8,9]
|
||||
|
||||
let key: Array<UInt8> = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
|
||||
let iv: Array<UInt8> = AES.randomIV(AES.blockSize)
|
||||
|
||||
do {
|
||||
let encrypted = try AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7).encrypt(input)
|
||||
let decrypted = try AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7).decrypt(encrypted)
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
```
|
||||
|
||||
AES without data padding
|
||||
|
||||
```swift
|
||||
let input: Array<UInt8> = [0,1,2,3,4,5,6,7,8,9]
|
||||
let encrypted: Array<UInt8> = try! AES(key: Array("secret0key000000".utf8), blockMode: .CBC(iv: Array("0123456789012345".utf8)), padding: .noPadding).encrypt(input)
|
||||
```
|
||||
|
||||
Using convenience extensions
|
||||
|
||||
```swift
|
||||
let plain = Data(bytes: [0x01, 0x02, 0x03])
|
||||
let encrypted = try! plain.encrypt(ChaCha20(key: key, iv: iv))
|
||||
let decrypted = try! encrypted.decrypt(ChaCha20(key: key, iv: iv))
|
||||
```
|
||||
|
||||
## Author
|
||||
|
||||
CryptoSwift is owned and maintained by [Marcin Krzyżanowski](http://www.krzyzanowskim.com)
|
||||
|
||||
You can follow me on Twitter at [@krzyzanowskim](http://twitter.com/krzyzanowskim) for project updates and releases.
|
||||
|
||||
## License
|
||||
|
||||
Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
|
||||
- The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, **an acknowledgment in the product documentation is required**.
|
||||
- Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
- This notice may not be removed or altered from any source or binary distribution.
|
||||
|
||||
## Changelog
|
||||
|
||||
See [CHANGELOG](./CHANGELOG) file.
|
142
Pods/CryptoSwift/Sources/CryptoSwift/AES.Cryptors.swift
generated
Normal file
@ -0,0 +1,142 @@
|
||||
//
|
||||
// AES.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
// MARK: Cryptors
|
||||
extension AES: Cryptors {
|
||||
public func makeEncryptor() throws -> AES.Encryptor {
|
||||
return try AES.Encryptor(aes: self)
|
||||
}
|
||||
|
||||
public func makeDecryptor() throws -> AES.Decryptor {
|
||||
return try AES.Decryptor(aes: self)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Encryptor
|
||||
extension AES {
|
||||
public struct Encryptor: Updatable {
|
||||
private var worker: BlockModeWorker
|
||||
private let padding: Padding
|
||||
private var accumulated = Array<UInt8>()
|
||||
private var processedBytesTotalCount: Int = 0
|
||||
private let paddingRequired: Bool
|
||||
|
||||
init(aes: AES) throws {
|
||||
padding = aes.padding
|
||||
worker = try aes.blockMode.worker(blockSize: AES.blockSize, cipherOperation: aes.encrypt)
|
||||
paddingRequired = aes.blockMode.options.contains(.paddingRequired)
|
||||
}
|
||||
|
||||
public mutating func update(withBytes bytes: ArraySlice<UInt8>, isLast: Bool = false) throws -> Array<UInt8> {
|
||||
accumulated += bytes
|
||||
|
||||
if isLast {
|
||||
accumulated = padding.add(to: accumulated, blockSize: AES.blockSize)
|
||||
}
|
||||
|
||||
var processedBytes = 0
|
||||
var encrypted = Array<UInt8>(reserveCapacity: accumulated.count)
|
||||
for chunk in accumulated.batched(by: AES.blockSize) {
|
||||
if isLast || (accumulated.count - processedBytes) >= AES.blockSize {
|
||||
encrypted += worker.encrypt(chunk)
|
||||
processedBytes += chunk.count
|
||||
}
|
||||
}
|
||||
accumulated.removeFirst(processedBytes)
|
||||
processedBytesTotalCount += processedBytes
|
||||
return encrypted
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Decryptor
|
||||
extension AES {
|
||||
|
||||
public struct Decryptor: RandomAccessCryptor {
|
||||
private var worker: BlockModeWorker
|
||||
private let padding: Padding
|
||||
private var accumulated = Array<UInt8>()
|
||||
private var processedBytesTotalCount: Int = 0
|
||||
private let paddingRequired: Bool
|
||||
|
||||
private var offset: Int = 0
|
||||
private var offsetToRemove: Int = 0
|
||||
|
||||
init(aes: AES) throws {
|
||||
padding = aes.padding
|
||||
|
||||
switch aes.blockMode {
|
||||
case .CFB, .OFB, .CTR:
|
||||
// CFB, OFB, CTR uses encryptBlock to decrypt
|
||||
worker = try aes.blockMode.worker(blockSize: AES.blockSize, cipherOperation: aes.encrypt)
|
||||
default:
|
||||
worker = try aes.blockMode.worker(blockSize: AES.blockSize, cipherOperation: aes.decrypt)
|
||||
}
|
||||
|
||||
paddingRequired = aes.blockMode.options.contains(.paddingRequired)
|
||||
}
|
||||
|
||||
public mutating func update(withBytes bytes: ArraySlice<UInt8>, isLast: Bool = false) throws -> Array<UInt8> {
|
||||
// prepend "offset" number of bytes at the begining
|
||||
if offset > 0 {
|
||||
accumulated += Array<UInt8>(repeating: 0, count: offset) + bytes
|
||||
offsetToRemove = offset
|
||||
offset = 0
|
||||
} else {
|
||||
accumulated += bytes
|
||||
}
|
||||
|
||||
var processedBytes = 0
|
||||
var plaintext = Array<UInt8>(reserveCapacity: accumulated.count)
|
||||
for chunk in accumulated.batched(by: AES.blockSize) {
|
||||
if isLast || (accumulated.count - processedBytes) >= AES.blockSize {
|
||||
plaintext += worker.decrypt(chunk)
|
||||
|
||||
// remove "offset" from the beginning of first chunk
|
||||
if offsetToRemove > 0 {
|
||||
plaintext.removeFirst(offsetToRemove)
|
||||
offsetToRemove = 0
|
||||
}
|
||||
|
||||
processedBytes += chunk.count
|
||||
}
|
||||
}
|
||||
accumulated.removeFirst(processedBytes)
|
||||
processedBytesTotalCount += processedBytes
|
||||
|
||||
if isLast {
|
||||
plaintext = padding.remove(from: plaintext, blockSize: AES.blockSize)
|
||||
}
|
||||
|
||||
return plaintext
|
||||
}
|
||||
|
||||
@discardableResult public mutating func seek(to position: Int) -> Bool {
|
||||
guard var worker = self.worker as? RandomAccessBlockModeWorker else {
|
||||
return false
|
||||
}
|
||||
|
||||
worker.counter = UInt(position / AES.blockSize)
|
||||
self.worker = worker
|
||||
|
||||
offset = position % AES.blockSize
|
||||
|
||||
accumulated = []
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
532
Pods/CryptoSwift/Sources/CryptoSwift/AES.swift
generated
Normal file
@ -0,0 +1,532 @@
|
||||
//
|
||||
// AES.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
// Implementation of Gladman algorithm http://www.gladman.me.uk/AES
|
||||
//
|
||||
|
||||
/// The Advanced Encryption Standard (AES)
|
||||
public final class AES: BlockCipher {
|
||||
|
||||
public enum Error: Swift.Error {
|
||||
/// Data padding is required
|
||||
case dataPaddingRequired
|
||||
/// Invalid Data
|
||||
case invalidData
|
||||
}
|
||||
|
||||
public enum Variant: Int {
|
||||
case aes128 = 1, aes192, aes256
|
||||
|
||||
var Nk: Int { // Nk words
|
||||
return [4, 6, 8][self.rawValue - 1]
|
||||
}
|
||||
|
||||
var Nb: Int { // Nb words
|
||||
return 4
|
||||
}
|
||||
|
||||
var Nr: Int { // Nr
|
||||
return Nk + 6
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var variantNr: Int = self.variant.Nr
|
||||
private lazy var variantNb: Int = self.variant.Nb
|
||||
private lazy var variantNk: Int = self.variant.Nk
|
||||
|
||||
public static let blockSize: Int = 16 // 128 /8
|
||||
|
||||
public var variant: Variant {
|
||||
switch key.count * 8 {
|
||||
case 128:
|
||||
return .aes128
|
||||
case 192:
|
||||
return .aes192
|
||||
case 256:
|
||||
return .aes256
|
||||
default:
|
||||
preconditionFailure("Unknown AES variant for given key.")
|
||||
}
|
||||
}
|
||||
|
||||
// Parameters
|
||||
let key: Key
|
||||
let blockMode: BlockMode
|
||||
let padding: Padding
|
||||
|
||||
//
|
||||
private lazy var expandedKey: Array<Array<UInt32>> = self.expandKey(self.key, variant: self.variant)
|
||||
private lazy var expandedKeyInv: Array<Array<UInt32>> = self.expandKeyInv(self.key, variant: self.variant)
|
||||
|
||||
private lazy var sBoxes: (sBox: Array<UInt32>, invSBox: Array<UInt32>) = self.calculateSBox()
|
||||
private lazy var sBox: Array<UInt32> = self.sBoxes.sBox
|
||||
private lazy var sBoxInv: Array<UInt32> = self.sBoxes.invSBox
|
||||
|
||||
// Parameters for Linear Congruence Generators
|
||||
private static let Rcon: Array<UInt8> = [
|
||||
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
|
||||
0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
|
||||
0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
|
||||
0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
|
||||
0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
|
||||
0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
|
||||
0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
|
||||
0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
|
||||
0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
|
||||
0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
|
||||
0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
|
||||
0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
|
||||
0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
|
||||
0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
|
||||
0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
|
||||
0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d,
|
||||
]
|
||||
|
||||
private static let T0: Array<UInt32> = [0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0xdf2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x3010102, 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0xbf0f0fb, 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x2f7f7f5, 0x4fcccc83, 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x8f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, 0xc040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0xf05050a, 0xb59a9a2f, 0x907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413, 0xf55353a6, 0x68d1d1b9, 0x0, 0x2cededc1, 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a, 0x10f9f9e9, 0x6020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x4f5f5f1, 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5, 0xef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0xa06060c, 0x6c242448, 0xe45c5cb8, 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda, 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8, 0xfa5656ac, 0x7f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x5030306, 0x1f6f6f7, 0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c]
|
||||
private static let T0_INV: Array<UInt32> = [0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d, 0x2752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, 0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, 0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566, 0x728ebb2, 0x3c2b52f, 0x9a7bc586, 0xa50837d3, 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x69f715e, 0x51106ebd, 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491, 0x55dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879, 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x0, 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0xfe75793, 0xd296eeb4, 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c, 0xaba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0xb0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8, 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322, 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, 0xe49d3a2c, 0xd927850, 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf, 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x97826cd, 0xf418596e, 0x1b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa, 0x8cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235, 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1, 0xf7daec41, 0xe50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546, 0x4ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, 0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478, 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0xc25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0]
|
||||
private static let T1: Array<UInt32> = [0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d, 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x1010203, 0x6767cea9, 0x2b2b567d, 0xfefee719, 0xd7d7b562, 0xabab4de6, 0x7676ec9a, 0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87, 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b, 0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7, 0x7272e496, 0xc0c09b5b, 0xb7b775c2, 0xfdfde11c, 0x93933dae, 0x26264c6a, 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f, 0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908, 0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f, 0x404080c, 0xc7c79552, 0x23234665, 0xc3c39d5e, 0x18183028, 0x969637a1, 0x5050a0f, 0x9a9a2fb5, 0x7070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d, 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, 0x909121b, 0x83831d9e, 0x2c2c5874, 0x1a1a342e, 0x1b1b362d, 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb, 0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce, 0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397, 0x5353a6f5, 0xd1d1b968, 0x0, 0xededc12c, 0x20204060, 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed, 0x6a6ad4be, 0xcbcb8d46, 0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a, 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16, 0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194, 0x45458acf, 0xf9f9e910, 0x2020406, 0x7f7ffe81, 0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3, 0x5151a2f3, 0xa3a35dfe, 0x404080c0, 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104, 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, 0x10102030, 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d, 0xcdcd814c, 0xc0c1814, 0x13132635, 0xececc32f, 0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39, 0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47, 0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695, 0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e, 0x90903bab, 0x88880b83, 0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c, 0xdedea779, 0x5e5ebce2, 0xb0b161d, 0xdbdbad76, 0xe0e0db3b, 0x32326456, 0x3a3a744e, 0xa0a141e, 0x494992db, 0x6060c0a, 0x2424486c, 0x5c5cb8e4, 0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4, 0xe4e4d337, 0x7979f28b, 0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7, 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, 0x6c6cd8b4, 0x5656acfa, 0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x8081018, 0xbaba6fd5, 0x7878f088, 0x25254a6f, 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751, 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, 0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, 0x7070e090, 0x3e3e7c42, 0xb5b571c4, 0x6666ccaa, 0x484890d8, 0x3030605, 0xf6f6f701, 0xe0e1c12, 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0, 0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9, 0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233, 0x6969d2bb, 0xd9d9a970, 0x8e8e0789, 0x949433a7, 0x9b9b2db6, 0x1e1e3c22, 0x87871592, 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a, 0x8c8c038f, 0xa1a159f8, 0x89890980, 0xd0d1a17, 0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8, 0x414182c3, 0x999929b0, 0x2d2d5a77, 0xf0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a]
|
||||
private static let T1_INV: Array<UInt32> = [0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96, 0x6bab3bcb, 0x459d1ff1, 0x58faacab, 0x3e34b93, 0xfa302055, 0x6d76adf6, 0x76cc8891, 0x4c02f525, 0xd7e54ffc, 0xcb2ac5d7, 0x44352680, 0xa362b58f, 0x5ab1de49, 0x1bba2567, 0xeea4598, 0xc0fe5de1, 0x752fc302, 0xf04c8112, 0x97468da3, 0xf9d36bc6, 0x5f8f03e7, 0x9c921595, 0x7a6dbfeb, 0x595295da, 0x83bed42d, 0x217458d3, 0x69e04929, 0xc8c98e44, 0x89c2756a, 0x798ef478, 0x3e58996b, 0x71b927dd, 0x4fe1beb6, 0xad88f017, 0xac20c966, 0x3ace7db4, 0x4adf6318, 0x311ae582, 0x33519760, 0x7f536245, 0x7764b1e0, 0xae6bbb84, 0xa081fe1c, 0x2b08f994, 0x68487058, 0xfd458f19, 0x6cde9487, 0xf87b52b7, 0xd373ab23, 0x24b72e2, 0x8f1fe357, 0xab55662a, 0x28ebb207, 0xc2b52f03, 0x7bc5869a, 0x837d3a5, 0x872830f2, 0xa5bf23b2, 0x6a0302ba, 0x8216ed5c, 0x1ccf8a2b, 0xb479a792, 0xf207f3f0, 0xe2694ea1, 0xf4da65cd, 0xbe0506d5, 0x6234d11f, 0xfea6c48a, 0x532e349d, 0x55f3a2a0, 0xe18a0532, 0xebf6a475, 0xec830b39, 0xef6040aa, 0x9f715e06, 0x106ebd51, 0x8a213ef9, 0x6dd963d, 0x53eddae, 0xbde64d46, 0x8d5491b5, 0x5dc47105, 0xd406046f, 0x155060ff, 0xfb981924, 0xe9bdd697, 0x434089cc, 0x9ed96777, 0x42e8b0bd, 0x8b890788, 0x5b19e738, 0xeec879db, 0xa7ca147, 0xf427ce9, 0x1e84f8c9, 0x0, 0x86800983, 0xed2b3248, 0x70111eac, 0x725a6c4e, 0xff0efdfb, 0x38850f56, 0xd5ae3d1e, 0x392d3627, 0xd90f0a64, 0xa65c6821, 0x545b9bd1, 0x2e36243a, 0x670a0cb1, 0xe757930f, 0x96eeb4d2, 0x919b1b9e, 0xc5c0804f, 0x20dc61a2, 0x4b775a69, 0x1a121c16, 0xba93e20a, 0x2aa0c0e5, 0xe0223c43, 0x171b121d, 0xd090e0b, 0xc78bf2ad, 0xa8b62db9, 0xa91e14c8, 0x19f15785, 0x775af4c, 0xdd99eebb, 0x607fa3fd, 0x2601f79f, 0xf5725cbc, 0x3b6644c5, 0x7efb5b34, 0x29438b76, 0xc623cbdc, 0xfcedb668, 0xf1e4b863, 0xdc31d7ca, 0x85634210, 0x22971340, 0x11c68420, 0x244a857d, 0x3dbbd2f8, 0x32f9ae11, 0xa129c76d, 0x2f9e1d4b, 0x30b2dcf3, 0x52860dec, 0xe3c177d0, 0x16b32b6c, 0xb970a999, 0x489411fa, 0x64e94722, 0x8cfca8c4, 0x3ff0a01a, 0x2c7d56d8, 0x903322ef, 0x4e4987c7, 0xd138d9c1, 0xa2ca8cfe, 0xbd49836, 0x81f5a6cf, 0xde7aa528, 0x8eb7da26, 0xbfad3fa4, 0x9d3a2ce4, 0x9278500d, 0xcc5f6a9b, 0x467e5462, 0x138df6c2, 0xb8d890e8, 0xf7392e5e, 0xafc382f5, 0x805d9fbe, 0x93d0697c, 0x2dd56fa9, 0x1225cfb3, 0x99acc83b, 0x7d1810a7, 0x639ce86e, 0xbb3bdb7b, 0x7826cd09, 0x18596ef4, 0xb79aec01, 0x9a4f83a8, 0x6e95e665, 0xe6ffaa7e, 0xcfbc2108, 0xe815efe6, 0x9be7bad9, 0x366f4ace, 0x99fead4, 0x7cb029d6, 0xb2a431af, 0x233f2a31, 0x94a5c630, 0x66a235c0, 0xbc4e7437, 0xca82fca6, 0xd090e0b0, 0xd8a73315, 0x9804f14a, 0xdaec41f7, 0x50cd7f0e, 0xf691172f, 0xd64d768d, 0xb0ef434d, 0x4daacc54, 0x496e4df, 0xb5d19ee3, 0x886a4c1b, 0x1f2cc1b8, 0x5165467f, 0xea5e9d04, 0x358c015d, 0x7487fa73, 0x410bfb2e, 0x1d67b35a, 0xd2db9252, 0x5610e933, 0x47d66d13, 0x61d79a8c, 0xca1377a, 0x14f8598e, 0x3c13eb89, 0x27a9ceee, 0xc961b735, 0xe51ce1ed, 0xb1477a3c, 0xdfd29c59, 0x73f2553f, 0xce141879, 0x37c773bf, 0xcdf753ea, 0xaafd5f5b, 0x6f3ddf14, 0xdb447886, 0xf3afca81, 0xc468b93e, 0x3424382c, 0x40a3c25f, 0xc31d1672, 0x25e2bc0c, 0x493c288b, 0x950dff41, 0x1a83971, 0xb30c08de, 0xe4b4d89c, 0xc1566490, 0x84cb7b61, 0xb632d570, 0x5c6c4874, 0x57b8d042]
|
||||
private static let T2: Array<UInt32> = [0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2, 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5, 0x30605030, 0x1020301, 0x67cea967, 0x2b567d2b, 0xfee719fe, 0xd7b562d7, 0xab4de6ab, 0x76ec9a76, 0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d, 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0, 0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4, 0x72e49672, 0xc09b5bc0, 0xb775c2b7, 0xfde11cfd, 0x933dae93, 0x264c6a26, 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc, 0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1, 0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15, 0x4080c04, 0xc79552c7, 0x23466523, 0xc39d5ec3, 0x18302818, 0x9637a196, 0x50a0f05, 0x9a2fb59a, 0x70e0907, 0x12243612, 0x801b9b80, 0xe2df3de2, 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, 0x9121b09, 0x831d9e83, 0x2c58742c, 0x1a342e1a, 0x1b362d1b, 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0, 0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3, 0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784, 0x53a6f553, 0xd1b968d1, 0x0, 0xedc12ced, 0x20406020, 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b, 0x6ad4be6a, 0xcb8d46cb, 0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf, 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb, 0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485, 0x458acf45, 0xf9e910f9, 0x2040602, 0x7ffe817f, 0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8, 0x51a2f351, 0xa35dfea3, 0x4080c040, 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5, 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, 0x10203010, 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2, 0xcd814ccd, 0xc18140c, 0x13263513, 0xecc32fec, 0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917, 0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d, 0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573, 0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a, 0x903bab90, 0x880b8388, 0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14, 0xdea779de, 0x5ebce25e, 0xb161d0b, 0xdbad76db, 0xe0db3be0, 0x32645632, 0x3a744e3a, 0xa141e0a, 0x4992db49, 0x60c0a06, 0x24486c24, 0x5cb8e45c, 0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495, 0xe4d337e4, 0x79f28b79, 0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d, 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, 0x6cd8b46c, 0x56acfa56, 0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x8101808, 0xba6fd5ba, 0x78f08878, 0x254a6f25, 0x2e5c722e, 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6, 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, 0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, 0x70e09070, 0x3e7c423e, 0xb571c4b5, 0x66ccaa66, 0x4890d848, 0x3060503, 0xf6f701f6, 0xe1c120e, 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9, 0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e, 0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311, 0x69d2bb69, 0xd9a970d9, 0x8e07898e, 0x9433a794, 0x9b2db69b, 0x1e3c221e, 0x87159287, 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf, 0x8c038f8c, 0xa159f8a1, 0x89098089, 0xd1a170d, 0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868, 0x4182c341, 0x9929b099, 0x2d5a772d, 0xf1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16]
|
||||
private static let T2_INV: Array<UInt32> = [0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e, 0xab3bcb6b, 0x9d1ff145, 0xfaacab58, 0xe34b9303, 0x302055fa, 0x76adf66d, 0xcc889176, 0x2f5254c, 0xe54ffcd7, 0x2ac5d7cb, 0x35268044, 0x62b58fa3, 0xb1de495a, 0xba25671b, 0xea45980e, 0xfe5de1c0, 0x2fc30275, 0x4c8112f0, 0x468da397, 0xd36bc6f9, 0x8f03e75f, 0x9215959c, 0x6dbfeb7a, 0x5295da59, 0xbed42d83, 0x7458d321, 0xe0492969, 0xc98e44c8, 0xc2756a89, 0x8ef47879, 0x58996b3e, 0xb927dd71, 0xe1beb64f, 0x88f017ad, 0x20c966ac, 0xce7db43a, 0xdf63184a, 0x1ae58231, 0x51976033, 0x5362457f, 0x64b1e077, 0x6bbb84ae, 0x81fe1ca0, 0x8f9942b, 0x48705868, 0x458f19fd, 0xde94876c, 0x7b52b7f8, 0x73ab23d3, 0x4b72e202, 0x1fe3578f, 0x55662aab, 0xebb20728, 0xb52f03c2, 0xc5869a7b, 0x37d3a508, 0x2830f287, 0xbf23b2a5, 0x302ba6a, 0x16ed5c82, 0xcf8a2b1c, 0x79a792b4, 0x7f3f0f2, 0x694ea1e2, 0xda65cdf4, 0x506d5be, 0x34d11f62, 0xa6c48afe, 0x2e349d53, 0xf3a2a055, 0x8a0532e1, 0xf6a475eb, 0x830b39ec, 0x6040aaef, 0x715e069f, 0x6ebd5110, 0x213ef98a, 0xdd963d06, 0x3eddae05, 0xe64d46bd, 0x5491b58d, 0xc471055d, 0x6046fd4, 0x5060ff15, 0x981924fb, 0xbdd697e9, 0x4089cc43, 0xd967779e, 0xe8b0bd42, 0x8907888b, 0x19e7385b, 0xc879dbee, 0x7ca1470a, 0x427ce90f, 0x84f8c91e, 0x0, 0x80098386, 0x2b3248ed, 0x111eac70, 0x5a6c4e72, 0xefdfbff, 0x850f5638, 0xae3d1ed5, 0x2d362739, 0xf0a64d9, 0x5c6821a6, 0x5b9bd154, 0x36243a2e, 0xa0cb167, 0x57930fe7, 0xeeb4d296, 0x9b1b9e91, 0xc0804fc5, 0xdc61a220, 0x775a694b, 0x121c161a, 0x93e20aba, 0xa0c0e52a, 0x223c43e0, 0x1b121d17, 0x90e0b0d, 0x8bf2adc7, 0xb62db9a8, 0x1e14c8a9, 0xf1578519, 0x75af4c07, 0x99eebbdd, 0x7fa3fd60, 0x1f79f26, 0x725cbcf5, 0x6644c53b, 0xfb5b347e, 0x438b7629, 0x23cbdcc6, 0xedb668fc, 0xe4b863f1, 0x31d7cadc, 0x63421085, 0x97134022, 0xc6842011, 0x4a857d24, 0xbbd2f83d, 0xf9ae1132, 0x29c76da1, 0x9e1d4b2f, 0xb2dcf330, 0x860dec52, 0xc177d0e3, 0xb32b6c16, 0x70a999b9, 0x9411fa48, 0xe9472264, 0xfca8c48c, 0xf0a01a3f, 0x7d56d82c, 0x3322ef90, 0x4987c74e, 0x38d9c1d1, 0xca8cfea2, 0xd498360b, 0xf5a6cf81, 0x7aa528de, 0xb7da268e, 0xad3fa4bf, 0x3a2ce49d, 0x78500d92, 0x5f6a9bcc, 0x7e546246, 0x8df6c213, 0xd890e8b8, 0x392e5ef7, 0xc382f5af, 0x5d9fbe80, 0xd0697c93, 0xd56fa92d, 0x25cfb312, 0xacc83b99, 0x1810a77d, 0x9ce86e63, 0x3bdb7bbb, 0x26cd0978, 0x596ef418, 0x9aec01b7, 0x4f83a89a, 0x95e6656e, 0xffaa7ee6, 0xbc2108cf, 0x15efe6e8, 0xe7bad99b, 0x6f4ace36, 0x9fead409, 0xb029d67c, 0xa431afb2, 0x3f2a3123, 0xa5c63094, 0xa235c066, 0x4e7437bc, 0x82fca6ca, 0x90e0b0d0, 0xa73315d8, 0x4f14a98, 0xec41f7da, 0xcd7f0e50, 0x91172ff6, 0x4d768dd6, 0xef434db0, 0xaacc544d, 0x96e4df04, 0xd19ee3b5, 0x6a4c1b88, 0x2cc1b81f, 0x65467f51, 0x5e9d04ea, 0x8c015d35, 0x87fa7374, 0xbfb2e41, 0x67b35a1d, 0xdb9252d2, 0x10e93356, 0xd66d1347, 0xd79a8c61, 0xa1377a0c, 0xf8598e14, 0x13eb893c, 0xa9ceee27, 0x61b735c9, 0x1ce1ede5, 0x477a3cb1, 0xd29c59df, 0xf2553f73, 0x141879ce, 0xc773bf37, 0xf753eacd, 0xfd5f5baa, 0x3ddf146f, 0x447886db, 0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40, 0x1d1672c3, 0xe2bc0c25, 0x3c288b49, 0xdff4195, 0xa8397101, 0xc08deb3, 0xb4d89ce4, 0x566490c1, 0xcb7b6184, 0x32d570b6, 0x6c48745c, 0xb8d04257]
|
||||
private static let T3: Array<UInt32> = [0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2, 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x2030101, 0xcea96767, 0x567d2b2b, 0xe719fefe, 0xb562d7d7, 0x4de6abab, 0xec9a7676, 0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d, 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0, 0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4, 0xe4967272, 0x9b5bc0c0, 0x75c2b7b7, 0xe11cfdfd, 0x3dae9393, 0x4c6a2626, 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc, 0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1, 0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515, 0x80c0404, 0x9552c7c7, 0x46652323, 0x9d5ec3c3, 0x30281818, 0x37a19696, 0xa0f0505, 0x2fb59a9a, 0xe090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2, 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, 0x121b0909, 0x1d9e8383, 0x58742c2c, 0x342e1a1a, 0x362d1b1b, 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0, 0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484, 0xa6f55353, 0xb968d1d1, 0x0, 0xc12ceded, 0x40602020, 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b, 0xd4be6a6a, 0x8d46cbcb, 0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf, 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb, 0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585, 0x8acf4545, 0xe910f9f9, 0x4060202, 0xfe817f7f, 0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8, 0xa2f35151, 0x5dfea3a3, 0x80c04040, 0x58a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5, 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, 0x20301010, 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2, 0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec, 0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717, 0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d, 0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373, 0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a, 0x3bab9090, 0xb838888, 0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414, 0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb, 0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, 0x92db4949, 0xc0a0606, 0x486c2424, 0xb8e45c5c, 0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595, 0xd337e4e4, 0xf28b7979, 0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d, 0x18c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, 0xd8b46c6c, 0xacfa5656, 0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808, 0x6fd5baba, 0xf0887878, 0x4a6f2525, 0x5c722e2e, 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6, 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, 0x96dd4b4b, 0x61dcbdbd, 0xd868b8b, 0xf858a8a, 0xe0907070, 0x7c423e3e, 0x71c4b5b5, 0xccaa6666, 0x90d84848, 0x6050303, 0xf701f6f6, 0x1c120e0e, 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9, 0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e, 0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111, 0xd2bb6969, 0xa970d9d9, 0x7898e8e, 0x33a79494, 0x2db69b9b, 0x3c221e1e, 0x15928787, 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf, 0x38f8c8c, 0x59f8a1a1, 0x9808989, 0x1a170d0d, 0x65dabfbf, 0xd731e6e6, 0x84c64242, 0xd0b86868, 0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616]
|
||||
private static let T3_INV: Array<UInt32> = [0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27, 0x3bcb6bab, 0x1ff1459d, 0xacab58fa, 0x4b9303e3, 0x2055fa30, 0xadf66d76, 0x889176cc, 0xf5254c02, 0x4ffcd7e5, 0xc5d7cb2a, 0x26804435, 0xb58fa362, 0xde495ab1, 0x25671bba, 0x45980eea, 0x5de1c0fe, 0xc302752f, 0x8112f04c, 0x8da39746, 0x6bc6f9d3, 0x3e75f8f, 0x15959c92, 0xbfeb7a6d, 0x95da5952, 0xd42d83be, 0x58d32174, 0x492969e0, 0x8e44c8c9, 0x756a89c2, 0xf478798e, 0x996b3e58, 0x27dd71b9, 0xbeb64fe1, 0xf017ad88, 0xc966ac20, 0x7db43ace, 0x63184adf, 0xe582311a, 0x97603351, 0x62457f53, 0xb1e07764, 0xbb84ae6b, 0xfe1ca081, 0xf9942b08, 0x70586848, 0x8f19fd45, 0x94876cde, 0x52b7f87b, 0xab23d373, 0x72e2024b, 0xe3578f1f, 0x662aab55, 0xb20728eb, 0x2f03c2b5, 0x869a7bc5, 0xd3a50837, 0x30f28728, 0x23b2a5bf, 0x2ba6a03, 0xed5c8216, 0x8a2b1ccf, 0xa792b479, 0xf3f0f207, 0x4ea1e269, 0x65cdf4da, 0x6d5be05, 0xd11f6234, 0xc48afea6, 0x349d532e, 0xa2a055f3, 0x532e18a, 0xa475ebf6, 0xb39ec83, 0x40aaef60, 0x5e069f71, 0xbd51106e, 0x3ef98a21, 0x963d06dd, 0xddae053e, 0x4d46bde6, 0x91b58d54, 0x71055dc4, 0x46fd406, 0x60ff1550, 0x1924fb98, 0xd697e9bd, 0x89cc4340, 0x67779ed9, 0xb0bd42e8, 0x7888b89, 0xe7385b19, 0x79dbeec8, 0xa1470a7c, 0x7ce90f42, 0xf8c91e84, 0x0, 0x9838680, 0x3248ed2b, 0x1eac7011, 0x6c4e725a, 0xfdfbff0e, 0xf563885, 0x3d1ed5ae, 0x3627392d, 0xa64d90f, 0x6821a65c, 0x9bd1545b, 0x243a2e36, 0xcb1670a, 0x930fe757, 0xb4d296ee, 0x1b9e919b, 0x804fc5c0, 0x61a220dc, 0x5a694b77, 0x1c161a12, 0xe20aba93, 0xc0e52aa0, 0x3c43e022, 0x121d171b, 0xe0b0d09, 0xf2adc78b, 0x2db9a8b6, 0x14c8a91e, 0x578519f1, 0xaf4c0775, 0xeebbdd99, 0xa3fd607f, 0xf79f2601, 0x5cbcf572, 0x44c53b66, 0x5b347efb, 0x8b762943, 0xcbdcc623, 0xb668fced, 0xb863f1e4, 0xd7cadc31, 0x42108563, 0x13402297, 0x842011c6, 0x857d244a, 0xd2f83dbb, 0xae1132f9, 0xc76da129, 0x1d4b2f9e, 0xdcf330b2, 0xdec5286, 0x77d0e3c1, 0x2b6c16b3, 0xa999b970, 0x11fa4894, 0x472264e9, 0xa8c48cfc, 0xa01a3ff0, 0x56d82c7d, 0x22ef9033, 0x87c74e49, 0xd9c1d138, 0x8cfea2ca, 0x98360bd4, 0xa6cf81f5, 0xa528de7a, 0xda268eb7, 0x3fa4bfad, 0x2ce49d3a, 0x500d9278, 0x6a9bcc5f, 0x5462467e, 0xf6c2138d, 0x90e8b8d8, 0x2e5ef739, 0x82f5afc3, 0x9fbe805d, 0x697c93d0, 0x6fa92dd5, 0xcfb31225, 0xc83b99ac, 0x10a77d18, 0xe86e639c, 0xdb7bbb3b, 0xcd097826, 0x6ef41859, 0xec01b79a, 0x83a89a4f, 0xe6656e95, 0xaa7ee6ff, 0x2108cfbc, 0xefe6e815, 0xbad99be7, 0x4ace366f, 0xead4099f, 0x29d67cb0, 0x31afb2a4, 0x2a31233f, 0xc63094a5, 0x35c066a2, 0x7437bc4e, 0xfca6ca82, 0xe0b0d090, 0x3315d8a7, 0xf14a9804, 0x41f7daec, 0x7f0e50cd, 0x172ff691, 0x768dd64d, 0x434db0ef, 0xcc544daa, 0xe4df0496, 0x9ee3b5d1, 0x4c1b886a, 0xc1b81f2c, 0x467f5165, 0x9d04ea5e, 0x15d358c, 0xfa737487, 0xfb2e410b, 0xb35a1d67, 0x9252d2db, 0xe9335610, 0x6d1347d6, 0x9a8c61d7, 0x377a0ca1, 0x598e14f8, 0xeb893c13, 0xceee27a9, 0xb735c961, 0xe1ede51c, 0x7a3cb147, 0x9c59dfd2, 0x553f73f2, 0x1879ce14, 0x73bf37c7, 0x53eacdf7, 0x5f5baafd, 0xdf146f3d, 0x7886db44, 0xca81f3af, 0xb93ec468, 0x382c3424, 0xc25f40a3, 0x1672c31d, 0xbc0c25e2, 0x288b493c, 0xff41950d, 0x397101a8, 0x8deb30c, 0xd89ce4b4, 0x6490c156, 0x7b6184cb, 0xd570b632, 0x48745c6c, 0xd04257b8]
|
||||
private static let U1: Array<UInt32> = [0x0, 0xb0d090e, 0x161a121c, 0x1d171b12, 0x2c342438, 0x27392d36, 0x3a2e3624, 0x31233f2a, 0x58684870, 0x5365417e, 0x4e725a6c, 0x457f5362, 0x745c6c48, 0x7f516546, 0x62467e54, 0x694b775a, 0xb0d090e0, 0xbbdd99ee, 0xa6ca82fc, 0xadc78bf2, 0x9ce4b4d8, 0x97e9bdd6, 0x8afea6c4, 0x81f3afca, 0xe8b8d890, 0xe3b5d19e, 0xfea2ca8c, 0xf5afc382, 0xc48cfca8, 0xcf81f5a6, 0xd296eeb4, 0xd99be7ba, 0x7bbb3bdb, 0x70b632d5, 0x6da129c7, 0x66ac20c9, 0x578f1fe3, 0x5c8216ed, 0x41950dff, 0x4a9804f1, 0x23d373ab, 0x28de7aa5, 0x35c961b7, 0x3ec468b9, 0xfe75793, 0x4ea5e9d, 0x19fd458f, 0x12f04c81, 0xcb6bab3b, 0xc066a235, 0xdd71b927, 0xd67cb029, 0xe75f8f03, 0xec52860d, 0xf1459d1f, 0xfa489411, 0x9303e34b, 0x980eea45, 0x8519f157, 0x8e14f859, 0xbf37c773, 0xb43ace7d, 0xa92dd56f, 0xa220dc61, 0xf66d76ad, 0xfd607fa3, 0xe07764b1, 0xeb7a6dbf, 0xda595295, 0xd1545b9b, 0xcc434089, 0xc74e4987, 0xae053edd, 0xa50837d3, 0xb81f2cc1, 0xb31225cf, 0x82311ae5, 0x893c13eb, 0x942b08f9, 0x9f2601f7, 0x46bde64d, 0x4db0ef43, 0x50a7f451, 0x5baafd5f, 0x6a89c275, 0x6184cb7b, 0x7c93d069, 0x779ed967, 0x1ed5ae3d, 0x15d8a733, 0x8cfbc21, 0x3c2b52f, 0x32e18a05, 0x39ec830b, 0x24fb9819, 0x2ff69117, 0x8dd64d76, 0x86db4478, 0x9bcc5f6a, 0x90c15664, 0xa1e2694e, 0xaaef6040, 0xb7f87b52, 0xbcf5725c, 0xd5be0506, 0xdeb30c08, 0xc3a4171a, 0xc8a91e14, 0xf98a213e, 0xf2872830, 0xef903322, 0xe49d3a2c, 0x3d06dd96, 0x360bd498, 0x2b1ccf8a, 0x2011c684, 0x1132f9ae, 0x1a3ff0a0, 0x728ebb2, 0xc25e2bc, 0x656e95e6, 0x6e639ce8, 0x737487fa, 0x78798ef4, 0x495ab1de, 0x4257b8d0, 0x5f40a3c2, 0x544daacc, 0xf7daec41, 0xfcd7e54f, 0xe1c0fe5d, 0xeacdf753, 0xdbeec879, 0xd0e3c177, 0xcdf4da65, 0xc6f9d36b, 0xafb2a431, 0xa4bfad3f, 0xb9a8b62d, 0xb2a5bf23, 0x83868009, 0x888b8907, 0x959c9215, 0x9e919b1b, 0x470a7ca1, 0x4c0775af, 0x51106ebd, 0x5a1d67b3, 0x6b3e5899, 0x60335197, 0x7d244a85, 0x7629438b, 0x1f6234d1, 0x146f3ddf, 0x97826cd, 0x2752fc3, 0x335610e9, 0x385b19e7, 0x254c02f5, 0x2e410bfb, 0x8c61d79a, 0x876cde94, 0x9a7bc586, 0x9176cc88, 0xa055f3a2, 0xab58faac, 0xb64fe1be, 0xbd42e8b0, 0xd4099fea, 0xdf0496e4, 0xc2138df6, 0xc91e84f8, 0xf83dbbd2, 0xf330b2dc, 0xee27a9ce, 0xe52aa0c0, 0x3cb1477a, 0x37bc4e74, 0x2aab5566, 0x21a65c68, 0x10856342, 0x1b886a4c, 0x69f715e, 0xd927850, 0x64d90f0a, 0x6fd40604, 0x72c31d16, 0x79ce1418, 0x48ed2b32, 0x43e0223c, 0x5ef7392e, 0x55fa3020, 0x1b79aec, 0xaba93e2, 0x17ad88f0, 0x1ca081fe, 0x2d83bed4, 0x268eb7da, 0x3b99acc8, 0x3094a5c6, 0x59dfd29c, 0x52d2db92, 0x4fc5c080, 0x44c8c98e, 0x75ebf6a4, 0x7ee6ffaa, 0x63f1e4b8, 0x68fcedb6, 0xb1670a0c, 0xba6a0302, 0xa77d1810, 0xac70111e, 0x9d532e34, 0x965e273a, 0x8b493c28, 0x80443526, 0xe90f427c, 0xe2024b72, 0xff155060, 0xf418596e, 0xc53b6644, 0xce366f4a, 0xd3217458, 0xd82c7d56, 0x7a0ca137, 0x7101a839, 0x6c16b32b, 0x671bba25, 0x5638850f, 0x5d358c01, 0x40229713, 0x4b2f9e1d, 0x2264e947, 0x2969e049, 0x347efb5b, 0x3f73f255, 0xe50cd7f, 0x55dc471, 0x184adf63, 0x1347d66d, 0xcadc31d7, 0xc1d138d9, 0xdcc623cb, 0xd7cb2ac5, 0xe6e815ef, 0xede51ce1, 0xf0f207f3, 0xfbff0efd, 0x92b479a7, 0x99b970a9, 0x84ae6bbb, 0x8fa362b5, 0xbe805d9f, 0xb58d5491, 0xa89a4f83, 0xa397468d]
|
||||
private static let U2: Array<UInt32> = [0x0, 0xd090e0b, 0x1a121c16, 0x171b121d, 0x3424382c, 0x392d3627, 0x2e36243a, 0x233f2a31, 0x68487058, 0x65417e53, 0x725a6c4e, 0x7f536245, 0x5c6c4874, 0x5165467f, 0x467e5462, 0x4b775a69, 0xd090e0b0, 0xdd99eebb, 0xca82fca6, 0xc78bf2ad, 0xe4b4d89c, 0xe9bdd697, 0xfea6c48a, 0xf3afca81, 0xb8d890e8, 0xb5d19ee3, 0xa2ca8cfe, 0xafc382f5, 0x8cfca8c4, 0x81f5a6cf, 0x96eeb4d2, 0x9be7bad9, 0xbb3bdb7b, 0xb632d570, 0xa129c76d, 0xac20c966, 0x8f1fe357, 0x8216ed5c, 0x950dff41, 0x9804f14a, 0xd373ab23, 0xde7aa528, 0xc961b735, 0xc468b93e, 0xe757930f, 0xea5e9d04, 0xfd458f19, 0xf04c8112, 0x6bab3bcb, 0x66a235c0, 0x71b927dd, 0x7cb029d6, 0x5f8f03e7, 0x52860dec, 0x459d1ff1, 0x489411fa, 0x3e34b93, 0xeea4598, 0x19f15785, 0x14f8598e, 0x37c773bf, 0x3ace7db4, 0x2dd56fa9, 0x20dc61a2, 0x6d76adf6, 0x607fa3fd, 0x7764b1e0, 0x7a6dbfeb, 0x595295da, 0x545b9bd1, 0x434089cc, 0x4e4987c7, 0x53eddae, 0x837d3a5, 0x1f2cc1b8, 0x1225cfb3, 0x311ae582, 0x3c13eb89, 0x2b08f994, 0x2601f79f, 0xbde64d46, 0xb0ef434d, 0xa7f45150, 0xaafd5f5b, 0x89c2756a, 0x84cb7b61, 0x93d0697c, 0x9ed96777, 0xd5ae3d1e, 0xd8a73315, 0xcfbc2108, 0xc2b52f03, 0xe18a0532, 0xec830b39, 0xfb981924, 0xf691172f, 0xd64d768d, 0xdb447886, 0xcc5f6a9b, 0xc1566490, 0xe2694ea1, 0xef6040aa, 0xf87b52b7, 0xf5725cbc, 0xbe0506d5, 0xb30c08de, 0xa4171ac3, 0xa91e14c8, 0x8a213ef9, 0x872830f2, 0x903322ef, 0x9d3a2ce4, 0x6dd963d, 0xbd49836, 0x1ccf8a2b, 0x11c68420, 0x32f9ae11, 0x3ff0a01a, 0x28ebb207, 0x25e2bc0c, 0x6e95e665, 0x639ce86e, 0x7487fa73, 0x798ef478, 0x5ab1de49, 0x57b8d042, 0x40a3c25f, 0x4daacc54, 0xdaec41f7, 0xd7e54ffc, 0xc0fe5de1, 0xcdf753ea, 0xeec879db, 0xe3c177d0, 0xf4da65cd, 0xf9d36bc6, 0xb2a431af, 0xbfad3fa4, 0xa8b62db9, 0xa5bf23b2, 0x86800983, 0x8b890788, 0x9c921595, 0x919b1b9e, 0xa7ca147, 0x775af4c, 0x106ebd51, 0x1d67b35a, 0x3e58996b, 0x33519760, 0x244a857d, 0x29438b76, 0x6234d11f, 0x6f3ddf14, 0x7826cd09, 0x752fc302, 0x5610e933, 0x5b19e738, 0x4c02f525, 0x410bfb2e, 0x61d79a8c, 0x6cde9487, 0x7bc5869a, 0x76cc8891, 0x55f3a2a0, 0x58faacab, 0x4fe1beb6, 0x42e8b0bd, 0x99fead4, 0x496e4df, 0x138df6c2, 0x1e84f8c9, 0x3dbbd2f8, 0x30b2dcf3, 0x27a9ceee, 0x2aa0c0e5, 0xb1477a3c, 0xbc4e7437, 0xab55662a, 0xa65c6821, 0x85634210, 0x886a4c1b, 0x9f715e06, 0x9278500d, 0xd90f0a64, 0xd406046f, 0xc31d1672, 0xce141879, 0xed2b3248, 0xe0223c43, 0xf7392e5e, 0xfa302055, 0xb79aec01, 0xba93e20a, 0xad88f017, 0xa081fe1c, 0x83bed42d, 0x8eb7da26, 0x99acc83b, 0x94a5c630, 0xdfd29c59, 0xd2db9252, 0xc5c0804f, 0xc8c98e44, 0xebf6a475, 0xe6ffaa7e, 0xf1e4b863, 0xfcedb668, 0x670a0cb1, 0x6a0302ba, 0x7d1810a7, 0x70111eac, 0x532e349d, 0x5e273a96, 0x493c288b, 0x44352680, 0xf427ce9, 0x24b72e2, 0x155060ff, 0x18596ef4, 0x3b6644c5, 0x366f4ace, 0x217458d3, 0x2c7d56d8, 0xca1377a, 0x1a83971, 0x16b32b6c, 0x1bba2567, 0x38850f56, 0x358c015d, 0x22971340, 0x2f9e1d4b, 0x64e94722, 0x69e04929, 0x7efb5b34, 0x73f2553f, 0x50cd7f0e, 0x5dc47105, 0x4adf6318, 0x47d66d13, 0xdc31d7ca, 0xd138d9c1, 0xc623cbdc, 0xcb2ac5d7, 0xe815efe6, 0xe51ce1ed, 0xf207f3f0, 0xff0efdfb, 0xb479a792, 0xb970a999, 0xae6bbb84, 0xa362b58f, 0x805d9fbe, 0x8d5491b5, 0x9a4f83a8, 0x97468da3]
|
||||
private static let U3: Array<UInt32> = [0x0, 0x90e0b0d, 0x121c161a, 0x1b121d17, 0x24382c34, 0x2d362739, 0x36243a2e, 0x3f2a3123, 0x48705868, 0x417e5365, 0x5a6c4e72, 0x5362457f, 0x6c48745c, 0x65467f51, 0x7e546246, 0x775a694b, 0x90e0b0d0, 0x99eebbdd, 0x82fca6ca, 0x8bf2adc7, 0xb4d89ce4, 0xbdd697e9, 0xa6c48afe, 0xafca81f3, 0xd890e8b8, 0xd19ee3b5, 0xca8cfea2, 0xc382f5af, 0xfca8c48c, 0xf5a6cf81, 0xeeb4d296, 0xe7bad99b, 0x3bdb7bbb, 0x32d570b6, 0x29c76da1, 0x20c966ac, 0x1fe3578f, 0x16ed5c82, 0xdff4195, 0x4f14a98, 0x73ab23d3, 0x7aa528de, 0x61b735c9, 0x68b93ec4, 0x57930fe7, 0x5e9d04ea, 0x458f19fd, 0x4c8112f0, 0xab3bcb6b, 0xa235c066, 0xb927dd71, 0xb029d67c, 0x8f03e75f, 0x860dec52, 0x9d1ff145, 0x9411fa48, 0xe34b9303, 0xea45980e, 0xf1578519, 0xf8598e14, 0xc773bf37, 0xce7db43a, 0xd56fa92d, 0xdc61a220, 0x76adf66d, 0x7fa3fd60, 0x64b1e077, 0x6dbfeb7a, 0x5295da59, 0x5b9bd154, 0x4089cc43, 0x4987c74e, 0x3eddae05, 0x37d3a508, 0x2cc1b81f, 0x25cfb312, 0x1ae58231, 0x13eb893c, 0x8f9942b, 0x1f79f26, 0xe64d46bd, 0xef434db0, 0xf45150a7, 0xfd5f5baa, 0xc2756a89, 0xcb7b6184, 0xd0697c93, 0xd967779e, 0xae3d1ed5, 0xa73315d8, 0xbc2108cf, 0xb52f03c2, 0x8a0532e1, 0x830b39ec, 0x981924fb, 0x91172ff6, 0x4d768dd6, 0x447886db, 0x5f6a9bcc, 0x566490c1, 0x694ea1e2, 0x6040aaef, 0x7b52b7f8, 0x725cbcf5, 0x506d5be, 0xc08deb3, 0x171ac3a4, 0x1e14c8a9, 0x213ef98a, 0x2830f287, 0x3322ef90, 0x3a2ce49d, 0xdd963d06, 0xd498360b, 0xcf8a2b1c, 0xc6842011, 0xf9ae1132, 0xf0a01a3f, 0xebb20728, 0xe2bc0c25, 0x95e6656e, 0x9ce86e63, 0x87fa7374, 0x8ef47879, 0xb1de495a, 0xb8d04257, 0xa3c25f40, 0xaacc544d, 0xec41f7da, 0xe54ffcd7, 0xfe5de1c0, 0xf753eacd, 0xc879dbee, 0xc177d0e3, 0xda65cdf4, 0xd36bc6f9, 0xa431afb2, 0xad3fa4bf, 0xb62db9a8, 0xbf23b2a5, 0x80098386, 0x8907888b, 0x9215959c, 0x9b1b9e91, 0x7ca1470a, 0x75af4c07, 0x6ebd5110, 0x67b35a1d, 0x58996b3e, 0x51976033, 0x4a857d24, 0x438b7629, 0x34d11f62, 0x3ddf146f, 0x26cd0978, 0x2fc30275, 0x10e93356, 0x19e7385b, 0x2f5254c, 0xbfb2e41, 0xd79a8c61, 0xde94876c, 0xc5869a7b, 0xcc889176, 0xf3a2a055, 0xfaacab58, 0xe1beb64f, 0xe8b0bd42, 0x9fead409, 0x96e4df04, 0x8df6c213, 0x84f8c91e, 0xbbd2f83d, 0xb2dcf330, 0xa9ceee27, 0xa0c0e52a, 0x477a3cb1, 0x4e7437bc, 0x55662aab, 0x5c6821a6, 0x63421085, 0x6a4c1b88, 0x715e069f, 0x78500d92, 0xf0a64d9, 0x6046fd4, 0x1d1672c3, 0x141879ce, 0x2b3248ed, 0x223c43e0, 0x392e5ef7, 0x302055fa, 0x9aec01b7, 0x93e20aba, 0x88f017ad, 0x81fe1ca0, 0xbed42d83, 0xb7da268e, 0xacc83b99, 0xa5c63094, 0xd29c59df, 0xdb9252d2, 0xc0804fc5, 0xc98e44c8, 0xf6a475eb, 0xffaa7ee6, 0xe4b863f1, 0xedb668fc, 0xa0cb167, 0x302ba6a, 0x1810a77d, 0x111eac70, 0x2e349d53, 0x273a965e, 0x3c288b49, 0x35268044, 0x427ce90f, 0x4b72e202, 0x5060ff15, 0x596ef418, 0x6644c53b, 0x6f4ace36, 0x7458d321, 0x7d56d82c, 0xa1377a0c, 0xa8397101, 0xb32b6c16, 0xba25671b, 0x850f5638, 0x8c015d35, 0x97134022, 0x9e1d4b2f, 0xe9472264, 0xe0492969, 0xfb5b347e, 0xf2553f73, 0xcd7f0e50, 0xc471055d, 0xdf63184a, 0xd66d1347, 0x31d7cadc, 0x38d9c1d1, 0x23cbdcc6, 0x2ac5d7cb, 0x15efe6e8, 0x1ce1ede5, 0x7f3f0f2, 0xefdfbff, 0x79a792b4, 0x70a999b9, 0x6bbb84ae, 0x62b58fa3, 0x5d9fbe80, 0x5491b58d, 0x4f83a89a, 0x468da397]
|
||||
private static let U4: Array<UInt32> = [0x0, 0xe0b0d09, 0x1c161a12, 0x121d171b, 0x382c3424, 0x3627392d, 0x243a2e36, 0x2a31233f, 0x70586848, 0x7e536541, 0x6c4e725a, 0x62457f53, 0x48745c6c, 0x467f5165, 0x5462467e, 0x5a694b77, 0xe0b0d090, 0xeebbdd99, 0xfca6ca82, 0xf2adc78b, 0xd89ce4b4, 0xd697e9bd, 0xc48afea6, 0xca81f3af, 0x90e8b8d8, 0x9ee3b5d1, 0x8cfea2ca, 0x82f5afc3, 0xa8c48cfc, 0xa6cf81f5, 0xb4d296ee, 0xbad99be7, 0xdb7bbb3b, 0xd570b632, 0xc76da129, 0xc966ac20, 0xe3578f1f, 0xed5c8216, 0xff41950d, 0xf14a9804, 0xab23d373, 0xa528de7a, 0xb735c961, 0xb93ec468, 0x930fe757, 0x9d04ea5e, 0x8f19fd45, 0x8112f04c, 0x3bcb6bab, 0x35c066a2, 0x27dd71b9, 0x29d67cb0, 0x3e75f8f, 0xdec5286, 0x1ff1459d, 0x11fa4894, 0x4b9303e3, 0x45980eea, 0x578519f1, 0x598e14f8, 0x73bf37c7, 0x7db43ace, 0x6fa92dd5, 0x61a220dc, 0xadf66d76, 0xa3fd607f, 0xb1e07764, 0xbfeb7a6d, 0x95da5952, 0x9bd1545b, 0x89cc4340, 0x87c74e49, 0xddae053e, 0xd3a50837, 0xc1b81f2c, 0xcfb31225, 0xe582311a, 0xeb893c13, 0xf9942b08, 0xf79f2601, 0x4d46bde6, 0x434db0ef, 0x5150a7f4, 0x5f5baafd, 0x756a89c2, 0x7b6184cb, 0x697c93d0, 0x67779ed9, 0x3d1ed5ae, 0x3315d8a7, 0x2108cfbc, 0x2f03c2b5, 0x532e18a, 0xb39ec83, 0x1924fb98, 0x172ff691, 0x768dd64d, 0x7886db44, 0x6a9bcc5f, 0x6490c156, 0x4ea1e269, 0x40aaef60, 0x52b7f87b, 0x5cbcf572, 0x6d5be05, 0x8deb30c, 0x1ac3a417, 0x14c8a91e, 0x3ef98a21, 0x30f28728, 0x22ef9033, 0x2ce49d3a, 0x963d06dd, 0x98360bd4, 0x8a2b1ccf, 0x842011c6, 0xae1132f9, 0xa01a3ff0, 0xb20728eb, 0xbc0c25e2, 0xe6656e95, 0xe86e639c, 0xfa737487, 0xf478798e, 0xde495ab1, 0xd04257b8, 0xc25f40a3, 0xcc544daa, 0x41f7daec, 0x4ffcd7e5, 0x5de1c0fe, 0x53eacdf7, 0x79dbeec8, 0x77d0e3c1, 0x65cdf4da, 0x6bc6f9d3, 0x31afb2a4, 0x3fa4bfad, 0x2db9a8b6, 0x23b2a5bf, 0x9838680, 0x7888b89, 0x15959c92, 0x1b9e919b, 0xa1470a7c, 0xaf4c0775, 0xbd51106e, 0xb35a1d67, 0x996b3e58, 0x97603351, 0x857d244a, 0x8b762943, 0xd11f6234, 0xdf146f3d, 0xcd097826, 0xc302752f, 0xe9335610, 0xe7385b19, 0xf5254c02, 0xfb2e410b, 0x9a8c61d7, 0x94876cde, 0x869a7bc5, 0x889176cc, 0xa2a055f3, 0xacab58fa, 0xbeb64fe1, 0xb0bd42e8, 0xead4099f, 0xe4df0496, 0xf6c2138d, 0xf8c91e84, 0xd2f83dbb, 0xdcf330b2, 0xceee27a9, 0xc0e52aa0, 0x7a3cb147, 0x7437bc4e, 0x662aab55, 0x6821a65c, 0x42108563, 0x4c1b886a, 0x5e069f71, 0x500d9278, 0xa64d90f, 0x46fd406, 0x1672c31d, 0x1879ce14, 0x3248ed2b, 0x3c43e022, 0x2e5ef739, 0x2055fa30, 0xec01b79a, 0xe20aba93, 0xf017ad88, 0xfe1ca081, 0xd42d83be, 0xda268eb7, 0xc83b99ac, 0xc63094a5, 0x9c59dfd2, 0x9252d2db, 0x804fc5c0, 0x8e44c8c9, 0xa475ebf6, 0xaa7ee6ff, 0xb863f1e4, 0xb668fced, 0xcb1670a, 0x2ba6a03, 0x10a77d18, 0x1eac7011, 0x349d532e, 0x3a965e27, 0x288b493c, 0x26804435, 0x7ce90f42, 0x72e2024b, 0x60ff1550, 0x6ef41859, 0x44c53b66, 0x4ace366f, 0x58d32174, 0x56d82c7d, 0x377a0ca1, 0x397101a8, 0x2b6c16b3, 0x25671bba, 0xf563885, 0x15d358c, 0x13402297, 0x1d4b2f9e, 0x472264e9, 0x492969e0, 0x5b347efb, 0x553f73f2, 0x7f0e50cd, 0x71055dc4, 0x63184adf, 0x6d1347d6, 0xd7cadc31, 0xd9c1d138, 0xcbdcc623, 0xc5d7cb2a, 0xefe6e815, 0xe1ede51c, 0xf3f0f207, 0xfdfbff0e, 0xa792b479, 0xa999b970, 0xbb84ae6b, 0xb58fa362, 0x9fbe805d, 0x91b58d54, 0x83a89a4f, 0x8da39746]
|
||||
|
||||
/// Initialize AES with variant calculated out of key length:
|
||||
/// - 16 bytes (AES-128)
|
||||
/// - 24 bytes (AES-192)
|
||||
/// - 32 bytes (AES-256)
|
||||
///
|
||||
/// - parameter key: Key. Length of the key decides on AES variant.
|
||||
/// - parameter iv: Initialization Vector (Optional for some blockMode values)
|
||||
/// - parameter blockMode: Cipher mode of operation
|
||||
/// - parameter padding: Padding method. .pkcs7, .noPadding, .zeroPadding, ...
|
||||
///
|
||||
/// - throws: AES.Error
|
||||
///
|
||||
/// - returns: Instance
|
||||
public init(key: Array<UInt8>, blockMode: BlockMode, padding: Padding = .pkcs7) throws {
|
||||
self.key = Key(bytes: key)
|
||||
self.blockMode = blockMode
|
||||
self.padding = padding
|
||||
}
|
||||
|
||||
internal func encrypt(block: ArraySlice<UInt8>) -> Array<UInt8>? {
|
||||
if blockMode.options.contains(.paddingRequired) && block.count != AES.blockSize {
|
||||
return Array(block)
|
||||
}
|
||||
|
||||
let rounds = variantNr
|
||||
let rk = expandedKey
|
||||
|
||||
let b00 = UInt32(block[block.startIndex.advanced(by: 0)])
|
||||
let b01 = UInt32(block[block.startIndex.advanced(by: 1)]) << 8
|
||||
let b02 = UInt32(block[block.startIndex.advanced(by: 2)]) << 16
|
||||
let b03 = UInt32(block[block.startIndex.advanced(by: 3)]) << 24
|
||||
var b0 = b00 | b01 | b02 | b03
|
||||
|
||||
let b10 = UInt32(block[block.startIndex.advanced(by: 4)])
|
||||
let b11 = UInt32(block[block.startIndex.advanced(by: 5)]) << 8
|
||||
let b12 = UInt32(block[block.startIndex.advanced(by: 6)]) << 16
|
||||
let b13 = UInt32(block[block.startIndex.advanced(by: 7)]) << 24
|
||||
var b1 = b10 | b11 | b12 | b13
|
||||
|
||||
let b20 = UInt32(block[block.startIndex.advanced(by: 8)])
|
||||
let b21 = UInt32(block[block.startIndex.advanced(by: 9)]) << 8
|
||||
let b22 = UInt32(block[block.startIndex.advanced(by: 10)]) << 16
|
||||
let b23 = UInt32(block[block.startIndex.advanced(by: 11)]) << 24
|
||||
var b2 = b20 | b21 | b22 | b23
|
||||
|
||||
let b30 = UInt32(block[block.startIndex.advanced(by: 12)])
|
||||
let b31 = UInt32(block[block.startIndex.advanced(by: 13)]) << 8
|
||||
let b32 = UInt32(block[block.startIndex.advanced(by: 14)]) << 16
|
||||
let b33 = UInt32(block[block.startIndex.advanced(by: 15)]) << 24
|
||||
var b3 = b30 | b31 | b32 | b33
|
||||
|
||||
let tLength = 4
|
||||
let t = UnsafeMutablePointer<UInt32>.allocate(capacity: tLength)
|
||||
t.initialize(to: 0, count: tLength)
|
||||
defer {
|
||||
t.deinitialize(count: tLength)
|
||||
t.deallocate(capacity: tLength)
|
||||
}
|
||||
|
||||
for r in 0..<rounds - 1 {
|
||||
t[0] = b0 ^ rk[r][0]
|
||||
t[1] = b1 ^ rk[r][1]
|
||||
t[2] = b2 ^ rk[r][2]
|
||||
t[3] = b3 ^ rk[r][3]
|
||||
|
||||
let lb00 = AES.T0[Int(t[0] & 0xff)]
|
||||
let lb01 = AES.T1[Int((t[1] >> 8) & 0xff)]
|
||||
let lb02 = AES.T2[Int((t[2] >> 16) & 0xff)]
|
||||
let lb03 = AES.T3[Int(t[3] >> 24)]
|
||||
b0 = lb00 ^ lb01 ^ lb02 ^ lb03
|
||||
|
||||
let lb10 = AES.T0[Int(t[1] & 0xff)]
|
||||
let lb11 = AES.T1[Int((t[2] >> 8) & 0xff)]
|
||||
let lb12 = AES.T2[Int((t[3] >> 16) & 0xff)]
|
||||
let lb13 = AES.T3[Int(t[0] >> 24)]
|
||||
b1 = lb10 ^ lb11 ^ lb12 ^ lb13
|
||||
|
||||
let lb20 = AES.T0[Int(t[2] & 0xff)]
|
||||
let lb21 = AES.T1[Int((t[3] >> 8) & 0xff)]
|
||||
let lb22 = AES.T2[Int((t[0] >> 16) & 0xff)]
|
||||
let lb23 = AES.T3[Int(t[1] >> 24)]
|
||||
b2 = lb20 ^ lb21 ^ lb22 ^ lb23
|
||||
|
||||
let lb30 = AES.T0[Int(t[3] & 0xff)]
|
||||
let lb31 = AES.T1[Int((t[0] >> 8) & 0xff)]
|
||||
let lb32 = AES.T2[Int((t[1] >> 16) & 0xff)]
|
||||
let lb33 = AES.T3[Int(t[2] >> 24)]
|
||||
b3 = lb30 ^ lb31 ^ lb32 ^ lb33
|
||||
}
|
||||
|
||||
// last round
|
||||
let r = rounds - 1
|
||||
|
||||
t[0] = b0 ^ rk[r][0]
|
||||
t[1] = b1 ^ rk[r][1]
|
||||
t[2] = b2 ^ rk[r][2]
|
||||
t[3] = b3 ^ rk[r][3]
|
||||
|
||||
// rounds
|
||||
b0 = F1(t[0], t[1], t[2], t[3]) ^ rk[rounds][0]
|
||||
b1 = F1(t[1], t[2], t[3], t[0]) ^ rk[rounds][1]
|
||||
b2 = F1(t[2], t[3], t[0], t[1]) ^ rk[rounds][2]
|
||||
b3 = F1(t[3], t[0], t[1], t[2]) ^ rk[rounds][3]
|
||||
|
||||
let encrypted: Array<UInt8> = [
|
||||
UInt8(b0 & 0xff), UInt8((b0 >> 8) & 0xff), UInt8((b0 >> 16) & 0xff), UInt8((b0 >> 24) & 0xff),
|
||||
UInt8(b1 & 0xff), UInt8((b1 >> 8) & 0xff), UInt8((b1 >> 16) & 0xff), UInt8((b1 >> 24) & 0xff),
|
||||
UInt8(b2 & 0xff), UInt8((b2 >> 8) & 0xff), UInt8((b2 >> 16) & 0xff), UInt8((b2 >> 24) & 0xff),
|
||||
UInt8(b3 & 0xff), UInt8((b3 >> 8) & 0xff), UInt8((b3 >> 16) & 0xff), UInt8((b3 >> 24) & 0xff),
|
||||
]
|
||||
return encrypted
|
||||
}
|
||||
|
||||
internal func decrypt(block: ArraySlice<UInt8>) -> Array<UInt8>? {
|
||||
if blockMode.options.contains(.paddingRequired) && block.count != AES.blockSize {
|
||||
return Array(block)
|
||||
}
|
||||
|
||||
let rounds = variantNr
|
||||
let rk = expandedKeyInv
|
||||
|
||||
// Save miliseconds by not using `block.toUInt32Array()`
|
||||
let b00 = UInt32(block[block.startIndex.advanced(by: 0)])
|
||||
let b01 = UInt32(block[block.startIndex.advanced(by: 1)]) << 8
|
||||
let b02 = UInt32(block[block.startIndex.advanced(by: 2)]) << 16
|
||||
let b03 = UInt32(block[block.startIndex.advanced(by: 3)]) << 24
|
||||
var b0 = b00 | b01 | b02 | b03
|
||||
|
||||
let b10 = UInt32(block[block.startIndex.advanced(by: 4)])
|
||||
let b11 = UInt32(block[block.startIndex.advanced(by: 5)]) << 8
|
||||
let b12 = UInt32(block[block.startIndex.advanced(by: 6)]) << 16
|
||||
let b13 = UInt32(block[block.startIndex.advanced(by: 7)]) << 24
|
||||
var b1 = b10 | b11 | b12 | b13
|
||||
|
||||
let b20 = UInt32(block[block.startIndex.advanced(by: 8)])
|
||||
let b21 = UInt32(block[block.startIndex.advanced(by: 9)]) << 8
|
||||
let b22 = UInt32(block[block.startIndex.advanced(by: 10)]) << 16
|
||||
let b23 = UInt32(block[block.startIndex.advanced(by: 11)]) << 24
|
||||
var b2 = b20 | b21 | b22 | b23
|
||||
|
||||
let b30 = UInt32(block[block.startIndex.advanced(by: 12)])
|
||||
let b31 = UInt32(block[block.startIndex.advanced(by: 13)]) << 8
|
||||
let b32 = UInt32(block[block.startIndex.advanced(by: 14)]) << 16
|
||||
let b33 = UInt32(block[block.startIndex.advanced(by: 15)]) << 24
|
||||
var b3 = b30 | b31 | b32 | b33
|
||||
|
||||
let tLength = 4
|
||||
let t = UnsafeMutablePointer<UInt32>.allocate(capacity: tLength)
|
||||
t.initialize(to: 0, count: tLength)
|
||||
defer {
|
||||
t.deinitialize(count: tLength)
|
||||
t.deallocate(capacity: tLength)
|
||||
}
|
||||
|
||||
for r in (2...rounds).reversed() {
|
||||
t[0] = b0 ^ rk[r][0]
|
||||
t[1] = b1 ^ rk[r][1]
|
||||
t[2] = b2 ^ rk[r][2]
|
||||
t[3] = b3 ^ rk[r][3]
|
||||
|
||||
let b00 = AES.T0_INV[Int(t[0] & 0xff)]
|
||||
let b01 = AES.T1_INV[Int((t[3] >> 8) & 0xff)]
|
||||
let b02 = AES.T2_INV[Int((t[2] >> 16) & 0xff)]
|
||||
let b03 = AES.T3_INV[Int(t[1] >> 24)]
|
||||
b0 = b00 ^ b01 ^ b02 ^ b03
|
||||
|
||||
let b10 = AES.T0_INV[Int(t[1] & 0xff)]
|
||||
let b11 = AES.T1_INV[Int((t[0] >> 8) & 0xff)]
|
||||
let b12 = AES.T2_INV[Int((t[3] >> 16) & 0xff)]
|
||||
let b13 = AES.T3_INV[Int(t[2] >> 24)]
|
||||
b1 = b10 ^ b11 ^ b12 ^ b13
|
||||
|
||||
let b20 = AES.T0_INV[Int(t[2] & 0xff)]
|
||||
let b21 = AES.T1_INV[Int((t[1] >> 8) & 0xff)]
|
||||
let b22 = AES.T2_INV[Int((t[0] >> 16) & 0xff)]
|
||||
let b23 = AES.T3_INV[Int(t[3] >> 24)]
|
||||
b2 = b20 ^ b21 ^ b22 ^ b23
|
||||
|
||||
let b30 = AES.T0_INV[Int(t[3] & 0xff)]
|
||||
let b31 = AES.T1_INV[Int((t[2] >> 8) & 0xff)]
|
||||
let b32 = AES.T2_INV[Int((t[1] >> 16) & 0xff)]
|
||||
let b33 = AES.T3_INV[Int(t[0] >> 24)]
|
||||
b3 = b30 ^ b31 ^ b32 ^ b33
|
||||
}
|
||||
|
||||
// last round
|
||||
t[0] = b0 ^ rk[1][0]
|
||||
t[1] = b1 ^ rk[1][1]
|
||||
t[2] = b2 ^ rk[1][2]
|
||||
t[3] = b3 ^ rk[1][3]
|
||||
|
||||
// rounds
|
||||
|
||||
let lb00 = sBoxInv[Int(B0(t[0]))]
|
||||
let lb01 = (sBoxInv[Int(B1(t[3]))] << 8)
|
||||
let lb02 = (sBoxInv[Int(B2(t[2]))] << 16)
|
||||
let lb03 = (sBoxInv[Int(B3(t[1]))] << 24)
|
||||
b0 = lb00 | lb01 | lb02 | lb03 ^ rk[0][0]
|
||||
|
||||
let lb10 = sBoxInv[Int(B0(t[1]))]
|
||||
let lb11 = (sBoxInv[Int(B1(t[0]))] << 8)
|
||||
let lb12 = (sBoxInv[Int(B2(t[3]))] << 16)
|
||||
let lb13 = (sBoxInv[Int(B3(t[2]))] << 24)
|
||||
b1 = lb10 | lb11 | lb12 | lb13 ^ rk[0][1]
|
||||
|
||||
let lb20 = sBoxInv[Int(B0(t[2]))]
|
||||
let lb21 = (sBoxInv[Int(B1(t[1]))] << 8)
|
||||
let lb22 = (sBoxInv[Int(B2(t[0]))] << 16)
|
||||
let lb23 = (sBoxInv[Int(B3(t[3]))] << 24)
|
||||
b2 = lb20 | lb21 | lb22 | lb23 ^ rk[0][2]
|
||||
|
||||
let lb30 = sBoxInv[Int(B0(t[3]))]
|
||||
let lb31 = (sBoxInv[Int(B1(t[2]))] << 8)
|
||||
let lb32 = (sBoxInv[Int(B2(t[1]))] << 16)
|
||||
let lb33 = (sBoxInv[Int(B3(t[0]))] << 24)
|
||||
b3 = lb30 | lb31 | lb32 | lb33 ^ rk[0][3]
|
||||
|
||||
let result: Array<UInt8> = [
|
||||
UInt8(b0 & 0xff), UInt8((b0 >> 8) & 0xff), UInt8((b0 >> 16) & 0xff), UInt8((b0 >> 24) & 0xff),
|
||||
UInt8(b1 & 0xff), UInt8((b1 >> 8) & 0xff), UInt8((b1 >> 16) & 0xff), UInt8((b1 >> 24) & 0xff),
|
||||
UInt8(b2 & 0xff), UInt8((b2 >> 8) & 0xff), UInt8((b2 >> 16) & 0xff), UInt8((b2 >> 24) & 0xff),
|
||||
UInt8(b3 & 0xff), UInt8((b3 >> 8) & 0xff), UInt8((b3 >> 16) & 0xff), UInt8((b3 >> 24) & 0xff),
|
||||
]
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private extension AES {
|
||||
private func expandKeyInv(_ key: Key, variant: Variant) -> Array<Array<UInt32>> {
|
||||
let rounds = variantNr
|
||||
var rk2: Array<Array<UInt32>> = expandKey(key, variant: variant)
|
||||
|
||||
for r in 1..<rounds {
|
||||
for i in 0..<4 {
|
||||
let w = rk2[r][i]
|
||||
let u1 = AES.U1[Int(B0(w))]
|
||||
let u2 = AES.U2[Int(B1(w))]
|
||||
let u3 = AES.U3[Int(B2(w))]
|
||||
let u4 = AES.U4[Int(B3(w))]
|
||||
rk2[r][i] = u1 ^ u2 ^ u3 ^ u4
|
||||
}
|
||||
}
|
||||
|
||||
return rk2
|
||||
}
|
||||
|
||||
private func expandKey(_ key: Key, variant _: Variant) -> Array<Array<UInt32>> {
|
||||
|
||||
func convertExpandedKey(_ expanded: Array<UInt8>) -> Array<Array<UInt32>> {
|
||||
return expanded.batched(by: 4).map({ UInt32(bytes: $0.reversed()) }).batched(by: 4).map({ Array($0) })
|
||||
}
|
||||
|
||||
/*
|
||||
* Function used in the Key Expansion routine that takes a four-byte
|
||||
* input word and applies an S-box to each of the four bytes to
|
||||
* produce an output word.
|
||||
*/
|
||||
func subWord(_ word: Array<UInt8>) -> Array<UInt8> {
|
||||
precondition(word.count == 4)
|
||||
|
||||
var result = word
|
||||
for i in 0..<4 {
|
||||
result[i] = UInt8(sBox[Int(word[i])])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
func subWordInPlace(_ word: inout Array<UInt8>) {
|
||||
precondition(word.count == 4)
|
||||
word[0] = UInt8(sBox[Int(word[0])])
|
||||
word[1] = UInt8(sBox[Int(word[1])])
|
||||
word[2] = UInt8(sBox[Int(word[2])])
|
||||
word[3] = UInt8(sBox[Int(word[3])])
|
||||
}
|
||||
|
||||
let wLength = variantNb * (variantNr + 1) * 4
|
||||
let w = UnsafeMutablePointer<UInt8>.allocate(capacity: wLength)
|
||||
w.initialize(to: 0, count: wLength)
|
||||
defer {
|
||||
w.deinitialize(count: wLength)
|
||||
w.deallocate(capacity: wLength)
|
||||
}
|
||||
|
||||
for i in 0..<variantNk {
|
||||
for wordIdx in 0..<4 {
|
||||
w[(4 * i) + wordIdx] = key[(4 * i) + wordIdx]
|
||||
}
|
||||
}
|
||||
|
||||
var tmp: Array<UInt8>
|
||||
|
||||
for i in variantNk..<variantNb * (variantNr + 1) {
|
||||
tmp = Array<UInt8>(repeating: 0, count: 4)
|
||||
|
||||
for wordIdx in 0..<4 {
|
||||
tmp[wordIdx] = w[4 * (i - 1) + wordIdx]
|
||||
}
|
||||
if (i % variantNk) == 0 {
|
||||
tmp = subWord(rotateLeft(UInt32(bytes: tmp), by: 8).bytes(totalBytes: 4))
|
||||
tmp[0] = tmp.first! ^ AES.Rcon[i / variantNk]
|
||||
} else if variantNk > 6 && (i % variantNk) == 4 {
|
||||
subWordInPlace(&tmp)
|
||||
}
|
||||
|
||||
// xor array of bytes
|
||||
for wordIdx in 0..<4 {
|
||||
w[4 * i + wordIdx] = w[4 * (i - variantNk) + wordIdx] ^ tmp[wordIdx]
|
||||
}
|
||||
}
|
||||
return convertExpandedKey(Array(UnsafeBufferPointer(start: w, count: wLength)))
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
private func B0(_ x: UInt32) -> UInt32 {
|
||||
return x & 0xff
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
private func B1(_ x: UInt32) -> UInt32 {
|
||||
return (x >> 8) & 0xff
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
private func B2(_ x: UInt32) -> UInt32 {
|
||||
return (x >> 16) & 0xff
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
private func B3(_ x: UInt32) -> UInt32 {
|
||||
return (x >> 24) & 0xff
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
private func F1(_ x0: UInt32, _ x1: UInt32, _ x2: UInt32, _ x3: UInt32) -> UInt32 {
|
||||
var result: UInt32 = 0
|
||||
result |= UInt32(B1(AES.T0[Int(x0 & 255)]))
|
||||
result |= UInt32(B1(AES.T0[Int((x1 >> 8) & 255)])) << 8
|
||||
result |= UInt32(B1(AES.T0[Int((x2 >> 16) & 255)])) << 16
|
||||
result |= UInt32(B1(AES.T0[Int(x3 >> 24)])) << 24
|
||||
return result
|
||||
}
|
||||
|
||||
private func calculateSBox() -> (sBox: Array<UInt32>, invSBox: Array<UInt32>) {
|
||||
let sboxLength = 256
|
||||
let sbox = UnsafeMutablePointer<UInt32>.allocate(capacity: sboxLength)
|
||||
let invsbox = UnsafeMutablePointer<UInt32>.allocate(capacity: sboxLength)
|
||||
sbox.initialize(to: 0, count: sboxLength)
|
||||
invsbox.initialize(to: 0, count: sboxLength)
|
||||
defer {
|
||||
sbox.deinitialize(count: sboxLength)
|
||||
sbox.deallocate(capacity: sboxLength)
|
||||
invsbox.deinitialize(count: sboxLength)
|
||||
invsbox.deallocate(capacity: sboxLength)
|
||||
}
|
||||
|
||||
sbox[0] = 0x63
|
||||
|
||||
var p: UInt8 = 1, q: UInt8 = 1
|
||||
|
||||
repeat {
|
||||
p = p ^ (UInt8(truncatingIfNeeded: Int(p) << 1) ^ ((p & 0x80) == 0x80 ? 0x1b : 0))
|
||||
q ^= q << 1
|
||||
q ^= q << 2
|
||||
q ^= q << 4
|
||||
q ^= (q & 0x80) == 0x80 ? 0x09 : 0
|
||||
|
||||
let s = 0x63 ^ q ^ rotateLeft(q, by: 1) ^ rotateLeft(q, by: 2) ^ rotateLeft(q, by: 3) ^ rotateLeft(q, by: 4)
|
||||
|
||||
sbox[Int(p)] = UInt32(s)
|
||||
invsbox[Int(s)] = UInt32(p)
|
||||
} while (p != 1)
|
||||
|
||||
return (sBox: Array(UnsafeBufferPointer(start: sbox, count: sboxLength)), invSBox: Array(UnsafeBufferPointer(start: invsbox, count: sboxLength)))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Cipher
|
||||
extension AES: Cipher {
|
||||
|
||||
public func encrypt(_ bytes: ArraySlice<UInt8>) throws -> Array<UInt8> {
|
||||
let chunks = bytes.batched(by: AES.blockSize)
|
||||
|
||||
var oneTimeCryptor = try self.makeEncryptor()
|
||||
var out = Array<UInt8>(reserveCapacity: bytes.count)
|
||||
for chunk in chunks {
|
||||
out += try oneTimeCryptor.update(withBytes: chunk, isLast: false)
|
||||
}
|
||||
// Padding may be added at the very end
|
||||
out += try oneTimeCryptor.finish()
|
||||
|
||||
if blockMode.options.contains(.paddingRequired) && (out.count % AES.blockSize != 0) {
|
||||
throw Error.dataPaddingRequired
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
public func decrypt(_ bytes: ArraySlice<UInt8>) throws -> Array<UInt8> {
|
||||
if blockMode.options.contains(.paddingRequired) && (bytes.count % AES.blockSize != 0) {
|
||||
throw Error.dataPaddingRequired
|
||||
}
|
||||
|
||||
var oneTimeCryptor = try self.makeDecryptor()
|
||||
let chunks = bytes.batched(by: AES.blockSize)
|
||||
if chunks.isEmpty {
|
||||
throw Error.invalidData
|
||||
}
|
||||
|
||||
var out = Array<UInt8>(reserveCapacity: bytes.count)
|
||||
|
||||
var lastIdx = chunks.startIndex
|
||||
chunks.indices.formIndex(&lastIdx, offsetBy: chunks.count - 1)
|
||||
|
||||
// To properly remove padding, `isLast` has to be known when called with the last chunk of ciphertext
|
||||
// Last chunk of ciphertext may contains padded data so next call to update(..) won't be able to remove it
|
||||
for idx in chunks.indices {
|
||||
out += try oneTimeCryptor.update(withBytes: chunks[idx], isLast: idx == lastIdx)
|
||||
}
|
||||
return out
|
||||
}
|
||||
}
|
85
Pods/CryptoSwift/Sources/CryptoSwift/Array+Extension.swift
generated
Normal file
@ -0,0 +1,85 @@
|
||||
//
|
||||
// ArrayExtension.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
extension Array {
|
||||
init(reserveCapacity: Int) {
|
||||
self = Array<Element>()
|
||||
self.reserveCapacity(reserveCapacity)
|
||||
}
|
||||
|
||||
var slice: ArraySlice<Element> {
|
||||
return self[self.startIndex..<self.endIndex]
|
||||
}
|
||||
}
|
||||
|
||||
extension Array {
|
||||
|
||||
/// split in chunks with given chunk size
|
||||
@available(*, deprecated: 0.8.0, message: "")
|
||||
public func chunks(size chunksize: Int) -> Array<Array<Element>> {
|
||||
var words = Array<Array<Element>>()
|
||||
words.reserveCapacity(count / chunksize)
|
||||
for idx in stride(from: chunksize, through: count, by: chunksize) {
|
||||
words.append(Array(self[idx - chunksize..<idx])) // slow for large table
|
||||
}
|
||||
let remainder = suffix(count % chunksize)
|
||||
if !remainder.isEmpty {
|
||||
words.append(Array(remainder))
|
||||
}
|
||||
return words
|
||||
}
|
||||
}
|
||||
|
||||
extension Array where Element == UInt8 {
|
||||
|
||||
public init(hex: String) {
|
||||
self.init(reserveCapacity: hex.unicodeScalars.lazy.underestimatedCount)
|
||||
var buffer: UInt8?
|
||||
var skip = hex.hasPrefix("0x") ? 2 : 0
|
||||
for char in hex.unicodeScalars.lazy {
|
||||
guard skip == 0 else {
|
||||
skip -= 1
|
||||
continue
|
||||
}
|
||||
guard char.value >= 48 && char.value <= 102 else {
|
||||
removeAll()
|
||||
return
|
||||
}
|
||||
let v: UInt8
|
||||
let c: UInt8 = UInt8(char.value)
|
||||
switch c {
|
||||
case let c where c <= 57:
|
||||
v = c - 48
|
||||
case let c where c >= 65 && c <= 70:
|
||||
v = c - 55
|
||||
case let c where c >= 97:
|
||||
v = c - 87
|
||||
default:
|
||||
removeAll()
|
||||
return
|
||||
}
|
||||
if let b = buffer {
|
||||
append(b << 4 | v)
|
||||
buffer = nil
|
||||
} else {
|
||||
buffer = v
|
||||
}
|
||||
}
|
||||
if let b = buffer {
|
||||
append(b)
|
||||
}
|
||||
}
|
||||
}
|
83
Pods/CryptoSwift/Sources/CryptoSwift/Array+Extensions.swift
generated
Normal file
@ -0,0 +1,83 @@
|
||||
//
|
||||
// Array+Extensions.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
public extension Array where Element == UInt8 {
|
||||
|
||||
public func toHexString() -> String {
|
||||
return `lazy`.reduce("") {
|
||||
var s = String($1, radix: 16)
|
||||
if s.count == 1 {
|
||||
s = "0" + s
|
||||
}
|
||||
return $0 + s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension Array where Element == UInt8 {
|
||||
|
||||
public func md5() -> [Element] {
|
||||
return Digest.md5(self)
|
||||
}
|
||||
|
||||
public func sha1() -> [Element] {
|
||||
return Digest.sha1(self)
|
||||
}
|
||||
|
||||
public func sha224() -> [Element] {
|
||||
return Digest.sha224(self)
|
||||
}
|
||||
|
||||
public func sha256() -> [Element] {
|
||||
return Digest.sha256(self)
|
||||
}
|
||||
|
||||
public func sha384() -> [Element] {
|
||||
return Digest.sha384(self)
|
||||
}
|
||||
|
||||
public func sha512() -> [Element] {
|
||||
return Digest.sha512(self)
|
||||
}
|
||||
|
||||
public func sha2(_ variant: SHA2.Variant) -> [Element] {
|
||||
return Digest.sha2(self, variant: variant)
|
||||
}
|
||||
|
||||
public func sha3(_ variant: SHA3.Variant) -> [Element] {
|
||||
return Digest.sha3(self, variant: variant)
|
||||
}
|
||||
|
||||
public func crc32(seed: UInt32? = nil, reflect: Bool = true) -> UInt32 {
|
||||
return Checksum.crc32(self, seed: seed, reflect: reflect)
|
||||
}
|
||||
|
||||
public func crc16(seed: UInt16? = nil) -> UInt16 {
|
||||
return Checksum.crc16(self, seed: seed)
|
||||
}
|
||||
|
||||
public func encrypt(cipher: Cipher) throws -> [Element] {
|
||||
return try cipher.encrypt(slice)
|
||||
}
|
||||
|
||||
public func decrypt(cipher: Cipher) throws -> [Element] {
|
||||
return try cipher.decrypt(slice)
|
||||
}
|
||||
|
||||
public func authenticate<A: Authenticator>(with authenticator: A) throws -> [Element] {
|
||||
return try authenticator.authenticate(self)
|
||||
}
|
||||
}
|
21
Pods/CryptoSwift/Sources/CryptoSwift/Authenticator.swift
generated
Normal file
@ -0,0 +1,21 @@
|
||||
//
|
||||
// MAC.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
/// Message authentication code.
|
||||
public protocol Authenticator {
|
||||
/// Calculate Message Authentication Code (MAC) for message.
|
||||
func authenticate(_ bytes: Array<UInt8>) throws -> Array<UInt8>
|
||||
}
|
65
Pods/CryptoSwift/Sources/CryptoSwift/BatchedCollection.swift
generated
Normal file
@ -0,0 +1,65 @@
|
||||
//
|
||||
// BatchedCollection.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
struct BatchedCollectionIndex<Base: Collection> {
|
||||
let range: Range<Base.Index>
|
||||
}
|
||||
|
||||
extension BatchedCollectionIndex: Comparable {
|
||||
static func ==<Base>(lhs: BatchedCollectionIndex<Base>, rhs: BatchedCollectionIndex<Base>) -> Bool {
|
||||
return lhs.range.lowerBound == rhs.range.lowerBound
|
||||
}
|
||||
|
||||
static func < <Base>(lhs: BatchedCollectionIndex<Base>, rhs: BatchedCollectionIndex<Base>) -> Bool {
|
||||
return lhs.range.lowerBound < rhs.range.lowerBound
|
||||
}
|
||||
}
|
||||
|
||||
protocol BatchedCollectionType: Collection {
|
||||
associatedtype Base: Collection
|
||||
}
|
||||
|
||||
struct BatchedCollection<Base: Collection>: Collection {
|
||||
let base: Base
|
||||
let size: Base.IndexDistance
|
||||
typealias Index = BatchedCollectionIndex<Base>
|
||||
private func nextBreak(after idx: Base.Index) -> Base.Index {
|
||||
return base.index(idx, offsetBy: size, limitedBy: base.endIndex)
|
||||
?? base.endIndex
|
||||
}
|
||||
|
||||
var startIndex: Index {
|
||||
return Index(range: base.startIndex..<nextBreak(after: base.startIndex))
|
||||
}
|
||||
|
||||
var endIndex: Index {
|
||||
return Index(range: base.endIndex..<base.endIndex)
|
||||
}
|
||||
|
||||
func index(after idx: Index) -> Index {
|
||||
return Index(range: idx.range.upperBound..<nextBreak(after: idx.range.upperBound))
|
||||
}
|
||||
|
||||
subscript(idx: Index) -> Base.SubSequence {
|
||||
return base[idx.range]
|
||||
}
|
||||
}
|
||||
|
||||
extension Collection {
|
||||
func batched(by size: IndexDistance) -> BatchedCollection<Self> {
|
||||
return BatchedCollection(base: self, size: size)
|
||||
}
|
||||
}
|
27
Pods/CryptoSwift/Sources/CryptoSwift/Bit.swift
generated
Normal file
@ -0,0 +1,27 @@
|
||||
//
|
||||
// Bit.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
public enum Bit: Int {
|
||||
case zero
|
||||
case one
|
||||
}
|
||||
|
||||
extension Bit {
|
||||
|
||||
func inverted() -> Bit {
|
||||
return self == .zero ? .one : .zero
|
||||
}
|
||||
}
|
19
Pods/CryptoSwift/Sources/CryptoSwift/BlockCipher.swift
generated
Normal file
@ -0,0 +1,19 @@
|
||||
//
|
||||
// BlockCipher.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
protocol BlockCipher: Cipher {
|
||||
static var blockSize: Int { get }
|
||||
}
|
77
Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/BlockMode.swift
generated
Normal file
@ -0,0 +1,77 @@
|
||||
//
|
||||
// BlockMode.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
typealias CipherOperationOnBlock = (_ block: ArraySlice<UInt8>) -> Array<UInt8>?
|
||||
|
||||
public enum BlockMode {
|
||||
case ECB, CBC(iv: Array<UInt8>), PCBC(iv: Array<UInt8>), CFB(iv: Array<UInt8>), OFB(iv: Array<UInt8>), CTR(iv: Array<UInt8>)
|
||||
|
||||
public enum Error: Swift.Error {
|
||||
/// Invalid key or IV
|
||||
case invalidKeyOrInitializationVector
|
||||
/// Invalid IV
|
||||
case invalidInitializationVector
|
||||
}
|
||||
|
||||
func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> BlockModeWorker {
|
||||
switch self {
|
||||
case .ECB:
|
||||
return ECBModeWorker(cipherOperation: cipherOperation)
|
||||
case let .CBC(iv):
|
||||
if iv.count != blockSize {
|
||||
throw Error.invalidInitializationVector
|
||||
}
|
||||
return CBCModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
|
||||
case let .PCBC(iv):
|
||||
if iv.count != blockSize {
|
||||
throw Error.invalidInitializationVector
|
||||
}
|
||||
return PCBCModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
|
||||
case let .CFB(iv):
|
||||
if iv.count != blockSize {
|
||||
throw Error.invalidInitializationVector
|
||||
}
|
||||
return CFBModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
|
||||
case let .OFB(iv):
|
||||
if iv.count != blockSize {
|
||||
throw Error.invalidInitializationVector
|
||||
}
|
||||
return OFBModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
|
||||
case let .CTR(iv):
|
||||
if iv.count != blockSize {
|
||||
throw Error.invalidInitializationVector
|
||||
}
|
||||
return CTRModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
|
||||
}
|
||||
}
|
||||
|
||||
var options: BlockModeOptions {
|
||||
switch self {
|
||||
case .ECB:
|
||||
return .paddingRequired
|
||||
case .CBC:
|
||||
return [.initializationVectorRequired, .paddingRequired]
|
||||
case .CFB:
|
||||
return .initializationVectorRequired
|
||||
case .CTR:
|
||||
return .initializationVectorRequired
|
||||
case .OFB:
|
||||
return .initializationVectorRequired
|
||||
case .PCBC:
|
||||
return [.initializationVectorRequired, .paddingRequired]
|
||||
}
|
||||
}
|
||||
}
|
23
Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/BlockModeOptions.swift
generated
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
// BlockModeOptions.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
struct BlockModeOptions: OptionSet {
|
||||
let rawValue: Int
|
||||
|
||||
static let none = BlockModeOptions(rawValue: 0)
|
||||
static let initializationVectorRequired = BlockModeOptions(rawValue: 1)
|
||||
static let paddingRequired = BlockModeOptions(rawValue: 2)
|
||||
}
|
21
Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/BlockModeWorker.swift
generated
Normal file
@ -0,0 +1,21 @@
|
||||
//
|
||||
// BlockModeWorker.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
protocol BlockModeWorker {
|
||||
var cipherOperation: CipherOperationOnBlock { get }
|
||||
mutating func encrypt(_ plaintext: ArraySlice<UInt8>) -> Array<UInt8>
|
||||
mutating func decrypt(_ ciphertext: ArraySlice<UInt8>) -> Array<UInt8>
|
||||
}
|
46
Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/CBC.swift
generated
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// CBC.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
// Cipher-block chaining (CBC)
|
||||
//
|
||||
|
||||
struct CBCModeWorker: BlockModeWorker {
|
||||
let cipherOperation: CipherOperationOnBlock
|
||||
private let iv: ArraySlice<UInt8>
|
||||
private var prev: ArraySlice<UInt8>?
|
||||
|
||||
init(iv: ArraySlice<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
|
||||
self.iv = iv
|
||||
self.cipherOperation = cipherOperation
|
||||
}
|
||||
|
||||
mutating func encrypt(_ plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
|
||||
guard let ciphertext = cipherOperation(xor(prev ?? iv, plaintext)) else {
|
||||
return Array(plaintext)
|
||||
}
|
||||
prev = ciphertext.slice
|
||||
return ciphertext
|
||||
}
|
||||
|
||||
mutating func decrypt(_ ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
|
||||
guard let plaintext = cipherOperation(ciphertext) else {
|
||||
return Array(ciphertext)
|
||||
}
|
||||
let result: Array<UInt8> = xor(prev ?? iv, plaintext)
|
||||
prev = ciphertext
|
||||
return result
|
||||
}
|
||||
}
|
46
Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/CFB.swift
generated
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// CFB.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
// Cipher feedback (CFB)
|
||||
//
|
||||
|
||||
struct CFBModeWorker: BlockModeWorker {
|
||||
let cipherOperation: CipherOperationOnBlock
|
||||
private let iv: ArraySlice<UInt8>
|
||||
private var prev: ArraySlice<UInt8>?
|
||||
|
||||
init(iv: ArraySlice<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
|
||||
self.iv = iv
|
||||
self.cipherOperation = cipherOperation
|
||||
}
|
||||
|
||||
mutating func encrypt(_ plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
|
||||
guard let ciphertext = cipherOperation(prev ?? iv) else {
|
||||
return Array(plaintext)
|
||||
}
|
||||
prev = xor(plaintext, ciphertext.slice)
|
||||
return Array(prev ?? [])
|
||||
}
|
||||
|
||||
mutating func decrypt(_ ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
|
||||
guard let plaintext = cipherOperation(prev ?? iv) else {
|
||||
return Array(ciphertext)
|
||||
}
|
||||
let result: Array<UInt8> = xor(plaintext, ciphertext)
|
||||
prev = ciphertext
|
||||
return result
|
||||
}
|
||||
}
|
52
Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/CTR.swift
generated
Normal file
@ -0,0 +1,52 @@
|
||||
//
|
||||
// CTR.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
// Counter (CTR)
|
||||
//
|
||||
|
||||
struct CTRModeWorker: RandomAccessBlockModeWorker {
|
||||
let cipherOperation: CipherOperationOnBlock
|
||||
private let iv: ArraySlice<UInt8>
|
||||
var counter: UInt = 0
|
||||
|
||||
init(iv: ArraySlice<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
|
||||
self.iv = iv
|
||||
self.cipherOperation = cipherOperation
|
||||
}
|
||||
|
||||
mutating func encrypt(_ plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
|
||||
let nonce = buildNonce(iv, counter: UInt64(counter))
|
||||
counter = counter + 1
|
||||
|
||||
guard let ciphertext = cipherOperation(nonce.slice) else {
|
||||
return Array(plaintext)
|
||||
}
|
||||
|
||||
return xor(plaintext, ciphertext)
|
||||
}
|
||||
|
||||
mutating func decrypt(_ ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
|
||||
return encrypt(ciphertext)
|
||||
}
|
||||
}
|
||||
|
||||
private func buildNonce(_ iv: ArraySlice<UInt8>, counter: UInt64) -> Array<UInt8> {
|
||||
let noncePartLen = AES.blockSize / 2
|
||||
let noncePrefix = Array(iv[iv.startIndex..<iv.startIndex.advanced(by: noncePartLen)])
|
||||
let nonceSuffix = Array(iv[iv.startIndex.advanced(by: noncePartLen)..<iv.startIndex.advanced(by: iv.count)])
|
||||
let c = UInt64(bytes: nonceSuffix) + counter
|
||||
return noncePrefix + c.bytes()
|
||||
}
|
38
Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/ECB.swift
generated
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// BlockMode.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
// Electronic codebook (ECB)
|
||||
//
|
||||
|
||||
struct ECBModeWorker: BlockModeWorker {
|
||||
typealias Element = Array<UInt8>
|
||||
let cipherOperation: CipherOperationOnBlock
|
||||
|
||||
init(cipherOperation: @escaping CipherOperationOnBlock) {
|
||||
self.cipherOperation = cipherOperation
|
||||
}
|
||||
|
||||
mutating func encrypt(_ plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
|
||||
guard let ciphertext = cipherOperation(plaintext) else {
|
||||
return Array(plaintext)
|
||||
}
|
||||
return ciphertext
|
||||
}
|
||||
|
||||
mutating func decrypt(_ ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
|
||||
return encrypt(ciphertext)
|
||||
}
|
||||
}
|
46
Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/OFB.swift
generated
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// OFB.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
// Output Feedback (OFB)
|
||||
//
|
||||
|
||||
struct OFBModeWorker: BlockModeWorker {
|
||||
let cipherOperation: CipherOperationOnBlock
|
||||
private let iv: ArraySlice<UInt8>
|
||||
private var prev: ArraySlice<UInt8>?
|
||||
|
||||
init(iv: ArraySlice<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
|
||||
self.iv = iv
|
||||
self.cipherOperation = cipherOperation
|
||||
}
|
||||
|
||||
mutating func encrypt(_ plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
|
||||
guard let ciphertext = cipherOperation(prev ?? iv) else {
|
||||
return Array(plaintext)
|
||||
}
|
||||
prev = ciphertext.slice
|
||||
return xor(plaintext, ciphertext)
|
||||
}
|
||||
|
||||
mutating func decrypt(_ ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
|
||||
guard let decrypted = cipherOperation(prev ?? iv) else {
|
||||
return Array(ciphertext)
|
||||
}
|
||||
let plaintext: Array<UInt8> = xor(decrypted, ciphertext)
|
||||
prev = decrypted.slice
|
||||
return plaintext
|
||||
}
|
||||
}
|
46
Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/PCBC.swift
generated
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// PCBM.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
// Propagating Cipher Block Chaining (PCBC)
|
||||
//
|
||||
|
||||
struct PCBCModeWorker: BlockModeWorker {
|
||||
let cipherOperation: CipherOperationOnBlock
|
||||
private let iv: ArraySlice<UInt8>
|
||||
private var prev: ArraySlice<UInt8>?
|
||||
|
||||
init(iv: ArraySlice<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
|
||||
self.iv = iv
|
||||
self.cipherOperation = cipherOperation
|
||||
}
|
||||
|
||||
mutating func encrypt(_ plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
|
||||
guard let ciphertext = cipherOperation(xor(prev ?? iv, plaintext)) else {
|
||||
return Array(plaintext)
|
||||
}
|
||||
prev = xor(plaintext, ciphertext.slice)
|
||||
return ciphertext
|
||||
}
|
||||
|
||||
mutating func decrypt(_ ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
|
||||
guard let plaintext = cipherOperation(ciphertext) else {
|
||||
return Array(ciphertext)
|
||||
}
|
||||
let result: Array<UInt8> = xor(prev ?? iv, plaintext)
|
||||
prev = xor(plaintext.slice, ciphertext)
|
||||
return result
|
||||
}
|
||||
}
|
19
Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/RandomAccessBlockModeWorker.swift
generated
Normal file
@ -0,0 +1,19 @@
|
||||
//
|
||||
// RandomAccessBlockModeWorker.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
protocol RandomAccessBlockModeWorker: BlockModeWorker {
|
||||
var counter: UInt { set get }
|
||||
}
|
538
Pods/CryptoSwift/Sources/CryptoSwift/Blowfish.swift
generated
Normal file
@ -0,0 +1,538 @@
|
||||
//
|
||||
// Blowfish.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
// https://en.wikipedia.org/wiki/Blowfish_(cipher)
|
||||
// Based on Paul Kocher implementation
|
||||
//
|
||||
|
||||
public final class Blowfish {
|
||||
|
||||
public enum Error: Swift.Error {
|
||||
/// Data padding is required
|
||||
case dataPaddingRequired
|
||||
/// Invalid key or IV
|
||||
case invalidKeyOrInitializationVector
|
||||
/// Invalid IV
|
||||
case invalidInitializationVector
|
||||
}
|
||||
|
||||
public static let blockSize: Int = 8 // 64 bit
|
||||
fileprivate let blockMode: BlockMode
|
||||
fileprivate let padding: Padding
|
||||
private var decryptWorker: BlockModeWorker!
|
||||
private var encryptWorker: BlockModeWorker!
|
||||
|
||||
private let N = 16 // rounds
|
||||
private var P: Array<UInt32>
|
||||
private var S: Array<Array<UInt32>>
|
||||
private let origP: Array<UInt32> = [
|
||||
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822,
|
||||
0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377,
|
||||
0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5,
|
||||
0xb5470917, 0x9216d5d9, 0x8979fb1b,
|
||||
]
|
||||
|
||||
private let origS: Array<Array<UInt32>> = [
|
||||
[
|
||||
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
|
||||
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
|
||||
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
|
||||
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
|
||||
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
|
||||
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
||||
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
|
||||
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
|
||||
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
|
||||
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
|
||||
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
|
||||
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
||||
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
|
||||
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
|
||||
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
|
||||
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
|
||||
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
|
||||
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
||||
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
|
||||
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
|
||||
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
|
||||
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
|
||||
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
|
||||
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
||||
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
|
||||
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
|
||||
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
|
||||
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
|
||||
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
|
||||
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
||||
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
|
||||
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
|
||||
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
|
||||
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
|
||||
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
|
||||
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
||||
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
|
||||
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
|
||||
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
|
||||
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
|
||||
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
|
||||
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
||||
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
|
||||
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
|
||||
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
|
||||
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
|
||||
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
|
||||
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
||||
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
|
||||
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
|
||||
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
|
||||
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
|
||||
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
|
||||
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
||||
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
|
||||
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
|
||||
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
|
||||
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
|
||||
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
|
||||
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
||||
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
|
||||
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
|
||||
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
|
||||
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
|
||||
],
|
||||
[
|
||||
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
|
||||
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
|
||||
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
|
||||
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
|
||||
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
|
||||
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
|
||||
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
|
||||
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
|
||||
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
|
||||
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
|
||||
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
|
||||
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
|
||||
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
|
||||
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
|
||||
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
|
||||
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
|
||||
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
|
||||
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
|
||||
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
|
||||
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
|
||||
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
|
||||
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
|
||||
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
|
||||
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
|
||||
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
|
||||
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
|
||||
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
|
||||
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
|
||||
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
|
||||
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
|
||||
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
|
||||
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
|
||||
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
|
||||
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
|
||||
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
|
||||
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
|
||||
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
|
||||
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
|
||||
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
|
||||
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
|
||||
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
|
||||
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
|
||||
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
|
||||
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
|
||||
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
|
||||
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
|
||||
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
|
||||
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
|
||||
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
|
||||
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
|
||||
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
|
||||
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
|
||||
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
|
||||
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
|
||||
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
|
||||
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
|
||||
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
|
||||
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
|
||||
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
|
||||
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
|
||||
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
|
||||
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
|
||||
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
|
||||
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
|
||||
],
|
||||
[
|
||||
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
|
||||
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
|
||||
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
|
||||
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
|
||||
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
|
||||
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
|
||||
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
|
||||
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
|
||||
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
|
||||
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
|
||||
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
|
||||
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
|
||||
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
|
||||
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
|
||||
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
|
||||
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
|
||||
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
|
||||
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
|
||||
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
|
||||
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
|
||||
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
|
||||
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
|
||||
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
|
||||
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
|
||||
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
|
||||
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
|
||||
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
|
||||
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
|
||||
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
|
||||
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
|
||||
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
|
||||
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
|
||||
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
|
||||
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
|
||||
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
|
||||
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
|
||||
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
|
||||
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
|
||||
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
|
||||
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
|
||||
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
|
||||
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
|
||||
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
|
||||
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
|
||||
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
|
||||
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
|
||||
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
|
||||
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
|
||||
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
|
||||
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
|
||||
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
|
||||
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
|
||||
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
|
||||
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
|
||||
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
|
||||
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
|
||||
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
|
||||
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
|
||||
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
|
||||
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
|
||||
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
|
||||
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
|
||||
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
|
||||
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
|
||||
],
|
||||
[
|
||||
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
|
||||
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
|
||||
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
|
||||
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
|
||||
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
|
||||
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
||||
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
|
||||
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
|
||||
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
|
||||
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
|
||||
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
|
||||
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
||||
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
|
||||
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
|
||||
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
|
||||
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
|
||||
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
|
||||
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
||||
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
|
||||
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
|
||||
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
|
||||
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
|
||||
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
|
||||
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
||||
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
|
||||
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
|
||||
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
|
||||
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
|
||||
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
|
||||
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
||||
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
|
||||
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
|
||||
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
|
||||
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
|
||||
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
|
||||
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
||||
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
|
||||
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
|
||||
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
|
||||
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
|
||||
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
|
||||
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
||||
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
|
||||
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
|
||||
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
|
||||
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
|
||||
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
|
||||
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
||||
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
|
||||
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
|
||||
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
|
||||
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
|
||||
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
|
||||
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
||||
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
|
||||
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
|
||||
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
|
||||
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
|
||||
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
|
||||
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
||||
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
|
||||
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
|
||||
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
|
||||
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
|
||||
],
|
||||
]
|
||||
|
||||
public init(key: Array<UInt8>, blockMode: BlockMode = .CBC(iv: Array<UInt8>(repeating: 0, count: Blowfish.blockSize)), padding: Padding) throws {
|
||||
precondition(key.count >= 5 && key.count <= 56)
|
||||
|
||||
self.blockMode = blockMode
|
||||
self.padding = padding
|
||||
|
||||
S = origS
|
||||
P = origP
|
||||
|
||||
expandKey(key: key)
|
||||
try setupBlockModeWorkers()
|
||||
}
|
||||
|
||||
private func setupBlockModeWorkers() throws {
|
||||
encryptWorker = try blockMode.worker(blockSize: Blowfish.blockSize, cipherOperation: encrypt)
|
||||
|
||||
switch blockMode {
|
||||
case .CFB, .OFB, .CTR:
|
||||
decryptWorker = try blockMode.worker(blockSize: Blowfish.blockSize, cipherOperation: encrypt)
|
||||
default:
|
||||
decryptWorker = try blockMode.worker(blockSize: Blowfish.blockSize, cipherOperation: decrypt)
|
||||
}
|
||||
}
|
||||
|
||||
private func reset() {
|
||||
S = origS
|
||||
P = origP
|
||||
// todo expand key
|
||||
}
|
||||
|
||||
private func expandKey(key: Array<UInt8>) {
|
||||
var j = 0
|
||||
for i in 0..<(N + 2) {
|
||||
var data: UInt32 = 0x0
|
||||
for _ in 0..<4 {
|
||||
data = (data << 8) | UInt32(key[j])
|
||||
j += 1
|
||||
if j >= key.count {
|
||||
j = 0
|
||||
}
|
||||
}
|
||||
P[i] ^= data
|
||||
}
|
||||
|
||||
var datal: UInt32 = 0
|
||||
var datar: UInt32 = 0
|
||||
|
||||
for i in stride(from: 0, to: N + 2, by: 2) {
|
||||
encryptBlowfishBlock(l: &datal, r: &datar)
|
||||
P[i] = datal
|
||||
P[i + 1] = datar
|
||||
}
|
||||
|
||||
for i in 0..<4 {
|
||||
for j in stride(from: 0, to: 256, by: 2) {
|
||||
encryptBlowfishBlock(l: &datal, r: &datar)
|
||||
S[i][j] = datal
|
||||
S[i][j + 1] = datar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func encrypt(block: ArraySlice<UInt8>) -> Array<UInt8>? {
|
||||
var result = Array<UInt8>()
|
||||
|
||||
var l = UInt32(bytes: block[block.startIndex..<block.startIndex.advanced(by: 4)])
|
||||
var r = UInt32(bytes: block[block.startIndex.advanced(by: 4)..<block.startIndex.advanced(by: 8)])
|
||||
|
||||
encryptBlowfishBlock(l: &l, r: &r)
|
||||
|
||||
// because everything is too complex to be solved in reasonable time o_O
|
||||
result += [
|
||||
UInt8((l >> 24) & 0xff),
|
||||
UInt8((l >> 16) & 0xff),
|
||||
]
|
||||
result += [
|
||||
UInt8((l >> 8) & 0xff),
|
||||
UInt8((l >> 0) & 0xff),
|
||||
]
|
||||
result += [
|
||||
UInt8((r >> 24) & 0xff),
|
||||
UInt8((r >> 16) & 0xff),
|
||||
]
|
||||
result += [
|
||||
UInt8((r >> 8) & 0xff),
|
||||
UInt8((r >> 0) & 0xff),
|
||||
]
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
fileprivate func decrypt(block: ArraySlice<UInt8>) -> Array<UInt8>? {
|
||||
var result = Array<UInt8>()
|
||||
|
||||
var l = UInt32(bytes: block[block.startIndex..<block.startIndex.advanced(by: 4)])
|
||||
var r = UInt32(bytes: block[block.startIndex.advanced(by: 4)..<block.startIndex.advanced(by: 8)])
|
||||
|
||||
decryptBlowfishBlock(l: &l, r: &r)
|
||||
|
||||
// because everything is too complex to be solved in reasonable time o_O
|
||||
result += [
|
||||
UInt8((l >> 24) & 0xff),
|
||||
UInt8((l >> 16) & 0xff),
|
||||
]
|
||||
result += [
|
||||
UInt8((l >> 8) & 0xff),
|
||||
UInt8((l >> 0) & 0xff),
|
||||
]
|
||||
result += [
|
||||
UInt8((r >> 24) & 0xff),
|
||||
UInt8((r >> 16) & 0xff),
|
||||
]
|
||||
result += [
|
||||
UInt8((r >> 8) & 0xff),
|
||||
UInt8((r >> 0) & 0xff),
|
||||
]
|
||||
return result
|
||||
}
|
||||
|
||||
/// Encrypts the 8-byte padded buffer
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - l: left half
|
||||
/// - r: right half
|
||||
fileprivate func encryptBlowfishBlock(l: inout UInt32, r: inout UInt32) {
|
||||
var Xl = l
|
||||
var Xr = r
|
||||
|
||||
for i in 0..<N {
|
||||
Xl = Xl ^ P[i]
|
||||
Xr = F(x: Xl) ^ Xr
|
||||
|
||||
(Xl, Xr) = (Xr, Xl)
|
||||
}
|
||||
|
||||
(Xl, Xr) = (Xr, Xl)
|
||||
|
||||
Xr = Xr ^ P[self.N]
|
||||
Xl = Xl ^ P[self.N + 1]
|
||||
|
||||
l = Xl
|
||||
r = Xr
|
||||
}
|
||||
|
||||
/// Decrypts the 8-byte padded buffer
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - l: left half
|
||||
/// - r: right half
|
||||
fileprivate func decryptBlowfishBlock(l: inout UInt32, r: inout UInt32) {
|
||||
var Xl = l
|
||||
var Xr = r
|
||||
|
||||
for i in (2...N + 1).reversed() {
|
||||
Xl = Xl ^ P[i]
|
||||
Xr = F(x: Xl) ^ Xr
|
||||
|
||||
(Xl, Xr) = (Xr, Xl)
|
||||
}
|
||||
|
||||
(Xl, Xr) = (Xr, Xl)
|
||||
|
||||
Xr = Xr ^ P[1]
|
||||
Xl = Xl ^ P[0]
|
||||
|
||||
l = Xl
|
||||
r = Xr
|
||||
}
|
||||
|
||||
private func F(x: UInt32) -> UInt32 {
|
||||
let f1 = S[0][Int(x >> 24) & 0xff]
|
||||
let f2 = S[1][Int(x >> 16) & 0xff]
|
||||
let f3 = S[2][Int(x >> 8) & 0xff]
|
||||
let f4 = S[3][Int(x & 0xff)]
|
||||
return ((f1 &+ f2) ^ f3) &+ f4
|
||||
}
|
||||
}
|
||||
|
||||
extension Blowfish: Cipher {
|
||||
|
||||
/// Encrypt the 8-byte padded buffer, block by block. Note that for amounts of data larger than a block, it is not safe to just call encrypt() on successive blocks.
|
||||
///
|
||||
/// - Parameter bytes: Plaintext data
|
||||
/// - Returns: Encrypted data
|
||||
public func encrypt<C: Collection>(_ bytes: C) throws -> Array<UInt8> where C.Element == UInt8, C.IndexDistance == Int, C.Index == Int {
|
||||
|
||||
let bytes = padding.add(to: Array(bytes), blockSize: Blowfish.blockSize) // FIXME: Array(bytes) copies
|
||||
|
||||
var out = Array<UInt8>()
|
||||
out.reserveCapacity(bytes.count)
|
||||
|
||||
for chunk in bytes.batched(by: Blowfish.blockSize) {
|
||||
out += encryptWorker.encrypt(chunk)
|
||||
}
|
||||
|
||||
if blockMode.options.contains(.paddingRequired) && (out.count % Blowfish.blockSize != 0) {
|
||||
throw Error.dataPaddingRequired
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
/// Decrypt the 8-byte padded buffer
|
||||
///
|
||||
/// - Parameter bytes: Ciphertext data
|
||||
/// - Returns: Plaintext data
|
||||
public func decrypt<C: Collection>(_ bytes: C) throws -> Array<UInt8> where C.Element == UInt8, C.IndexDistance == Int, C.Index == Int {
|
||||
|
||||
if blockMode.options.contains(.paddingRequired) && (bytes.count % Blowfish.blockSize != 0) {
|
||||
throw Error.dataPaddingRequired
|
||||
}
|
||||
|
||||
var out = Array<UInt8>()
|
||||
out.reserveCapacity(bytes.count)
|
||||
|
||||
for chunk in Array(bytes).batched(by: Blowfish.blockSize) {
|
||||
out += decryptWorker.decrypt(chunk) // FIXME: copying here is innefective
|
||||
}
|
||||
|
||||
out = padding.remove(from: out, blockSize: Blowfish.blockSize)
|
||||
|
||||
return out
|
||||
}
|
||||
}
|
336
Pods/CryptoSwift/Sources/CryptoSwift/ChaCha20.swift
generated
Normal file
@ -0,0 +1,336 @@
|
||||
//
|
||||
// ChaCha20.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
// https://tools.ietf.org/html/rfc7539
|
||||
//
|
||||
|
||||
public final class ChaCha20: BlockCipher {
|
||||
|
||||
public enum Error: Swift.Error {
|
||||
case invalidKeyOrInitializationVector
|
||||
}
|
||||
|
||||
public static let blockSize = 64 // 512 / 8
|
||||
|
||||
fileprivate let key: Key
|
||||
fileprivate var counter: Array<UInt8>
|
||||
|
||||
public init(key: Array<UInt8>, iv nonce: Array<UInt8>) throws {
|
||||
precondition(nonce.count == 12 || nonce.count == 8)
|
||||
|
||||
if key.count != 32 {
|
||||
throw Error.invalidKeyOrInitializationVector
|
||||
}
|
||||
|
||||
self.key = Key(bytes: key)
|
||||
|
||||
if nonce.count == 8 {
|
||||
counter = [0, 0, 0, 0, 0, 0, 0, 0] + nonce
|
||||
} else {
|
||||
counter = [0, 0, 0, 0] + nonce
|
||||
}
|
||||
|
||||
assert(counter.count == 16)
|
||||
}
|
||||
|
||||
/// https://tools.ietf.org/html/rfc7539#section-2.3.
|
||||
fileprivate func core(block: inout Array<UInt8>, counter: Array<UInt8>, key: Array<UInt8>) {
|
||||
precondition(block.count == ChaCha20.blockSize)
|
||||
precondition(counter.count == 16)
|
||||
precondition(key.count == 32)
|
||||
|
||||
let j0: UInt32 = 0x61707865
|
||||
let j1: UInt32 = 0x3320646e // 0x3620646e sigma/tau
|
||||
let j2: UInt32 = 0x79622d32
|
||||
let j3: UInt32 = 0x6b206574
|
||||
let j4: UInt32 = UInt32(bytes: key[0..<4]).bigEndian
|
||||
let j5: UInt32 = UInt32(bytes: key[4..<8]).bigEndian
|
||||
let j6: UInt32 = UInt32(bytes: key[8..<12]).bigEndian
|
||||
let j7: UInt32 = UInt32(bytes: key[12..<16]).bigEndian
|
||||
let j8: UInt32 = UInt32(bytes: key[16..<20]).bigEndian
|
||||
let j9: UInt32 = UInt32(bytes: key[20..<24]).bigEndian
|
||||
let j10: UInt32 = UInt32(bytes: key[24..<28]).bigEndian
|
||||
let j11: UInt32 = UInt32(bytes: key[28..<32]).bigEndian
|
||||
let j12: UInt32 = UInt32(bytes: counter[0..<4]).bigEndian
|
||||
let j13: UInt32 = UInt32(bytes: counter[4..<8]).bigEndian
|
||||
let j14: UInt32 = UInt32(bytes: counter[8..<12]).bigEndian
|
||||
let j15: UInt32 = UInt32(bytes: counter[12..<16]).bigEndian
|
||||
|
||||
var (x0, x1, x2, x3, x4, x5, x6, x7) = (j0, j1, j2, j3, j4, j5, j6, j7)
|
||||
var (x8, x9, x10, x11, x12, x13, x14, x15) = (j8, j9, j10, j11, j12, j13, j14, j15)
|
||||
|
||||
for _ in 0..<10 { // 20 rounds
|
||||
x0 = x0 &+ x4
|
||||
x12 ^= x0
|
||||
x12 = (x12 << 16) | (x12 >> 16)
|
||||
x8 = x8 &+ x12
|
||||
x4 ^= x8
|
||||
x4 = (x4 << 12) | (x4 >> 20)
|
||||
x0 = x0 &+ x4
|
||||
x12 ^= x0
|
||||
x12 = (x12 << 8) | (x12 >> 24)
|
||||
x8 = x8 &+ x12
|
||||
x4 ^= x8
|
||||
x4 = (x4 << 7) | (x4 >> 25)
|
||||
x1 = x1 &+ x5
|
||||
x13 ^= x1
|
||||
x13 = (x13 << 16) | (x13 >> 16)
|
||||
x9 = x9 &+ x13
|
||||
x5 ^= x9
|
||||
x5 = (x5 << 12) | (x5 >> 20)
|
||||
x1 = x1 &+ x5
|
||||
x13 ^= x1
|
||||
x13 = (x13 << 8) | (x13 >> 24)
|
||||
x9 = x9 &+ x13
|
||||
x5 ^= x9
|
||||
x5 = (x5 << 7) | (x5 >> 25)
|
||||
x2 = x2 &+ x6
|
||||
x14 ^= x2
|
||||
x14 = (x14 << 16) | (x14 >> 16)
|
||||
x10 = x10 &+ x14
|
||||
x6 ^= x10
|
||||
x6 = (x6 << 12) | (x6 >> 20)
|
||||
x2 = x2 &+ x6
|
||||
x14 ^= x2
|
||||
x14 = (x14 << 8) | (x14 >> 24)
|
||||
x10 = x10 &+ x14
|
||||
x6 ^= x10
|
||||
x6 = (x6 << 7) | (x6 >> 25)
|
||||
x3 = x3 &+ x7
|
||||
x15 ^= x3
|
||||
x15 = (x15 << 16) | (x15 >> 16)
|
||||
x11 = x11 &+ x15
|
||||
x7 ^= x11
|
||||
x7 = (x7 << 12) | (x7 >> 20)
|
||||
x3 = x3 &+ x7
|
||||
x15 ^= x3
|
||||
x15 = (x15 << 8) | (x15 >> 24)
|
||||
x11 = x11 &+ x15
|
||||
x7 ^= x11
|
||||
x7 = (x7 << 7) | (x7 >> 25)
|
||||
x0 = x0 &+ x5
|
||||
x15 ^= x0
|
||||
x15 = (x15 << 16) | (x15 >> 16)
|
||||
x10 = x10 &+ x15
|
||||
x5 ^= x10
|
||||
x5 = (x5 << 12) | (x5 >> 20)
|
||||
x0 = x0 &+ x5
|
||||
x15 ^= x0
|
||||
x15 = (x15 << 8) | (x15 >> 24)
|
||||
x10 = x10 &+ x15
|
||||
x5 ^= x10
|
||||
x5 = (x5 << 7) | (x5 >> 25)
|
||||
x1 = x1 &+ x6
|
||||
x12 ^= x1
|
||||
x12 = (x12 << 16) | (x12 >> 16)
|
||||
x11 = x11 &+ x12
|
||||
x6 ^= x11
|
||||
x6 = (x6 << 12) | (x6 >> 20)
|
||||
x1 = x1 &+ x6
|
||||
x12 ^= x1
|
||||
x12 = (x12 << 8) | (x12 >> 24)
|
||||
x11 = x11 &+ x12
|
||||
x6 ^= x11
|
||||
x6 = (x6 << 7) | (x6 >> 25)
|
||||
x2 = x2 &+ x7
|
||||
x13 ^= x2
|
||||
x13 = (x13 << 16) | (x13 >> 16)
|
||||
x8 = x8 &+ x13
|
||||
x7 ^= x8
|
||||
x7 = (x7 << 12) | (x7 >> 20)
|
||||
x2 = x2 &+ x7
|
||||
x13 ^= x2
|
||||
x13 = (x13 << 8) | (x13 >> 24)
|
||||
x8 = x8 &+ x13
|
||||
x7 ^= x8
|
||||
x7 = (x7 << 7) | (x7 >> 25)
|
||||
x3 = x3 &+ x4
|
||||
x14 ^= x3
|
||||
x14 = (x14 << 16) | (x14 >> 16)
|
||||
x9 = x9 &+ x14
|
||||
x4 ^= x9
|
||||
x4 = (x4 << 12) | (x4 >> 20)
|
||||
x3 = x3 &+ x4
|
||||
x14 ^= x3
|
||||
x14 = (x14 << 8) | (x14 >> 24)
|
||||
x9 = x9 &+ x14
|
||||
x4 ^= x9
|
||||
x4 = (x4 << 7) | (x4 >> 25)
|
||||
}
|
||||
|
||||
x0 = x0 &+ j0
|
||||
x1 = x1 &+ j1
|
||||
x2 = x2 &+ j2
|
||||
x3 = x3 &+ j3
|
||||
x4 = x4 &+ j4
|
||||
x5 = x5 &+ j5
|
||||
x6 = x6 &+ j6
|
||||
x7 = x7 &+ j7
|
||||
x8 = x8 &+ j8
|
||||
x9 = x9 &+ j9
|
||||
x10 = x10 &+ j10
|
||||
x11 = x11 &+ j11
|
||||
x12 = x12 &+ j12
|
||||
x13 = x13 &+ j13
|
||||
x14 = x14 &+ j14
|
||||
x15 = x15 &+ j15
|
||||
|
||||
block.replaceSubrange(0..<4, with: x0.bigEndian.bytes())
|
||||
block.replaceSubrange(4..<8, with: x1.bigEndian.bytes())
|
||||
block.replaceSubrange(8..<12, with: x2.bigEndian.bytes())
|
||||
block.replaceSubrange(12..<16, with: x3.bigEndian.bytes())
|
||||
block.replaceSubrange(16..<20, with: x4.bigEndian.bytes())
|
||||
block.replaceSubrange(20..<24, with: x5.bigEndian.bytes())
|
||||
block.replaceSubrange(24..<28, with: x6.bigEndian.bytes())
|
||||
block.replaceSubrange(28..<32, with: x7.bigEndian.bytes())
|
||||
block.replaceSubrange(32..<36, with: x8.bigEndian.bytes())
|
||||
block.replaceSubrange(36..<40, with: x9.bigEndian.bytes())
|
||||
block.replaceSubrange(40..<44, with: x10.bigEndian.bytes())
|
||||
block.replaceSubrange(44..<48, with: x11.bigEndian.bytes())
|
||||
block.replaceSubrange(48..<52, with: x12.bigEndian.bytes())
|
||||
block.replaceSubrange(52..<56, with: x13.bigEndian.bytes())
|
||||
block.replaceSubrange(56..<60, with: x14.bigEndian.bytes())
|
||||
block.replaceSubrange(60..<64, with: x15.bigEndian.bytes())
|
||||
}
|
||||
|
||||
// XORKeyStream
|
||||
func process(bytes: Array<UInt8>, counter: inout Array<UInt8>, key: Array<UInt8>) -> Array<UInt8> {
|
||||
precondition(counter.count == 16)
|
||||
precondition(key.count == 32)
|
||||
|
||||
var block = Array<UInt8>(repeating: 0, count: ChaCha20.blockSize)
|
||||
var bytes = bytes // TODO: check bytes[bytes.indices]
|
||||
var out = Array<UInt8>(reserveCapacity: bytes.count)
|
||||
|
||||
while bytes.count >= ChaCha20.blockSize {
|
||||
core(block: &block, counter: counter, key: key)
|
||||
for (i, x) in block.enumerated() {
|
||||
out.append(bytes[i] ^ x)
|
||||
}
|
||||
var u: UInt32 = 1
|
||||
for i in 0..<4 {
|
||||
u += UInt32(counter[i])
|
||||
counter[i] = UInt8(u & 0xFF)
|
||||
u >>= 8
|
||||
}
|
||||
bytes = Array(bytes[ChaCha20.blockSize..<bytes.endIndex])
|
||||
}
|
||||
|
||||
if bytes.count > 0 {
|
||||
core(block: &block, counter: counter, key: key)
|
||||
for (i, v) in bytes.enumerated() {
|
||||
out.append(v ^ block[i])
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Cipher
|
||||
extension ChaCha20: Cipher {
|
||||
|
||||
public func encrypt(_ bytes: ArraySlice<UInt8>) throws -> Array<UInt8> {
|
||||
return process(bytes: Array(bytes), counter: &counter, key: Array(key))
|
||||
}
|
||||
|
||||
public func decrypt(_ bytes: ArraySlice<UInt8>) throws -> Array<UInt8> {
|
||||
return try encrypt(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Encryptor
|
||||
extension ChaCha20 {
|
||||
|
||||
public struct Encryptor: Updatable {
|
||||
private var accumulated = Array<UInt8>()
|
||||
private let chacha: ChaCha20
|
||||
|
||||
init(chacha: ChaCha20) {
|
||||
self.chacha = chacha
|
||||
}
|
||||
|
||||
public mutating func update(withBytes bytes: ArraySlice<UInt8>, isLast: Bool = false) throws -> Array<UInt8> {
|
||||
accumulated += bytes
|
||||
|
||||
var encrypted = Array<UInt8>()
|
||||
encrypted.reserveCapacity(accumulated.count)
|
||||
for chunk in accumulated.batched(by: ChaCha20.blockSize) {
|
||||
if isLast || accumulated.count >= ChaCha20.blockSize {
|
||||
encrypted += try chacha.encrypt(chunk)
|
||||
accumulated.removeFirst(chunk.count) // TODO: improve performance
|
||||
}
|
||||
}
|
||||
return encrypted
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Decryptor
|
||||
extension ChaCha20 {
|
||||
|
||||
public struct Decryptor: Updatable {
|
||||
private var accumulated = Array<UInt8>()
|
||||
|
||||
private var offset: Int = 0
|
||||
private var offsetToRemove: Int = 0
|
||||
private let chacha: ChaCha20
|
||||
|
||||
init(chacha: ChaCha20) {
|
||||
self.chacha = chacha
|
||||
}
|
||||
|
||||
public mutating func update(withBytes bytes: ArraySlice<UInt8>, isLast: Bool = true) throws -> Array<UInt8> {
|
||||
// prepend "offset" number of bytes at the begining
|
||||
if offset > 0 {
|
||||
accumulated += Array<UInt8>(repeating: 0, count: offset) + bytes
|
||||
offsetToRemove = offset
|
||||
offset = 0
|
||||
} else {
|
||||
accumulated += bytes
|
||||
}
|
||||
|
||||
var plaintext = Array<UInt8>()
|
||||
plaintext.reserveCapacity(accumulated.count)
|
||||
for chunk in accumulated.batched(by: ChaCha20.blockSize) {
|
||||
if isLast || accumulated.count >= ChaCha20.blockSize {
|
||||
plaintext += try chacha.decrypt(chunk)
|
||||
|
||||
// remove "offset" from the beginning of first chunk
|
||||
if offsetToRemove > 0 {
|
||||
plaintext.removeFirst(offsetToRemove) // TODO: improve performance
|
||||
offsetToRemove = 0
|
||||
}
|
||||
|
||||
accumulated.removeFirst(chunk.count)
|
||||
}
|
||||
}
|
||||
|
||||
return plaintext
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Cryptors
|
||||
extension ChaCha20: Cryptors {
|
||||
|
||||
public func makeEncryptor() -> ChaCha20.Encryptor {
|
||||
return Encryptor(chacha: self)
|
||||
}
|
||||
|
||||
public func makeDecryptor() -> ChaCha20.Decryptor {
|
||||
return Decryptor(chacha: self)
|
||||
}
|
||||
}
|
134
Pods/CryptoSwift/Sources/CryptoSwift/Checksum.swift
generated
Normal file
@ -0,0 +1,134 @@
|
||||
//
|
||||
// Checksum.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
/// CRC - cyclic redundancy check code.
|
||||
public final class Checksum {
|
||||
private static let table32: Array<UInt32> = [
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
|
||||
]
|
||||
|
||||
private static let table16: Array<UInt16> = [
|
||||
0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
|
||||
0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
|
||||
0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
|
||||
0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
|
||||
0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
|
||||
0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
|
||||
0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
|
||||
0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
|
||||
0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
|
||||
0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
|
||||
0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
|
||||
0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
|
||||
0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
|
||||
0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
|
||||
0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
|
||||
0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
|
||||
0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
|
||||
0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
|
||||
0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
|
||||
0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
|
||||
0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
|
||||
0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
|
||||
0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
|
||||
0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
|
||||
0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
|
||||
0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
|
||||
0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
|
||||
0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
|
||||
0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
|
||||
0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
|
||||
0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
|
||||
0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040,
|
||||
]
|
||||
|
||||
func crc32(_ message: Array<UInt8>, seed: UInt32? = nil, reflect: Bool = true) -> UInt32 {
|
||||
var crc: UInt32 = seed != nil ? seed! : 0xffffffff
|
||||
for chunk in message.batched(by: 256) {
|
||||
for b in chunk {
|
||||
let idx = Int((crc ^ UInt32(reflect ? b : reversed(b))) & 0xff)
|
||||
crc = (crc >> 8) ^ Checksum.table32[idx]
|
||||
}
|
||||
}
|
||||
return (reflect ? crc : reversed(crc)) ^ 0xffffffff
|
||||
}
|
||||
|
||||
func crc16(_ message: Array<UInt8>, seed: UInt16? = nil) -> UInt16 {
|
||||
var crc: UInt16 = seed != nil ? seed! : 0x0000
|
||||
for chunk in message.batched(by: 256) {
|
||||
for b in chunk {
|
||||
crc = (crc >> 8) ^ Checksum.table16[Int((crc ^ UInt16(b)) & 0xff)]
|
||||
}
|
||||
}
|
||||
return crc
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Public interface
|
||||
public extension Checksum {
|
||||
|
||||
/// Calculate CRC32
|
||||
///
|
||||
/// - parameter message: Message
|
||||
/// - parameter seed: Seed value (Optional)
|
||||
/// - parameter reflect: is reflect (default true)
|
||||
///
|
||||
/// - returns: Calculated code
|
||||
static func crc32(_ message: Array<UInt8>, seed: UInt32? = nil, reflect: Bool = true) -> UInt32 {
|
||||
return Checksum().crc32(message, seed: seed, reflect: reflect)
|
||||
}
|
||||
|
||||
/// Calculate CRC16
|
||||
///
|
||||
/// - parameter message: Message
|
||||
/// - parameter seed: Seed value (Optional)
|
||||
///
|
||||
/// - returns: Calculated code
|
||||
static func crc16(_ message: Array<UInt8>, seed: UInt16? = nil) -> UInt16 {
|
||||
return Checksum().crc16(message, seed: seed)
|
||||
}
|
||||
}
|
46
Pods/CryptoSwift/Sources/CryptoSwift/Cipher.swift
generated
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// Cipher.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
public enum CipherError: Error {
|
||||
case encrypt
|
||||
case decrypt
|
||||
}
|
||||
|
||||
public protocol Cipher: class {
|
||||
/// Encrypt given bytes at once
|
||||
///
|
||||
/// - parameter bytes: Plaintext data
|
||||
/// - returns: Encrypted data
|
||||
func encrypt(_ bytes: ArraySlice<UInt8>) throws -> Array<UInt8>
|
||||
func encrypt(_ bytes: Array<UInt8>) throws -> Array<UInt8>
|
||||
|
||||
/// Decrypt given bytes at once
|
||||
///
|
||||
/// - parameter bytes: Ciphertext data
|
||||
/// - returns: Plaintext data
|
||||
func decrypt(_ bytes: ArraySlice<UInt8>) throws -> Array<UInt8>
|
||||
func decrypt(_ bytes: Array<UInt8>) throws -> Array<UInt8>
|
||||
}
|
||||
|
||||
extension Cipher {
|
||||
public func encrypt(_ bytes: Array<UInt8>) throws -> Array<UInt8> {
|
||||
return try encrypt(bytes.slice)
|
||||
}
|
||||
|
||||
public func decrypt(_ bytes: Array<UInt8>) throws -> Array<UInt8> {
|
||||
return try decrypt(bytes.slice)
|
||||
}
|
||||
}
|
47
Pods/CryptoSwift/Sources/CryptoSwift/Collection+Extension.swift
generated
Normal file
@ -0,0 +1,47 @@
|
||||
//
|
||||
// Collection+Extension.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
extension Collection where Self.Element == UInt8, Self.Index == Int {
|
||||
|
||||
// Big endian order
|
||||
func toUInt32Array() -> Array<UInt32> {
|
||||
if isEmpty {
|
||||
return []
|
||||
}
|
||||
|
||||
var result = Array<UInt32>(reserveCapacity: 16)
|
||||
for idx in stride(from: startIndex, to: endIndex, by: 4) {
|
||||
let val = UInt32(bytes: self, fromIndex: idx).bigEndian
|
||||
result.append(val)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Big endian order
|
||||
func toUInt64Array() -> Array<UInt64> {
|
||||
if isEmpty {
|
||||
return []
|
||||
}
|
||||
|
||||
var result = Array<UInt64>(reserveCapacity: 32)
|
||||
for idx in stride(from: startIndex, to: endIndex, by: 8) {
|
||||
let val = UInt64(bytes: self, fromIndex: idx).bigEndian
|
||||
result.append(val)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
48
Pods/CryptoSwift/Sources/CryptoSwift/Cryptors.swift
generated
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// Cryptors.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
#if os(Linux) || os(Android) || os(FreeBSD)
|
||||
import Glibc
|
||||
#else
|
||||
import Darwin
|
||||
#endif
|
||||
|
||||
/// Worker cryptor/decryptor of `Updatable` types
|
||||
public protocol Cryptors: class {
|
||||
associatedtype EncryptorType: Updatable
|
||||
associatedtype DecryptorType: Updatable
|
||||
|
||||
/// Cryptor suitable for encryption
|
||||
func makeEncryptor() throws -> EncryptorType
|
||||
|
||||
/// Cryptor suitable for decryption
|
||||
func makeDecryptor() throws -> DecryptorType
|
||||
|
||||
/// Generate array of random bytes. Helper function.
|
||||
static func randomIV(_ blockSize: Int) -> Array<UInt8>
|
||||
}
|
||||
|
||||
extension Cryptors {
|
||||
|
||||
public static func randomIV(_ blockSize: Int) -> Array<UInt8> {
|
||||
var randomIV: Array<UInt8> = Array<UInt8>()
|
||||
randomIV.reserveCapacity(blockSize)
|
||||
for randomByte in RandomBytesSequence(size: blockSize) {
|
||||
randomIV.append(randomByte)
|
||||
}
|
||||
return randomIV
|
||||
}
|
||||
}
|
80
Pods/CryptoSwift/Sources/CryptoSwift/Digest.swift
generated
Normal file
@ -0,0 +1,80 @@
|
||||
//
|
||||
// Hash.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
@available(*, deprecated: 0.6.0, renamed: "Digest")
|
||||
public typealias Hash = Digest
|
||||
|
||||
/// Hash functions to calculate Digest.
|
||||
public struct Digest {
|
||||
|
||||
/// Calculate MD5 Digest
|
||||
/// - parameter bytes: input message
|
||||
/// - returns: Digest bytes
|
||||
public static func md5(_ bytes: Array<UInt8>) -> Array<UInt8> {
|
||||
return MD5().calculate(for: bytes)
|
||||
}
|
||||
|
||||
/// Calculate SHA1 Digest
|
||||
/// - parameter bytes: input message
|
||||
/// - returns: Digest bytes
|
||||
public static func sha1(_ bytes: Array<UInt8>) -> Array<UInt8> {
|
||||
return SHA1().calculate(for: bytes)
|
||||
}
|
||||
|
||||
/// Calculate SHA2-224 Digest
|
||||
/// - parameter bytes: input message
|
||||
/// - returns: Digest bytes
|
||||
public static func sha224(_ bytes: Array<UInt8>) -> Array<UInt8> {
|
||||
return sha2(bytes, variant: .sha224)
|
||||
}
|
||||
|
||||
/// Calculate SHA2-256 Digest
|
||||
/// - parameter bytes: input message
|
||||
/// - returns: Digest bytes
|
||||
public static func sha256(_ bytes: Array<UInt8>) -> Array<UInt8> {
|
||||
return sha2(bytes, variant: .sha256)
|
||||
}
|
||||
|
||||
/// Calculate SHA2-384 Digest
|
||||
/// - parameter bytes: input message
|
||||
/// - returns: Digest bytes
|
||||
public static func sha384(_ bytes: Array<UInt8>) -> Array<UInt8> {
|
||||
return sha2(bytes, variant: .sha384)
|
||||
}
|
||||
|
||||
/// Calculate SHA2-512 Digest
|
||||
/// - parameter bytes: input message
|
||||
/// - returns: Digest bytes
|
||||
public static func sha512(_ bytes: Array<UInt8>) -> Array<UInt8> {
|
||||
return sha2(bytes, variant: .sha512)
|
||||
}
|
||||
|
||||
/// Calculate SHA2 Digest
|
||||
/// - parameter bytes: input message
|
||||
/// - parameter variant: SHA-2 variant
|
||||
/// - returns: Digest bytes
|
||||
public static func sha2(_ bytes: Array<UInt8>, variant: SHA2.Variant) -> Array<UInt8> {
|
||||
return SHA2(variant: variant).calculate(for: bytes)
|
||||
}
|
||||
|
||||
/// Calculate SHA3 Digest
|
||||
/// - parameter bytes: input message
|
||||
/// - parameter variant: SHA-3 variant
|
||||
/// - returns: Digest bytes
|
||||
public static func sha3(_ bytes: Array<UInt8>, variant: SHA3.Variant) -> Array<UInt8> {
|
||||
return SHA3(variant: variant).calculate(for: bytes)
|
||||
}
|
||||
}
|
19
Pods/CryptoSwift/Sources/CryptoSwift/DigestType.swift
generated
Normal file
@ -0,0 +1,19 @@
|
||||
//
|
||||
// Digest.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
internal protocol DigestType {
|
||||
func calculate(for bytes: Array<UInt8>) -> Array<UInt8>
|
||||
}
|
25
Pods/CryptoSwift/Sources/CryptoSwift/Foundation/AES+Foundation.swift
generated
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// AES+Foundation.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension AES {
|
||||
|
||||
/// Initialize with CBC block mode.
|
||||
public convenience init(key: String, iv: String, padding: Padding = .pkcs7) throws {
|
||||
try self.init(key: key.bytes, blockMode: .CBC(iv: iv.bytes), padding: padding)
|
||||
}
|
||||
}
|
34
Pods/CryptoSwift/Sources/CryptoSwift/Foundation/Array+Foundation.swift
generated
Normal file
@ -0,0 +1,34 @@
|
||||
//
|
||||
// Array+Foundation.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension Array where Element == UInt8 {
|
||||
|
||||
public func toBase64() -> String? {
|
||||
return Data(bytes: self).base64EncodedString()
|
||||
}
|
||||
|
||||
public init(base64: String) {
|
||||
self.init()
|
||||
|
||||
guard let decodedData = Data(base64Encoded: base64) else {
|
||||
return
|
||||
}
|
||||
|
||||
append(contentsOf: decodedData.bytes)
|
||||
}
|
||||
}
|
25
Pods/CryptoSwift/Sources/CryptoSwift/Foundation/Blowfish+Foundation.swift
generated
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// Blowfish+Foundation.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Blowfish {
|
||||
|
||||
/// Initialize with CBC block mode.
|
||||
public convenience init(key: String, iv: String, padding: Padding = .pkcs7) throws {
|
||||
try self.init(key: key.bytes, blockMode: .CBC(iv: iv.bytes), padding: padding)
|
||||
}
|
||||
}
|
24
Pods/CryptoSwift/Sources/CryptoSwift/Foundation/ChaCha20+Foundation.swift
generated
Normal file
@ -0,0 +1,24 @@
|
||||
//
|
||||
// ChaCha20+Foundation.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension ChaCha20 {
|
||||
|
||||
public convenience init(key: String, iv: String) throws {
|
||||
try self.init(key: key.bytes, iv: iv.bytes)
|
||||
}
|
||||
}
|
94
Pods/CryptoSwift/Sources/CryptoSwift/Foundation/Data+Extension.swift
generated
Normal file
@ -0,0 +1,94 @@
|
||||
//
|
||||
// PGPDataExtension.swift
|
||||
// SwiftPGP
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Data {
|
||||
|
||||
/// Two octet checksum as defined in RFC-4880. Sum of all octets, mod 65536
|
||||
public func checksum() -> UInt16 {
|
||||
var s: UInt32 = 0
|
||||
var bytesArray = bytes
|
||||
for i in 0..<bytesArray.count {
|
||||
s = s + UInt32(bytesArray[i])
|
||||
}
|
||||
s = s % 65536
|
||||
return UInt16(s)
|
||||
}
|
||||
|
||||
public func md5() -> Data {
|
||||
return Data(bytes: Digest.md5(bytes))
|
||||
}
|
||||
|
||||
public func sha1() -> Data {
|
||||
return Data(bytes: Digest.sha1(bytes))
|
||||
}
|
||||
|
||||
public func sha224() -> Data {
|
||||
return Data(bytes: Digest.sha224(bytes))
|
||||
}
|
||||
|
||||
public func sha256() -> Data {
|
||||
return Data(bytes: Digest.sha256(bytes))
|
||||
}
|
||||
|
||||
public func sha384() -> Data {
|
||||
return Data(bytes: Digest.sha384(bytes))
|
||||
}
|
||||
|
||||
public func sha512() -> Data {
|
||||
return Data(bytes: Digest.sha512(bytes))
|
||||
}
|
||||
|
||||
public func sha3(_ variant: SHA3.Variant) -> Data {
|
||||
return Data(bytes: Digest.sha3(bytes, variant: variant))
|
||||
}
|
||||
|
||||
public func crc32(seed: UInt32? = nil, reflect: Bool = true) -> Data {
|
||||
return Data(bytes: Checksum.crc32(bytes, seed: seed, reflect: reflect).bytes())
|
||||
}
|
||||
|
||||
public func crc16(seed: UInt16? = nil) -> Data {
|
||||
return Data(bytes: Checksum.crc16(bytes, seed: seed).bytes())
|
||||
}
|
||||
|
||||
public func encrypt(cipher: Cipher) throws -> Data {
|
||||
return Data(bytes: try cipher.encrypt(bytes.slice))
|
||||
}
|
||||
|
||||
public func decrypt(cipher: Cipher) throws -> Data {
|
||||
return Data(bytes: try cipher.decrypt(bytes.slice))
|
||||
}
|
||||
|
||||
public func authenticate(with authenticator: Authenticator) throws -> Data {
|
||||
return Data(bytes: try authenticator.authenticate(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
extension Data {
|
||||
|
||||
public init(hex: String) {
|
||||
self.init(bytes: Array<UInt8>(hex: hex))
|
||||
}
|
||||
|
||||
public var bytes: Array<UInt8> {
|
||||
return Array(self)
|
||||
}
|
||||
|
||||
public func toHexString() -> String {
|
||||
return bytes.toHexString()
|
||||
}
|
||||
}
|
24
Pods/CryptoSwift/Sources/CryptoSwift/Foundation/HMAC+Foundation.swift
generated
Normal file
@ -0,0 +1,24 @@
|
||||
//
|
||||
// HMAC+Foundation.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension HMAC {
|
||||
|
||||
public convenience init(key: String, variant: HMAC.Variant = .md5) throws {
|
||||
self.init(key: key.bytes, variant: variant)
|
||||
}
|
||||
}
|
28
Pods/CryptoSwift/Sources/CryptoSwift/Foundation/Rabbit+Foundation.swift
generated
Normal file
@ -0,0 +1,28 @@
|
||||
//
|
||||
// Rabbit+Foundation.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Rabbit {
|
||||
|
||||
public convenience init(key: String) throws {
|
||||
try self.init(key: key.bytes)
|
||||
}
|
||||
|
||||
public convenience init(key: String, iv: String) throws {
|
||||
try self.init(key: key.bytes, iv: iv.bytes)
|
||||
}
|
||||
}
|
43
Pods/CryptoSwift/Sources/CryptoSwift/Foundation/String+FoundationExtension.swift
generated
Normal file
@ -0,0 +1,43 @@
|
||||
//
|
||||
// String+Extension.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension String {
|
||||
|
||||
/// Return Base64 back to String
|
||||
public func decryptBase64ToString(cipher: Cipher) throws -> String {
|
||||
guard let decodedData = Data(base64Encoded: self, options: []) else {
|
||||
throw CipherError.decrypt
|
||||
}
|
||||
|
||||
let decrypted = try decodedData.decrypt(cipher: cipher)
|
||||
|
||||
if let decryptedString = String(data: decrypted, encoding: String.Encoding.utf8) {
|
||||
return decryptedString
|
||||
}
|
||||
|
||||
throw CipherError.decrypt
|
||||
}
|
||||
|
||||
public func decryptBase64(cipher: Cipher) throws -> Array<UInt8> {
|
||||
guard let decodedData = Data(base64Encoded: self, options: []) else {
|
||||
throw CipherError.decrypt
|
||||
}
|
||||
|
||||
return try decodedData.decrypt(cipher: cipher).bytes
|
||||
}
|
||||
}
|
28
Pods/CryptoSwift/Sources/CryptoSwift/Foundation/Utils+Foundation.swift
generated
Normal file
@ -0,0 +1,28 @@
|
||||
//
|
||||
// Utils+Foundation.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
func perf(_ text: String, closure: () -> Void) {
|
||||
let measurementStart = Date()
|
||||
|
||||
closure()
|
||||
|
||||
let measurementStop = Date()
|
||||
let executionTime = measurementStop.timeIntervalSince(measurementStart)
|
||||
|
||||
print("\(text) \(executionTime)")
|
||||
}
|
56
Pods/CryptoSwift/Sources/CryptoSwift/Generics.swift
generated
Normal file
@ -0,0 +1,56 @@
|
||||
//
|
||||
// Generics.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
/** build bit pattern from array of bits */
|
||||
@_specialize(exported: true, where T == UInt8)
|
||||
func integerFrom<T: FixedWidthInteger>(_ bits: Array<Bit>) -> T {
|
||||
var bitPattern: T = 0
|
||||
for idx in bits.indices {
|
||||
if bits[idx] == Bit.one {
|
||||
let bit = T(UInt64(1) << UInt64(idx))
|
||||
bitPattern = bitPattern | bit
|
||||
}
|
||||
}
|
||||
return bitPattern
|
||||
}
|
||||
|
||||
/// Array of bytes. Caution: don't use directly because generic is slow.
|
||||
///
|
||||
/// - parameter value: integer value
|
||||
/// - parameter length: length of output array. By default size of value type
|
||||
///
|
||||
/// - returns: Array of bytes
|
||||
@_specialize(exported: true, where T == Int)
|
||||
@_specialize(exported: true, where T == UInt)
|
||||
@_specialize(exported: true, where T == UInt8)
|
||||
@_specialize(exported: true, where T == UInt16)
|
||||
@_specialize(exported: true, where T == UInt32)
|
||||
@_specialize(exported: true, where T == UInt64)
|
||||
func arrayOfBytes<T: FixedWidthInteger>(value: T, length totalBytes: Int = MemoryLayout<T>.size) -> Array<UInt8> {
|
||||
let valuePointer = UnsafeMutablePointer<T>.allocate(capacity: 1)
|
||||
valuePointer.pointee = value
|
||||
|
||||
let bytesPointer = UnsafeMutablePointer<UInt8>(OpaquePointer(valuePointer))
|
||||
var bytes = Array<UInt8>(repeating: 0, count: totalBytes)
|
||||
for j in 0..<min(MemoryLayout<T>.size, totalBytes) {
|
||||
bytes[totalBytes - 1 - j] = (bytesPointer + j).pointee
|
||||
}
|
||||
|
||||
valuePointer.deinitialize()
|
||||
valuePointer.deallocate(capacity: 1)
|
||||
|
||||
return bytes
|
||||
}
|
87
Pods/CryptoSwift/Sources/CryptoSwift/HKDF.swift
generated
Normal file
@ -0,0 +1,87 @@
|
||||
//
|
||||
// HKDF.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
// https://www.ietf.org/rfc/rfc5869.txt
|
||||
//
|
||||
|
||||
#if os(Linux) || os(Android) || os(FreeBSD)
|
||||
import Glibc
|
||||
#else
|
||||
import Darwin
|
||||
#endif
|
||||
|
||||
/// A key derivation function.
|
||||
///
|
||||
/// HKDF - HMAC-based Extract-and-Expand Key Derivation Function.
|
||||
public struct HKDF {
|
||||
|
||||
public enum Error: Swift.Error {
|
||||
case invalidInput
|
||||
case derivedKeyTooLong
|
||||
}
|
||||
|
||||
private let numBlocks: Int // l
|
||||
private let dkLen: Int
|
||||
private let info: Array<UInt8>
|
||||
fileprivate let prk: Array<UInt8>
|
||||
fileprivate let variant: HMAC.Variant
|
||||
|
||||
/// - parameters:
|
||||
/// - variant: hash variant
|
||||
/// - salt: optional salt (if not provided, it is set to a sequence of variant.digestLength zeros)
|
||||
/// - info: optional context and application specific information
|
||||
/// - keyLength: intended length of derived key
|
||||
public init(password: Array<UInt8>, salt: Array<UInt8>? = nil, info: Array<UInt8>? = nil, keyLength: Int? = nil /* dkLen */, variant: HMAC.Variant = .sha256) throws {
|
||||
guard !password.isEmpty else {
|
||||
throw Error.invalidInput
|
||||
}
|
||||
|
||||
let dkLen = keyLength ?? variant.digestLength
|
||||
let keyLengthFinal = Double(dkLen)
|
||||
let hLen = Double(variant.digestLength)
|
||||
let numBlocks = Int(ceil(keyLengthFinal / hLen)) // l = ceil(keyLength / hLen)
|
||||
guard numBlocks <= 255 else {
|
||||
throw Error.derivedKeyTooLong
|
||||
}
|
||||
|
||||
/// HKDF-Extract(salt, password) -> PRK
|
||||
/// - PRK - a pseudo-random key; it is used by calculate()
|
||||
self.prk = try HMAC(key: salt ?? [], variant: variant).authenticate(password)
|
||||
self.info = info ?? []
|
||||
self.variant = variant
|
||||
self.dkLen = dkLen
|
||||
self.numBlocks = numBlocks
|
||||
}
|
||||
|
||||
public func calculate() throws -> Array<UInt8> {
|
||||
let hmac = HMAC(key: self.prk, variant: self.variant)
|
||||
var ret = Array<UInt8>()
|
||||
ret.reserveCapacity(self.numBlocks * self.variant.digestLength)
|
||||
var value = Array<UInt8>()
|
||||
for i in 1...self.numBlocks {
|
||||
value.append(contentsOf: self.info)
|
||||
value.append(UInt8(i))
|
||||
|
||||
let bytes = try hmac.authenticate(value)
|
||||
ret.append(contentsOf: bytes)
|
||||
|
||||
/// update value to use it as input for next iteration
|
||||
value = bytes
|
||||
}
|
||||
return Array(ret.prefix(dkLen))
|
||||
}
|
||||
}
|
||||
|
107
Pods/CryptoSwift/Sources/CryptoSwift/HMAC.swift
generated
Normal file
@ -0,0 +1,107 @@
|
||||
//
|
||||
// HMAC.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
public final class HMAC: Authenticator {
|
||||
|
||||
public enum Error: Swift.Error {
|
||||
case authenticateError
|
||||
case invalidInput
|
||||
}
|
||||
|
||||
public enum Variant {
|
||||
case sha1, sha256, sha384, sha512, md5
|
||||
|
||||
var digestLength: Int {
|
||||
switch self {
|
||||
case .sha1:
|
||||
return SHA1.digestLength
|
||||
case .sha256:
|
||||
return SHA2.Variant.sha256.digestLength
|
||||
case .sha384:
|
||||
return SHA2.Variant.sha384.digestLength
|
||||
case .sha512:
|
||||
return SHA2.Variant.sha512.digestLength
|
||||
case .md5:
|
||||
return MD5.digestLength
|
||||
}
|
||||
}
|
||||
|
||||
func calculateHash(_ bytes: Array<UInt8>) -> Array<UInt8>? {
|
||||
switch self {
|
||||
case .sha1:
|
||||
return Digest.sha1(bytes)
|
||||
case .sha256:
|
||||
return Digest.sha256(bytes)
|
||||
case .sha384:
|
||||
return Digest.sha384(bytes)
|
||||
case .sha512:
|
||||
return Digest.sha512(bytes)
|
||||
case .md5:
|
||||
return Digest.md5(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
func blockSize() -> Int {
|
||||
switch self {
|
||||
case .md5:
|
||||
return MD5.blockSize
|
||||
case .sha1, .sha256:
|
||||
return 64
|
||||
case .sha384, .sha512:
|
||||
return 128
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var key: Array<UInt8>
|
||||
let variant: Variant
|
||||
|
||||
public init(key: Array<UInt8>, variant: HMAC.Variant = .md5) {
|
||||
self.variant = variant
|
||||
self.key = key
|
||||
|
||||
if key.count > variant.blockSize() {
|
||||
if let hash = variant.calculateHash(key) {
|
||||
self.key = hash
|
||||
}
|
||||
}
|
||||
|
||||
if key.count < variant.blockSize() {
|
||||
self.key = ZeroPadding().add(to: key, blockSize: variant.blockSize())
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Authenticator
|
||||
|
||||
public func authenticate(_ bytes: Array<UInt8>) throws -> Array<UInt8> {
|
||||
var opad = Array<UInt8>(repeating: 0x5c, count: variant.blockSize())
|
||||
for idx in key.indices {
|
||||
opad[idx] = key[idx] ^ opad[idx]
|
||||
}
|
||||
var ipad = Array<UInt8>(repeating: 0x36, count: variant.blockSize())
|
||||
for idx in key.indices {
|
||||
ipad[idx] = key[idx] ^ ipad[idx]
|
||||
}
|
||||
|
||||
guard let ipadAndMessageHash = variant.calculateHash(ipad + bytes),
|
||||
let result = variant.calculateHash(opad + ipadAndMessageHash) else {
|
||||
throw Error.authenticateError
|
||||
}
|
||||
|
||||
// return Array(result[0..<10]) // 80 bits
|
||||
return result
|
||||
}
|
||||
}
|
39
Pods/CryptoSwift/Sources/CryptoSwift/Int+Extension.swift
generated
Normal file
@ -0,0 +1,39 @@
|
||||
//
|
||||
// IntExtension.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Created by Marcin Krzyzanowski on 12/08/14.
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
#if os(Linux) || os(Android) || os(FreeBSD)
|
||||
import Glibc
|
||||
#else
|
||||
import Darwin
|
||||
#endif
|
||||
|
||||
/* array of bits */
|
||||
extension Int {
|
||||
init(bits: [Bit]) {
|
||||
self.init(bitPattern: integerFrom(bits) as UInt)
|
||||
}
|
||||
}
|
||||
|
||||
extension FixedWidthInteger {
|
||||
@_transparent
|
||||
func bytes(totalBytes: Int = MemoryLayout<Self>.size) -> Array<UInt8> {
|
||||
return arrayOfBytes(value: self, length: totalBytes)
|
||||
// TODO: adjust bytes order
|
||||
// var value = self
|
||||
// return withUnsafeBytes(of: &value, Array.init).reversed()
|
||||
}
|
||||
}
|
167
Pods/CryptoSwift/Sources/CryptoSwift/MD5.swift
generated
Normal file
@ -0,0 +1,167 @@
|
||||
//
|
||||
// MD5.swift
|
||||
// CryptoSwift
|
||||
//
|
||||
// Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
//
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
|
||||
// - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
// - This notice may not be removed or altered from any source or binary distribution.
|
||||
//
|
||||
|
||||
public final class MD5: DigestType {
|
||||
static let blockSize: Int = 64
|
||||
static let digestLength: Int = 16 // 128 / 8
|
||||
fileprivate static let hashInitialValue: Array<UInt32> = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476]
|
||||
|
||||
fileprivate var accumulated = Array<UInt8>()
|
||||
fileprivate var processedBytesTotalCount: Int = 0
|
||||
fileprivate var accumulatedHash: Array<UInt32> = MD5.hashInitialValue
|
||||
|
||||
/** specifies the per-round shift amounts */
|
||||
private let s: Array<UInt32> = [
|
||||
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
|
||||
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
|
||||
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
|
||||
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,
|
||||
]
|
||||
|
||||
/** binary integer part of the sines of integers (Radians) */
|
||||
private let k: Array<UInt32> = [
|
||||
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
|
||||
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
||||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
|
||||
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
|
||||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
|
||||
0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
|
||||
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
|
||||
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
|
||||
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
|
||||
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
|
||||
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
|
||||
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
|
||||
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
|
||||
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
|
||||
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
|
||||
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
|
||||
]
|
||||
|
||||
public init() {
|
||||
}
|
||||
|
||||
public func calculate(for bytes: Array<UInt8>) -> Array<UInt8> {
|
||||
do {
|
||||
return try update(withBytes: bytes.slice, isLast: true)
|
||||
} catch {
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
|
||||
// mutating currentHash in place is way faster than returning new result
|
||||
fileprivate func process(block chunk: ArraySlice<UInt8>, currentHash: inout Array<UInt32>) {
|
||||
assert(chunk.count == 16 * 4)
|
||||
|
||||
// Initialize hash value for this chunk:
|
||||
var A: UInt32 = currentHash[0]
|
||||
var B: UInt32 = currentHash[1]
|
||||
var C: UInt32 = currentHash[2]
|
||||
var D: UInt32 = currentHash[3]
|
||||
|
||||
var dTemp: UInt32 = 0
|
||||
|
||||
// Main loop
|
||||
for j in 0..<k.count {
|
||||
var g = 0
|
||||
var F: UInt32 = 0
|
||||
|
||||
switch j {
|
||||
case 0...15:
|
||||
F = (B & C) | ((~B) & D)
|
||||
g = j
|
||||
break
|
||||
case 16...31:
|
||||
F = (D & B) | (~D & C)
|
||||
g = (5 * j + 1) % 16
|
||||
break
|
||||
case 32...47:
|
||||
F = B ^ C ^ D
|
||||
g = (3 * j + 5) % 16
|
||||
break
|
||||
case 48...63:
|
||||
F = C ^ (B | (~D))
|
||||
g = (7 * j) % 16
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
dTemp = D
|
||||
D = C
|
||||
C = B
|
||||
|
||||
// break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15 and get M[g] value
|
||||
let gAdvanced = g << 2
|
||||
|
||||
var Mg = UInt32(chunk[chunk.startIndex &+ gAdvanced])
|
||||
Mg |= UInt32(chunk[chunk.startIndex &+ gAdvanced &+ 1]) << 8
|
||||
Mg |= UInt32(chunk[chunk.startIndex &+ gAdvanced &+ 2]) << 16
|
||||
Mg |= UInt32(chunk[chunk.startIndex &+ gAdvanced &+ 3]) << 24
|
||||
|
||||
B = B &+ rotateLeft(A &+ F &+ k[j] &+ Mg, by: s[j])
|
||||
A = dTemp
|
||||
}
|
||||
|
||||
currentHash[0] = currentHash[0] &+ A
|
||||
currentHash[1] = currentHash[1] &+ B
|
||||
currentHash[2] = currentHash[2] &+ C
|
||||
currentHash[3] = currentHash[3] &+ D
|
||||
}
|
||||
}
|
||||
|
||||
extension MD5: Updatable {
|
||||
|
||||
public func update(withBytes bytes: ArraySlice<UInt8>, isLast: Bool = false) throws -> Array<UInt8> {
|
||||
accumulated += bytes
|
||||
|
||||
if isLast {
|
||||
let lengthInBits = (processedBytesTotalCount + accumulated.count) * 8
|
||||
let lengthBytes = lengthInBits.bytes(totalBytes: 64 / 8) // A 64-bit representation of b
|
||||
|
||||
// Step 1. Append padding
|
||||
bitPadding(to: &accumulated, blockSize: MD5.blockSize, allowance: 64 / 8)
|
||||
|
||||
// Step 2. Append Length a 64-bit representation of lengthInBits
|
||||
accumulated += lengthBytes.reversed()
|
||||
}
|
||||
|
||||
var processedBytes = 0
|
||||
for chunk in accumulated.batched(by: MD5.blockSize) {
|
||||
if isLast || (accumulated.count - processedBytes) >= MD5.blockSize {
|
||||
process(block: chunk, currentHash: &accumulatedHash)
|
||||
processedBytes += chunk.count
|
||||
}
|
||||
}
|
||||
accumulated.removeFirst(processedBytes)
|
||||
processedBytesTotalCount += processedBytes
|
||||
|
||||
// output current hash
|
||||
var result = Array<UInt8>()
|
||||
result.reserveCapacity(MD5.digestLength)
|
||||
|
||||
for hElement in accumulatedHash {
|
||||
let hLE = hElement.littleEndian
|
||||
result += Array<UInt8>(arrayLiteral: UInt8(hLE & 0xff), UInt8((hLE >> 8) & 0xff), UInt8((hLE >> 16) & 0xff), UInt8((hLE >> 24) & 0xff))
|
||||
}
|
||||
|
||||
// reset hash value for instance
|
||||
if isLast {
|
||||
accumulatedHash = MD5.hashInitialValue
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|