-
-
Notifications
You must be signed in to change notification settings - Fork 105
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
43 changed files
with
2,207 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
// Originally based on CryptoSwift by Marcin Krzyżanowski <marcin.krzyzanowski@gmail.com> | ||
// Copyright (C) 2014 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. | ||
|
||
import Foundation | ||
|
||
public protocol ArrayProtocol: RangeReplaceableCollection, ExpressibleByArrayLiteral { | ||
func arrayValue() -> [Generator.Element] | ||
} | ||
|
||
extension Array: ArrayProtocol { | ||
public func arrayValue() -> [Iterator.Element] { | ||
return self | ||
} | ||
} | ||
|
||
public extension ArrayProtocol where Iterator.Element == UInt8 { | ||
public var hexString: String { | ||
#if os(Linux) | ||
return self.lazy.reduce("") { $0 + (NSString(format:"%02x", $1).description) } | ||
#else | ||
let s = self.lazy.reduce("") { $0 + String(format:"%02x", $1) } | ||
|
||
return s | ||
#endif | ||
} | ||
|
||
public var checksum: UInt16? { | ||
guard let bytesArray = self as? [UInt8] else { | ||
return nil | ||
} | ||
|
||
var s:UInt32 = 0 | ||
for i in 0..<bytesArray.count { | ||
s = s + UInt32(bytesArray[i]) | ||
} | ||
s = s % 65536 | ||
return UInt16(s) | ||
} | ||
|
||
public var base64: String { | ||
let bytesArray = self as? [UInt8] ?? [] | ||
|
||
#if os(Linux) | ||
return NSData(bytes: bytesArray).base64EncodedString([]) | ||
#else | ||
return NSData(bytes: bytesArray).base64EncodedString(options: []) | ||
#endif | ||
} | ||
|
||
public init(base64: String) { | ||
self.init() | ||
|
||
guard let decodedData = NSData(base64: base64) else { | ||
return | ||
} | ||
|
||
self.append(contentsOf: decodedData.byteArray) | ||
} | ||
|
||
public init(hexString: String) { | ||
var data = [UInt8]() | ||
|
||
var gen = hexString.characters.makeIterator() | ||
while let c1 = gen.next(), let c2 = gen.next() { | ||
let s = String([c1, c2]) | ||
|
||
guard let d = UInt8(s, radix: 16) else { | ||
break | ||
} | ||
|
||
data.append(d) | ||
} | ||
|
||
self.init(data) | ||
} | ||
} | ||
|
||
extension Array { | ||
|
||
/** split in chunks with given chunk size */ | ||
public func chunks(chunkSize: Int) -> [Array<Element>] { | ||
var words = [[Element]]() | ||
words.reserveCapacity(self.count / chunkSize) | ||
for idx in stride(from: chunkSize, through: self.count, by: chunkSize) { | ||
let word = Array(self[idx - chunkSize..<idx]) // this is slow for large table | ||
words.append(word) | ||
} | ||
let reminder = Array(self.suffix(self.count % chunkSize)) | ||
if (reminder.count > 0) { | ||
words.append(reminder) | ||
} | ||
return words | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
// Base64.swift | ||
// | ||
// The MIT License (MIT) | ||
// | ||
// Copyright (c) 2015 Zewo | ||
// | ||
// Permission is hereby granted, free of charge, to any person obtaining a copy | ||
// of this software and associated documentation files (the "Software"), to deal | ||
// in the Software without restriction, including without limitation the rights | ||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
// copies of the Software, and to permit persons to whom the Software is | ||
// furnished to do so, subject to the following conditions: | ||
// | ||
// The above copyright notice and this permission notice shall be included in all | ||
// copies or substantial portions of the Software. | ||
// | ||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
// SOFTWARE. | ||
|
||
public struct Base64 { | ||
/** | ||
Decodes the base64 encoded string into an array of UInt8 representing | ||
bytes. Throws an Base64DecodingError.invalidCharacter if the input string | ||
is not encoded in valid Base64. | ||
|
||
- parameters: | ||
- string: the string to decode | ||
- returns: an array of bytes. | ||
*/ | ||
public static func decode(_ string: String) throws -> [UInt8] { | ||
let ascii: [UInt8] = [ | ||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 62, 64, 63, | ||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, | ||
64, 00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, | ||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 63, | ||
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, | ||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, | ||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||
] | ||
|
||
var decoded = [UInt8]() | ||
var unreadBytes = 0 | ||
|
||
for character in string.utf8 { | ||
// If we don't get a valid Base64 Character (excluding =): | ||
if ascii[Int(character)] > 63 { | ||
|
||
// If it's '=', which is padding, we are done with the string! | ||
if character == 61 { | ||
break | ||
} | ||
// Otherwise this is not a valid Base64 encoded string | ||
else { | ||
throw Base64DecodingError.invalidCharacter | ||
} | ||
} | ||
|
||
unreadBytes += 1 | ||
} | ||
|
||
func byte(_ index: Int) -> Int { | ||
return Int(Array(string.utf8)[index]) | ||
} | ||
|
||
var index = 0 | ||
|
||
while unreadBytes > 4 { | ||
decoded.append(ascii[byte(index + 0)] << 2 | ascii[byte(index + 1)] >> 4) | ||
decoded.append(ascii[byte(index + 1)] << 4 | ascii[byte(index + 2)] >> 2) | ||
decoded.append(ascii[byte(index + 2)] << 6 | ascii[byte(index + 3)]) | ||
index += 4 | ||
unreadBytes -= 4 | ||
} | ||
|
||
if unreadBytes > 1 { | ||
decoded.append(ascii[byte(index + 0)] << 2 | ascii[byte(index + 1)] >> 4) | ||
} | ||
|
||
if unreadBytes > 2 { | ||
decoded.append(ascii[byte(index + 1)] << 4 | ascii[byte(index + 2)] >> 2) | ||
} | ||
|
||
if unreadBytes > 3 { | ||
decoded.append(ascii[byte(index + 2)] << 6 | ascii[byte(index + 3)]) | ||
} | ||
|
||
return decoded | ||
} | ||
|
||
public static func encode(_ data: [UInt8], specialChars: String = "+/", paddingChar: Character? = "=") -> String { | ||
let base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + specialChars | ||
var encoded: String = "" | ||
|
||
func appendCharacterFromBase(_ character: Int) { | ||
encoded.append(base64[base64.index(base64.startIndex, offsetBy: character)]) | ||
} | ||
|
||
func byte(_ index: Int) -> Int { | ||
return Int(data[index]) | ||
} | ||
|
||
let decodedBytes = data.map { Int($0) } | ||
|
||
var i = 0 | ||
|
||
while i < decodedBytes.count - 2 { | ||
appendCharacterFromBase(( byte(i) >> 2) & 0x3F) | ||
appendCharacterFromBase(((byte(i) & 0x3) << 4) | ((byte(i + 1) & 0xF0) >> 4)) | ||
appendCharacterFromBase(((byte(i + 1) & 0xF) << 2) | ((byte(i + 2) & 0xC0) >> 6)) | ||
appendCharacterFromBase( byte(i + 2) & 0x3F) | ||
i += 3 | ||
} | ||
|
||
if i < decodedBytes.count { | ||
appendCharacterFromBase((byte(i) >> 2) & 0x3F) | ||
|
||
if i == decodedBytes.count - 1 { | ||
appendCharacterFromBase(((byte(i) & 0x3) << 4)) | ||
if let paddingChar = paddingChar { | ||
encoded.append(paddingChar) | ||
} | ||
} else { | ||
appendCharacterFromBase(((byte(i) & 0x3) << 4) | ((byte(i + 1) & 0xF0) >> 4)) | ||
appendCharacterFromBase(((byte(i + 1) & 0xF) << 2)) | ||
} | ||
|
||
if let paddingChar = paddingChar { | ||
encoded.append(paddingChar) | ||
} | ||
} | ||
|
||
return encoded | ||
} | ||
|
||
public static func urlSafeEncode(_ data: [UInt8]) -> String { | ||
return Base64.encode(data, specialChars: "-_", paddingChar: nil) | ||
} | ||
} | ||
|
||
enum Base64DecodingError: Error { | ||
case invalidCharacter | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// Originally based on CryptoSwift by Marcin Krzyżanowski <marcin.krzyzanowski@gmail.com> | ||
// Copyright (C) 2014 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. | ||
|
||
public typealias CipherBlockOperation = (_ block: [UInt8]) -> [UInt8]? | ||
|
||
public protocol BlockMode { | ||
static var options: BlockModeOptions { get } | ||
static var blockType: InputBlockType { get } | ||
|
||
static func makeDecryptionIterator(iv: [UInt8], cipherOperation: @escaping CipherBlockOperation, inputGenerator: AnyIterator<[UInt8]>) -> AnyIterator<[UInt8]> | ||
|
||
static func makeEncryptionIterator(iv: [UInt8], cipherOperation: @escaping CipherBlockOperation, inputGenerator: AnyIterator<[UInt8]>) -> AnyIterator<[UInt8]> | ||
} | ||
|
||
public enum InputBlockType { | ||
case encrypt | ||
case decrypt | ||
} | ||
|
||
public struct BlockModeOptions: OptionSet { | ||
public let rawValue: Int | ||
|
||
public init(rawValue: Int) { | ||
self.rawValue = rawValue | ||
} | ||
|
||
public static let none = BlockModeOptions(rawValue: 0) | ||
public static let initializationVectorRequired = BlockModeOptions(rawValue: 1) | ||
public static let paddingRequired = BlockModeOptions(rawValue: 2) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// Originally based on CryptoSwift by Marcin Krzyżanowski <marcin.krzyzanowski@gmail.com> | ||
// Copyright (C) 2014 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. | ||
|
||
import Foundation | ||
|
||
public struct BytesSequence: Sequence { | ||
let chunkSize: Int | ||
let data: [UInt8] | ||
|
||
public init(chunkSize: Int, data: [UInt8]) { | ||
self.chunkSize = chunkSize | ||
self.data = data | ||
} | ||
|
||
public func makeIterator() -> AnyIterator<ArraySlice<UInt8>> { | ||
var offset:Int = 0 | ||
|
||
return AnyIterator { | ||
let end = Swift.min(self.chunkSize, self.data.count - offset) | ||
let result = self.data[offset..<offset + end] | ||
offset += result.count | ||
return result.count > 0 ? result : nil | ||
} | ||
} | ||
} |
Oops, something went wrong.