diff --git a/CryptoSwift.xcodeproj/project.pbxproj b/CryptoSwift.xcodeproj/project.pbxproj index e4d4d6d9..d1221dba 100644 --- a/CryptoSwift.xcodeproj/project.pbxproj +++ b/CryptoSwift.xcodeproj/project.pbxproj @@ -125,6 +125,8 @@ E3FD2D531D6B81CE00A9F35F /* Error+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3FD2D511D6B813C00A9F35F /* Error+Extension.swift */; }; E6200E141FB9A7AE00258382 /* HKDF.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6200E131FB9A7AE00258382 /* HKDF.swift */; }; E6200E171FB9B68C00258382 /* HKDFTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6200E151FB9B67C00258382 /* HKDFTests.swift */; }; + EBB32ABF22737C16003A065D /* Salsa20Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB51933F2268D600009CE32B /* Salsa20Tests.swift */; }; + EBCE52E7226515AD00D8DAE7 /* Salsa20.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBCE52E6226515AD00D8DAE7 /* Salsa20.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -373,6 +375,8 @@ E3FD2D511D6B813C00A9F35F /* Error+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Error+Extension.swift"; sourceTree = ""; }; E6200E131FB9A7AE00258382 /* HKDF.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HKDF.swift; sourceTree = ""; }; E6200E151FB9B67C00258382 /* HKDFTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HKDFTests.swift; sourceTree = ""; }; + EB51933F2268D600009CE32B /* Salsa20Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Salsa20Tests.swift; sourceTree = ""; }; + EBCE52E6226515AD00D8DAE7 /* Salsa20.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Salsa20.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -500,6 +504,7 @@ 75C2E76C1D55F097003D2BCA /* Access.swift */, 756BFDCA1A82B87300B9D9A4 /* Bridging.h */, 754BE46519693E190098E6F3 /* Supporting Files */, + EB51933F2268D600009CE32B /* Salsa20Tests.swift */, ); name = Tests; path = Tests/Tests; @@ -615,6 +620,7 @@ 75B3ED78210FA016005D4ADA /* BlockEncryptor.swift */, 753674062175D012003E32A6 /* StreamDecryptor.swift */, 756A64C52111083B00BE8805 /* StreamEncryptor.swift */, + EBCE52E6226515AD00D8DAE7 /* Salsa20.swift */, ); path = CryptoSwift; sourceTree = ""; @@ -925,6 +931,7 @@ 75EC52841EE8B8170048EB3B /* CipherModeWorker.swift in Sources */, 75EC52A41EE8B8290048EB3B /* Operators.swift in Sources */, 75EC529A1EE8B8200048EB3B /* HMAC+Foundation.swift in Sources */, + EBCE52E7226515AD00D8DAE7 /* Salsa20.swift in Sources */, 75EC52B21EE8B83D0048EB3B /* String+Extension.swift in Sources */, 750509991F6BEF2A00394A1B /* PKCS7.swift in Sources */, 75EC52B51EE8B83D0048EB3B /* UInt64+Extension.swift in Sources */, @@ -978,6 +985,7 @@ 758A94291A65C67400E46135 /* HMACTests.swift in Sources */, 75100F8F19B0BC890005C5F5 /* Poly1305Tests.swift in Sources */, E6200E171FB9B68C00258382 /* HKDFTests.swift in Sources */, + EBB32ABF22737C16003A065D /* Salsa20Tests.swift in Sources */, 753B33011DAB84D600D06422 /* RandomBytesSequenceTests.swift in Sources */, 754BE46819693E190098E6F3 /* DigestTests.swift in Sources */, E3FD2D531D6B81CE00A9F35F /* Error+Extension.swift in Sources */, diff --git a/CryptoSwift.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/CryptoSwift.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index b2541484..5cb42a1a 100644 --- a/CryptoSwift.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/CryptoSwift.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -5,6 +5,19 @@ + + + + + + + + + + + + + + + + + + +// Copyright (C) 2019 Roger Miret Giné // 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. @@ -16,39 +17,28 @@ // https://tools.ietf.org/html/rfc7539 // -public final class ChaCha20: BlockCipher { - public enum Error: Swift.Error { - case invalidKeyOrInitializationVector - case notSupported - } - - public static let blockSize = 64 // 512 / 8 - public let keySize: Int +public final class ChaCha20: Salsa20 { - fileprivate let key: Key - fileprivate var counter: Array + override internal func qr(_ a: inout UInt32, _ b: inout UInt32, _ c: inout UInt32, _ d: inout UInt32) { + a = a &+ b + d ^= a + d = rotl(d, 16) - public init(key: Array, iv nonce: Array) throws { - precondition(nonce.count == 12 || nonce.count == 8) - - if key.count != 32 { - throw Error.invalidKeyOrInitializationVector - } + c = c &+ d + b ^= c + b = rotl(b, 12) - self.key = Key(bytes: key) - keySize = self.key.count + a = a &+ b + d ^= a + d = rotl(d, 8) - 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) + c = c &+ d + b ^= c + b = rotl(b, 7) } /// https://tools.ietf.org/html/rfc7539#section-2.3. - fileprivate func core(block: inout Array, counter: Array, key: Array) { + override internal func core(block: inout Array, counter: Array, key: Array) { precondition(block.count == ChaCha20.blockSize) precondition(counter.count == 16) precondition(key.count == 32) @@ -74,102 +64,16 @@ public final class ChaCha20: BlockCipher { 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) + // Odd round + qr(&x0, &x4, &x8, &x12) + qr(&x1, &x5, &x9, &x13) + qr(&x2, &x6, &x10, &x14) + qr(&x3, &x7, &x11, &x15) + // Even round + qr(&x0, &x5, &x10, &x15) + qr(&x1, &x6, &x11, &x12) + qr(&x2, &x7, &x8, &x13) + qr(&x3, &x4, &x9, &x14) } x0 = x0 &+ j0 @@ -206,142 +110,4 @@ public final class ChaCha20: BlockCipher { block.replaceSubrange(56..<60, with: x14.bigEndian.bytes()) block.replaceSubrange(60..<64, with: x15.bigEndian.bytes()) } - - // XORKeyStream - func process(bytes: ArraySlice, counter: inout Array, key: Array) -> Array { - precondition(counter.count == 16) - precondition(key.count == 32) - - var block = Array(repeating: 0, count: ChaCha20.blockSize) - var bytesSlice = bytes - var out = Array(reserveCapacity: bytesSlice.count) - - while bytesSlice.count >= ChaCha20.blockSize { - core(block: &block, counter: counter, key: key) - for (i, x) in block.enumerated() { - out.append(bytesSlice[bytesSlice.startIndex + i] ^ x) - } - var u: UInt32 = 1 - for i in 0..<4 { - u += UInt32(counter[i]) - counter[i] = UInt8(u & 0xff) - u >>= 8 - } - bytesSlice = bytesSlice[bytesSlice.startIndex + ChaCha20.blockSize.. 0 { - core(block: &block, counter: counter, key: key) - for (i, v) in bytesSlice.enumerated() { - out.append(v ^ block[i]) - } - } - return out - } -} - -// MARK: Cipher - -extension ChaCha20: Cipher { - public func encrypt(_ bytes: ArraySlice) throws -> Array { - return process(bytes: bytes, counter: &counter, key: Array(key)) - } - - public func decrypt(_ bytes: ArraySlice) throws -> Array { - return try encrypt(bytes) - } -} - -// MARK: Encryptor - -extension ChaCha20 { - public struct ChaChaEncryptor: Cryptor, Updatable { - private var accumulated = Array() - private let chacha: ChaCha20 - - init(chacha: ChaCha20) { - self.chacha = chacha - } - - public mutating func update(withBytes bytes: ArraySlice, isLast: Bool = false) throws -> Array { - accumulated += bytes - - var encrypted = Array() - 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 - } - - public func seek(to: Int) throws { - throw Error.notSupported - } - } -} - -// MARK: Decryptor - -extension ChaCha20 { - public struct ChaChaDecryptor: Cryptor, Updatable { - private var accumulated = Array() - - 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, isLast: Bool = true) throws -> Array { - // prepend "offset" number of bytes at the beginning - if offset > 0 { - accumulated += Array(repeating: 0, count: offset) + bytes - offsetToRemove = offset - offset = 0 - } else { - accumulated += bytes - } - - var plaintext = Array() - 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 - } - - public func seek(to: Int) throws { - throw Error.notSupported - } - } -} - -// MARK: Cryptors - -extension ChaCha20: Cryptors { - //TODO: Use BlockEncryptor/BlockDecryptor - - public func makeEncryptor() -> Cryptor & Updatable { - return ChaCha20.ChaChaEncryptor(chacha: self) - } - - public func makeDecryptor() -> Cryptor & Updatable { - return ChaCha20.ChaChaDecryptor(chacha: self) - } } diff --git a/Sources/CryptoSwift/Foundation/Utils+Foundation.swift b/Sources/CryptoSwift/Foundation/Utils+Foundation.swift index f9453650..9f2cc3e2 100644 --- a/Sources/CryptoSwift/Foundation/Utils+Foundation.swift +++ b/Sources/CryptoSwift/Foundation/Utils+Foundation.swift @@ -2,6 +2,7 @@ // CryptoSwift // // Copyright (C) 2014-2017 Marcin Krzyżanowski +// Copyright (C) 2019 Roger Miret Giné // 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. @@ -25,3 +26,7 @@ func perf(_ text: String, closure: () -> Void) { print("\(text) \(executionTime)") } + +func rotl(_ a: UInt32, _ b: Int) -> UInt32 { + return (a << b) | (a >> (32 - b)) +} diff --git a/Sources/CryptoSwift/Salsa20.swift b/Sources/CryptoSwift/Salsa20.swift new file mode 100644 index 00000000..79bbc2f0 --- /dev/null +++ b/Sources/CryptoSwift/Salsa20.swift @@ -0,0 +1,266 @@ +// +// CryptoSwift +// +// Copyright (C) 2014-2017 Marcin Krzyżanowski +// Copyright (C) 2019 Roger Miret Giné +// 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 class Salsa20: BlockCipher { + public enum Error: Swift.Error { + case invalidKeyOrInitializationVector + case notSupported + } + + public static let blockSize = 64 // 512 / 8 + public let keySize: Int + + let key: Key + var counter: Array + + public init(key: Array, iv nonce: Array) throws { + precondition(nonce.count == 12 || nonce.count == 8) + + if key.count != 32 { + throw Error.invalidKeyOrInitializationVector + } + + self.key = Key(bytes: key) + keySize = self.key.count + + 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) + } + + func qr(_ a: inout UInt32, _ b: inout UInt32, _ c: inout UInt32, _ d: inout UInt32) { + b ^= rotl(a + d, 7) + c ^= rotl(b + a, 9) + d ^= rotl(c + b, 13) + a ^= rotl(d + c, 18) + } + + func core(block: inout Array, counter: Array, key: Array) { + precondition(block.count == Salsa20.blockSize) + precondition(counter.count == 16) + precondition(key.count == 32) + + let j0: UInt32 = 0x61707865 + let j1: UInt32 = UInt32(bytes: key[0..<4]).bigEndian + let j2: UInt32 = UInt32(bytes: key[4..<8]).bigEndian + let j3: UInt32 = UInt32(bytes: key[8..<12]).bigEndian + let j4: UInt32 = UInt32(bytes: key[12..<16]).bigEndian + let j5: UInt32 = 0x3320646e // 0x3620646e sigma/tau + let j6: UInt32 = UInt32(bytes: counter[8..<12]).bigEndian + let j7: UInt32 = UInt32(bytes: counter[12..<16]).bigEndian + let j8: UInt32 = UInt32(bytes: counter[0..<4]).bigEndian + let j9: UInt32 = UInt32(bytes: counter[4..<8]).bigEndian + let j10: UInt32 = 0x79622d32 + let j11: UInt32 = UInt32(bytes: key[16..<20]).bigEndian + let j12: UInt32 = UInt32(bytes: key[20..<24]).bigEndian + let j13: UInt32 = UInt32(bytes: key[24..<28]).bigEndian + let j14: UInt32 = UInt32(bytes: key[28..<32]).bigEndian + let j15: UInt32 = 0x6b206574 + + 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 + // Odd round + qr(&x0, &x4, &x8, &x12) // column 1 + qr(&x5, &x9, &x13, &x1) // column 2 + qr(&x10, &x14, &x2, &x6) // column 3 + qr(&x15, &x3, &x7, &x11) // column 4 + + // Even round + qr(&x0, &x1, &x2, &x3) // row 1 + qr(&x5, &x6, &x7, &x4) // row 2 + qr(&x10, &x11, &x8, &x9) // row 3 + qr(&x15, &x12, &x13, &x14) // row 4 + } + + 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: ArraySlice, counter: inout Array, key: Array) -> Array { + precondition(counter.count == 16) + precondition(key.count == 32) + + var block = Array(repeating: 0, count: Salsa20.blockSize) + var bytesSlice = bytes + var out = Array(reserveCapacity: bytesSlice.count) + + while bytesSlice.count >= Salsa20.blockSize { + core(block: &block, counter: counter, key: key) + for (i, x) in block.enumerated() { + out.append(bytesSlice[bytesSlice.startIndex + i] ^ x) + } + var u: UInt32 = 1 + for i in 0..<4 { + u += UInt32(counter[i]) + counter[i] = UInt8(u & 0xff) + u >>= 8 + } + bytesSlice = bytesSlice[bytesSlice.startIndex + Salsa20.blockSize.. 0 { + core(block: &block, counter: counter, key: key) + for (i, v) in bytesSlice.enumerated() { + out.append(v ^ block[i]) + } + } + return out + } +} + +// MARK: Cipher + +extension Salsa20: Cipher { + public func encrypt(_ bytes: ArraySlice) throws -> Array { + return process(bytes: bytes, counter: &counter, key: Array(key)) + } + + public func decrypt(_ bytes: ArraySlice) throws -> Array { + return try encrypt(bytes) + } +} + +// MARK: Encryptor + +extension Salsa20 { + public struct SalsaEncryptor: Cryptor, Updatable { + private var accumulated = Array() + private let salsa: Salsa20 + + init(salsa: Salsa20) { + self.salsa = salsa + } + + public mutating func update(withBytes bytes: ArraySlice, isLast: Bool = false) throws -> Array { + accumulated += bytes + + var encrypted = Array() + encrypted.reserveCapacity(accumulated.count) + for chunk in accumulated.batched(by: Salsa20.blockSize) { + if isLast || accumulated.count >= Salsa20.blockSize { + encrypted += try salsa.encrypt(chunk) + accumulated.removeFirst(chunk.count) // TODO: improve performance + } + } + return encrypted + } + + public func seek(to: Int) throws { + throw Error.notSupported + } + } +} + +// MARK: Decryptor + +extension Salsa20 { + public struct SalsaDecryptor: Cryptor, Updatable { + private var accumulated = Array() + + private var offset: Int = 0 + private var offsetToRemove: Int = 0 + private let salsa: Salsa20 + + init(salsa: Salsa20) { + self.salsa = salsa + } + + public mutating func update(withBytes bytes: ArraySlice, isLast: Bool = true) throws -> Array { + // prepend "offset" number of bytes at the beginning + if offset > 0 { + accumulated += Array(repeating: 0, count: offset) + bytes + offsetToRemove = offset + offset = 0 + } else { + accumulated += bytes + } + + var plaintext = Array() + plaintext.reserveCapacity(accumulated.count) + for chunk in accumulated.batched(by: Salsa20.blockSize) { + if isLast || accumulated.count >= Salsa20.blockSize { + plaintext += try salsa.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 + } + + public func seek(to: Int) throws { + throw Error.notSupported + } + } +} + +// MARK: Cryptors + +extension Salsa20: Cryptors { + //TODO: Use BlockEncryptor/BlockDecryptor + + public func makeEncryptor() -> Cryptor & Updatable { + return Salsa20.SalsaEncryptor(salsa: self) + } + + public func makeDecryptor() -> Cryptor & Updatable { + return Salsa20.SalsaDecryptor(salsa: self) + } +} diff --git a/Tests/Tests/Salsa20Tests.swift b/Tests/Tests/Salsa20Tests.swift new file mode 100644 index 00000000..0744b432 --- /dev/null +++ b/Tests/Tests/Salsa20Tests.swift @@ -0,0 +1,423 @@ +// +// CryptoSwift +// +// Copyright (C) 2014-2017 Marcin Krzyżanowski +// Copyright (C) 2019 Roger Miret Giné +// 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. +// + +@testable import CryptoSwift +import Foundation +import XCTest + +final class Salsa20Tests: XCTestCase { + func testSalsa20() { + let keys: [Array] = [ + [0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 0 + [0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 9 + [0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 18 + [0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 27 + [0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 36 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 45 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 54 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 63 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 72 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 81 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 90 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 99 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 108 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 117 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 126 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 135 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 144 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 153 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 162 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 171 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 180 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 189 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 198 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 207 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 216 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00], // Set 1, vector# 225 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00], // Set 1, vector# 234 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00], // Set 1, vector# 243 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08], // Set 1, vector# 252 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector# 0 + [0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09], // Set 2, vector# 9 + [0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12], // Set 2, vector# 18 + [0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B], // Set 2, vector# 27 + [0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24], // Set 2, vector# 36 + [0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D], // Set 2, vector# 45 + [0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36], // Set 2, vector# 54 + [0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F], // Set 2, vector# 63 + [0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48], // Set 2, vector# 72 + [0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51], // Set 2, vector# 81 + [0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A], // Set 2, vector# 90 + [0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63], // Set 2, vector# 99 + [0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C], // Set 2, vector#108 + [0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75], // Set 2, vector#117 + [0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E], // Set 2, vector#126 + [0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87], // Set 2, vector#135 + [0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90], // Set 2, vector#144 + [0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99], // Set 2, vector#153 + [0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2], // Set 2, vector#162 + [0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB], // Set 2, vector#171 + [0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4], // Set 2, vector#180 + [0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD], // Set 2, vector#189 + [0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6], // Set 2, vector#198 + [0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF], // Set 2, vector#207 + [0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8], // Set 2, vector#216 + [0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1], // Set 2, vector#225 + [0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA], // Set 2, vector#234 + [0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3], // Set 2, vector#243 + [0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC], // Set 2, vector#252 + [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F], // Set 3, vector# 0 + [0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28], // Set 3, vector# 9 + [0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31], // Set 3, vector# 18 + [0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A], // Set 3, vector# 27 + [0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43], // Set 3, vector# 36 + [0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C], // Set 3, vector# 45 + [0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55], // Set 3, vector# 54 + [0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E], // Set 3, vector# 63 + [0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67], // Set 3, vector# 72 + [0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70], // Set 3, vector# 81 + [0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79], // Set 3, vector# 90 + [0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82], // Set 3, vector# 99 + [0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B], // Set 3, vector#108 + [0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94], // Set 3, vector#117 + [0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D], // Set 3, vector#126 + [0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6], // Set 3, vector#135 + [0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF], // Set 3, vector#144 + [0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8], // Set 3, vector#153 + [0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1], // Set 3, vector#162 + [0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA], // Set 3, vector#171 + [0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3], // Set 3, vector#180 + [0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC], // Set 3, vector#189 + [0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5], // Set 3, vector#198 + [0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE], // Set 3, vector#207 + [0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7], // Set 3, vector#216 + [0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x00], // Set 3, vector#225 + [0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09], // Set 3, vector#234 + [0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12], // Set 3, vector#243 + [0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B], // Set 3, vector#252 + [0x00, 0x53, 0xA6, 0xF9, 0x4C, 0x9F, 0xF2, 0x45, 0x98, 0xEB, 0x3E, 0x91, 0xE4, 0x37, 0x8A, 0xDD, 0x30, 0x83, 0xD6, 0x29, 0x7C, 0xCF, 0x22, 0x75, 0xC8, 0x1B, 0x6E, 0xC1, 0x14, 0x67, 0xBA, 0x0D], // Set 4, vector# 0 + [0x05, 0x58, 0xAB, 0xFE, 0x51, 0xA4, 0xF7, 0x4A, 0x9D, 0xF0, 0x43, 0x96, 0xE9, 0x3C, 0x8F, 0xE2, 0x35, 0x88, 0xDB, 0x2E, 0x81, 0xD4, 0x27, 0x7A, 0xCD, 0x20, 0x73, 0xC6, 0x19, 0x6C, 0xBF, 0x12], // Set 4, vector# 1 + [0x0A, 0x5D, 0xB0, 0x03, 0x56, 0xA9, 0xFC, 0x4F, 0xA2, 0xF5, 0x48, 0x9B, 0xEE, 0x41, 0x94, 0xE7, 0x3A, 0x8D, 0xE0, 0x33, 0x86, 0xD9, 0x2C, 0x7F, 0xD2, 0x25, 0x78, 0xCB, 0x1E, 0x71, 0xC4, 0x17], // Set 4, vector# 2 + [0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC, 0x3F, 0x92, 0xE5, 0x38, 0x8B, 0xDE, 0x31, 0x84, 0xD7, 0x2A, 0x7D, 0xD0, 0x23, 0x76, 0xC9, 0x1C], // Set 4, vector# 3 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 5, vector# 0 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 5, vector# 9 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 5, vector# 18 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 5, vector# 27 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 5, vector# 36 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 5, vector# 45 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 5, vector# 54 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 5, vector# 63 + [0x00, 0x53, 0xA6, 0xF9, 0x4C, 0x9F, 0xF2, 0x45, 0x98, 0xEB, 0x3E, 0x91, 0xE4, 0x37, 0x8A, 0xDD, 0x30, 0x83, 0xD6, 0x29, 0x7C, 0xCF, 0x22, 0x75, 0xC8, 0x1B, 0x6E, 0xC1, 0x14, 0x67, 0xBA, 0x0D], // Set 6, vector# 0 + [0x05, 0x58, 0xAB, 0xFE, 0x51, 0xA4, 0xF7, 0x4A, 0x9D, 0xF0, 0x43, 0x96, 0xE9, 0x3C, 0x8F, 0xE2, 0x35, 0x88, 0xDB, 0x2E, 0x81, 0xD4, 0x27, 0x7A, 0xCD, 0x20, 0x73, 0xC6, 0x19, 0x6C, 0xBF, 0x12], // Set 6, vector# 1 + [0x0A, 0x5D, 0xB0, 0x03, 0x56, 0xA9, 0xFC, 0x4F, 0xA2, 0xF5, 0x48, 0x9B, 0xEE, 0x41, 0x94, 0xE7, 0x3A, 0x8D, 0xE0, 0x33, 0x86, 0xD9, 0x2C, 0x7F, 0xD2, 0x25, 0x78, 0xCB, 0x1E, 0x71, 0xC4, 0x17], // Set 6, vector# 2 + [0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC, 0x3F, 0x92, 0xE5, 0x38, 0x8B, 0xDE, 0x31, 0x84, 0xD7, 0x2A, 0x7D, 0xD0, 0x23, 0x76, 0xC9, 0x1C], // Set 6, vector# 3 + ] + + let ivs: [Array] = [ + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 0 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 9 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 18 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 27 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 36 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 45 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 54 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 63 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 72 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 81 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 90 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 99 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 108 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 117 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 126 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 135 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 144 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 153 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 162 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 171 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 180 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 189 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 198 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 207 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 216 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 225 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 234 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 243 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 1, vector# 252 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector# 0 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector# 9 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector# 18 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector# 27 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector# 36 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector# 45 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector# 54 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector# 63 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector# 72 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector# 81 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector# 90 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector# 99 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector#108 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector#117 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector#126 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector#135 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector#144 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector#153 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector#162 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector#171 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector#180 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector#189 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector#198 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector#207 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector#216 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector#225 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector#234 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector#243 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 2, vector#252 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector# 0 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector# 9 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector# 18 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector# 27 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector# 36 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector# 45 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector# 54 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector# 63 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector# 72 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector# 81 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector# 90 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector# 99 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector#108 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector#117 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector#126 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector#135 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector#144 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector#153 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector#162 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector#171 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector#180 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector#189 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector#198 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector#207 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector#216 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector#225 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector#234 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector#243 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 3, vector#252 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 4, vector# 0 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 4, vector# 1 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 4, vector# 2 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 4, vector# 3 + [0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 5, vector# 0 + [0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 5, vector# 9 + [0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00], // Set 5, vector# 18 + [0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00], // Set 5, vector# 27 + [0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00], // Set 5, vector# 36 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00], // Set 5, vector# 45 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00], // Set 5, vector# 54 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01], // Set 5, vector# 63 + [0x0D, 0x74, 0xDB, 0x42, 0xA9, 0x10, 0x77, 0xDE], // Set 6, vector# 0 + [0x16, 0x7D, 0xE4, 0x4B, 0xB2, 0x19, 0x80, 0xE7], // Set 6, vector# 1 + [0x1F, 0x86, 0xED, 0x54, 0xBB, 0x22, 0x89, 0xF0], // Set 6, vector# 2 + [0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9], // Set 6, vector# 3 + ] + + let expectedHexes = [ + "E3BE8FDD8BECA2E3EA8EF9475B29A6E7003951E1097A5C38D23B7A5FAD9F6844B22C97559E2723C7CBBD3FE4FC8D9A0744652A83E72A9C461876AF4D7EF1A117", // Set 1, vector# 0 + "01F191C3A1F2CC6EBED78095A05E062E1228154AF6BAE80A0E1A61DF2AE15FBCC37286440F66780761413F23B0C2C9E4678C628C5E7FB48C6EC1D82D47117D9F", // Set 1, vector# 9 + "C29BA0DA9EBEBFACDEBBDD1D16E5F5987E1CB12E9083D437EAAAA4BA0CDC909E53D052AC387D86ACDA8D956BA9E6F6543065F6912A7DF710B4B57F27809BAFE3", // Set 1, vector# 18 + "FF852567EB72687DC56C122D61B2FB2A4FB9E8E8DA62313B618D10F8E0DA521B176E879CD78E641043F0FA4A22211566429B7C68EC645FF5E44B2505D61A2D71", // Set 1, vector# 27 + "AF6E2EE1D5021675A92F02C764AFD94AF3097F53532FC965EB861D6D12A3A012ABA683A5281238CE76E3AF3944736752AD86A5FD16E7DAFAF241ECFB0ADBBDFE", // Set 1, vector# 36 + "D203CC523351942C94E215F6D5CC1425C5FFB2EA9A916C0D4F7B343333A58D941DE20B5F543E3EE63C29D981469ACE4886ED9DEF839D4FBD20CDF9D001F1B89B", // Set 1, vector# 45 + "C45E28A2C9A80AC07A760580DCD9634026651B25BA2332FDAFC9AA16998317B9751A446302CDE95525C709E79CB559514E4A54FD73ADAAF0AB3A3F1ADDABBADA", // Set 1, vector# 54 + "5F7B6B86B0C197B960D8250B5106CFEBF6F4DE0D94D3958945FA979534AFE19CD5305C55A1404C59302F05ACC819D3A3B0BDB9D154A45C0DEE52F25012DAA445", // Set 1, vector# 63 + "B96FCF5A182789AD14E53FB2E981E496B47C6B44BE7EF95692F19AE24E1932196E180778AC04A0EB2497497680587FEBF412BB3A67E9538CA5B2A373E16E60F3", // Set 1, vector# 72 + "2B08D82E92AC352247211D5F0791DAC9D585ABF67DADFBD7B5AC60EB2EEF4C72F6F71CA110DEE4CB2F19FABE4F442B2F5F9FB1C94FBD553C21CD5B0CEF139880", // Set 1, vector# 81 + "C9969A75572ABFAA28FBE769A287A6763B534AF50B697C31B7F4CD8F50DDF2F217B3C5532E95F73AF11B0693D5A33A34DAFBB64635A195EC9477FDFD69AE7540", // Set 1, vector# 90 + "698BFC90B147715FB9F0CA1DDC94EE103082316701CDD1DF2EAE752BA485F5859E131D0D9233B16890BD5946CBCF116DB50E8E2DCAE104162C7B76CB3D11445C", // Set 1, vector# 99 + "07AE6801D7A94836ED52CCD69D9E97F634B136A234B978BAE4302F475B0A6B0EA7905CEE090F648962BB969CB4D6522803E1ACD1DCBEFC2E7482C0D426E4BD95", // Set 1, vector# 108 + "A374C1F86586B0D5A121E1F734EE70CC7072284B322BF61F88336EBE84B53219F4D1FEE2C5EECC4A421BA8AEA9D108E721A7A82DD979F2559BB0E45CC88C8780", // Set 1, vector# 117 + "19F23D5CB3C7303D56AFF18413835EF3DF7405C30BE5F19C72FE8746BA04610DD5D261FB3A0E8C11D2478F4A4D6CF8209730187BB1386C03229F4EB02C5B4422", // Set 1, vector# 126 + "B18CFBA23F81884FBFEA037648B1715CEFAEF1D8CD5C98957353E82B838FE332672B3D7C2905979698F6F6D98EAAE8F98DA16EF393CB150228FE6438440C5759", // Set 1, vector# 135 + "0EEF3E17B6B9388FB55C2C0AEF9716CB106786EEB0E606E124C41AB552EF33897902AA2AE93D9E4628E785B356C53AC970BDEE2A7DDBAB427371903EF3EC9FA5", // Set 1, vector# 144 + "AE5572D5E61A992162AEEE513815339C93A994DB12576D087EA4A9A98EA5946CF58794B43515A4B55C5E9B28A882DADE7D3BFE82B32EC3B604D2C1E1B37B1B99", // Set 1, vector# 153 + "BA66E5BA75AD8C4030AE54B554E07A9729685FDF033CCC35A153334E9FC93A903C79F281907BADF6F37123819ACA25E1F03BA0AC69D9B2D5E447F59F31A7A402", // Set 1, vector# 162 + "59DBEE08FB86EBCBEBFFBF087F9DD8812AFFFD75414B5162B5E7AE540BFA87775BEC4982E1F4B6985DC8B2B25F06194761BD6BC5EFD66B2A1EB12833733E5490", // Set 1, vector# 171 + "FD1D039AE6D953654A63334A92CEC647A671CAB6374DB63B89DA1A12B99C231DC7B9418D44210CB0C88F114EAA54AE4A096FEFCCBF51062E8EFD169715677F28", // Set 1, vector# 180 + "72491EC81A704E3694C83FCCC47CF5E87B66F7B7979F78D8150A606ACDCB4492F64A9D7D9DAD5042F8738DB462F4728C2475F5FDEE985CD3601FA31F576712C3", // Set 1, vector# 189 + "E3D058FC000427B4F0802300E5D7FE9F8E3F68E9E8339E9F4C5DE62252E1485771371DE4D2E1C97DC4172AA378924AB42CADF887136B88D6FEB6514538EBA847", // Set 1, vector# 198 + "FF0D93064CDBD91A8D6BD0B9267A4F93DF7D3C76BAA5D0D14798812203C55A343BD50E6931394DAB88F514F44E2A1FB58EF3A915F3B60DAB35E36174AD92B3B1", // Set 1, vector# 207 + "DCC597DC08E1AD1451E69D857AF803BBDBF7CD6D510D5C59C9D6C66EB153CC79F9A6228ADEE570983E959788628F174E5833B5CFA350C0C2D8A18F7FE46BB4E1", // Set 1, vector# 216 + "C94A72C1B17F8B9F26420BF06B3A544520C658D5F77ED7D62CC65AF824BD567898EE4928AF0E2BEDEA64D5A7C22749C3C16369D274EFD2A6DF2CFCCB130A1144", // Set 1, vector# 225 + "832A824C044E27605AD9A3201EF106C1A19B6FC6EA5B328DC1D1FC59086C498D47E7568CFA9616D7D5E63D9C087CC426B4276752E0FF14D7F1E258F9A28A54BA", // Set 1, vector# 234 + "28DD9E566F018FDA0251E1E648057E85211831E215AE21525E04C932736245C2288AD4A197E4ECA04003B85C3B80D02A9B82C28E7662A34467946A34257D8D0B", // Set 1, vector# 243 + "E48C2F264BF9E8374B78FB652BAFF1E33ECB4B1C635D76A64ECFC4BDE00EE5C877E1094D6480CA382815CCCD5CC3677046E801C29A860EB032420DCAEEBC36F4", // Set 1, vector# 252 + "9A97F65B9B4C721B960A672145FCA8D4E32E67F9111EA979CE9C4826806AEEE63DE9C0DA2BD7F91EBCB2639BF989C6251B29BF38D39A9BDCE7C55F4B2AC12A39", // Set 2, vector# 0 + "7041E747CEB22ED7812985465F50333124F971DA1C5D6EFE5CA201B886F31046E757E5C3EC914F60ED1F6BCE2819B6810953F12B8BA1199BF82D746A8B8A88F1", // Set 2, vector# 9 + "7BCD4C5528F4BEAE0FC9F164CEBEC73ED89CE32DA46EB68CA3CEDAA7C7A580FB1C50D291F31C38DB2811864F6654098E141A2213828593A98B7D0020BF0D6D93", // Set 2, vector# 18 + "944B67EAB62DF3756085CEE577D0C1DA4DD7CD17B85F9B9C51004107C8AA69357E413AEA37BB512BD8246F2D03E2748D3BB24B60C1FBE4D1A55237FFE3D4D604", // Set 2, vector# 27 + "0FDF243C21DA8B291097C9F385DFF2AD4FDCA5EB4FA7E4C23CC61FA1A582EB235AE23454DF6F19B259E498F746F9EF35491F77DC53BD596AACCB9FB7B5EE8ABC", // Set 2, vector# 36 + "3D9EA1F4A3036C92CF9E0D6BB20824C0F57818B3C84DF65AE4A1DE2A058F8BEE242F9BEA42A78383F98AC998BE4B1EA5401BEA5250611CFE6505AA5F43C9A262", // Set 2, vector# 45 + "E0E9C87C82202453CDE753D368DA18429279F0B97446FB12A0436C6BE1AA75143E98B740F6F9CEC72A1EA38D4EF2BC65E1AF3AE13C5ADF6DA16A2131739C0084", // Set 2, vector# 54 + "18B631E89190A2C763AD5F1DBC57B565EAD588F7DC85C3DD75E7D7E74C1D4429E2FB3C6CB687A620EB7050CCD49B54D0F147302BFB7ADC6D1EB235A60338D190", // Set 2, vector# 63 + "82492EEE44E22AD4DFCA2032BA401F737D4BC35CE8546EB6314EDC25E69DAC16C8A9EBED6EAB895B7D72BFACEAA14E363F9A9773E43B077A1991EAC1EEA83EC5", // Set 2, vector# 72 + "C7FC0F8C8D2064FE05BEC4A641560FCBC41A60718B1DF62AA297E754756CDB6848C5BF60721B49A854A7A4D4BF2D36EE943A3B3922A638293B32F15A7E9A1357", // Set 2, vector# 81 + "6C3645C8621D8E7286911278BAB37C5EEBAA2AD321AB8ECA62D13372156F8B87FB87FBE02B1EFE39AB0EBE41553E5348073053048A0D4DBDA1880230CD23A4F1", // Set 2, vector# 90 + "D417644E8A37FF8840772A55960C4B064DA371869EA07FD02D7F8EFEF0BDB7CE308173B8BAFDCA6064CEBE09609377B6542CE73D44A0134C95C452D9B83A4B35", // Set 2, vector# 99 + "1456A98D271F43A5FF29B3D0BCC35B7850C4D9DA5BBA43B752A1A541A4FC88DC0FC4C89F35ACF1B540F5C3207A0BF359490D482232936E5C0B818C3DE6EF2012", // Set 2, vector#108 + "8F04C8F40319569CB4B04458528135E835AF2C69561F0F0F5B6009B540B85ED1BC7612C9EC7A200B08AEDF07DB08ABC39FA48E63AC81974175AE3A4AC9429985", // Set 2, vector#117 + "DFD428440260E1B64579A6940EE539078CF48977E4B61DD0C708B52B42A607ABC0A0774F49FD8599E4A4CA3B7C54FEDC353D2467DEECDB9FFC8350C79414CFBB", // Set 2, vector#126 + "47756F1D1EEDDF06790A5E39083186D316E3258B9C5B7D25E478E817308E2B90A5DC4A8C03A38AE1757B6EFAE73B058A7CEA675CEE9A01E9BBC7B15DC5424E64", // Set 2, vector#135 + "6AB7A8C769386FB6067059D0EE3DBC971EFAEF4AC10C74A2F17527EA5A8C6E0CDF1FA10F27A29911BB57BF3E7A6DBDCE4AF3E7BB730F47AC79DC917DA646A8B7", // Set 2, vector#144 + "E548ECEAF4B4AF1F8572F7113C7D8FF961837C15ECC6BEAAB80F38CB15022B50BCB1FA414A798C954DAFB572CF22A9A4D82F7561186C31BA0199EAE1678CC4CF", // Set 2, vector#153 + "D0854334E4619E3EFBB2A53D59F89866F67220CE00A3116313FB9CB6453397660CA976A8B3477F76FF8FA485D61E37583DA5F35A8FAD678B7C2B9EC97321DFD0", // Set 2, vector#162 + "6CD6B451B1C793485006B3B51470E6AB20163502C30240C4A3C6406482A2770D550AD77D0091632C719BA33769823D2D8147396466F1A2A857060A42ECCE0A0E", // Set 2, vector#171 + "EE879D01C8E20CE8CACDDB464348F69C6551F70383A82933C3A765B8AC1385818D67C69841FF2B4B8BC209ECFC0FE765C44C42C9CD6EFF90E0A6DAB153F52D04", // Set 2, vector#180 + "DED8C79CC623162C2074FC7B4876F7541B959209AC6573E6D25D1F1E649CC24131A2F1B1B9E9E0FA639F8AF373CCAB883C659001BD120449997871E6A1D5AD8E", // Set 2, vector#189 + "36AFBAFFF746195D8784CB72A16D12AA604CDBF567955F15FB55DD42FAE8DDC4E6CEA63B6F8E2815F3094005E403FEA30EEDD68B5F2573EFD03A4E2BC41AEC32", // Set 2, vector#198 + "AA68F6EB41DB62A2C5E4E9AAF21D7D431C29A66303854A68EF737872CBF7C505918B87CE4DB6B3D84BC039906AC0561DF79F0A57CFA762B8B9C2991F1DC98032", // Set 2, vector#207 + "596EA70BBA1A4DE2F8ED2AF37A0CE6D12443354659CD0C41203EB345E160CF056F8D71314AA7221D86F868304F34D5B3ED4D51072FE7B12568B859077B6F920D", // Set 2, vector#216 + "6D221A5561813E4B6BF1A3821F0BC95B3D51004ED29EAECD26016E5B7F628BA06B2BA4D650D685C3BA9FB51E305EEB36A11CA08C431E0740D59D521FBDDBF716", // Set 2, vector#225 + "304665A82B0838D4EA0A7737855CEAB044583FBF2F8E68D7B3B191600ADAEB33538942A71998F68DA9A0D4BAC36A5052CBEAEFFCABC6B506E5F805F8105D5E79", // Set 2, vector#234 + "BF9634C2D81B6400C2ADACFCC0C353CE3AC45A2EB636AE9D2D6B8DB6107511C9399FB22CA2DF6406307EADEED423E72B72411E11530B1814AB196A74DFD4FA61", // Set 2, vector#243 + "356DD71DBC2B216B7A439E07BCC1348F769F7EF482486C92E8FD8EB050224838AB1F4DFCD2FB196AFD4C4FFBF51B91246BF45AE8131B8D5CAFA29FC3025A3597", // Set 2, vector#252 + "B580F7671C76E5F7441AF87C146D6B513910DC8B4146EF1B3211CF12AF4A4B49E5C874B3EF4F85E7D7ED539FFEBA73EB73E0CCA74FBD306D8AA716C7783E89AF", // Set 3, vector# 0 + "0DD83B7F93629BA8E489E30FE4B6EE549BAFB44CB794AAEF2EF07116649FD4C44DAC52560EFB34FF1A2E56FC0DD86F2D56C2C5C97089FC4C35C6788F36E6F142", // Set 3, vector# 9 + "4B094A8031FEA02C5CBDC1E2A64B13A9A0976897FCBD92A15738330CD1F85448EBD8B7E61A76855C64BE1BE78034ADEBFFDEDFCF064AB92744760DFBF59F0A9D", // Set 3, vector# 18 + "AE39508EAC9AECE7BF97BB20B9DEE41F87D947F828913598DB72CC232948565E837E0BF37D5D387B2D7102B43BB5D823B04ADF3CECB6D93B9BA752BEC5D45059", // Set 3, vector# 27 + "5DDE22EEE0ED12CF83F433441A3799B3A4415A2018A60BDE0A0F8E08993820C820998D420F346D8B808CBED40FC7CBD0CC43949B0A16F0EF2577CECAD03DCAD6", // Set 3, vector# 36 + "BDF4E0BB6B36D01A31EE2E76F2379D33286ABFA82F6872677955777DEE0B1662A65D85EBC56A7995A6F6CF995154C444C27CEF3EABC85B8985C7FA94C8ECB065", // Set 3, vector# 45 + "51B180F1C9C31388F8B3DE8734F3918FF6DEC759689E6A54D0EAF8734DECAB2CA2ACA4DFAA260AB781769B83CF94C2A0166F2643585CAB42220D200F92074363", // Set 3, vector# 54 + "AADBA970B29F5BB8522C3817E849E5D0417863554D16D6FC42405CA5A826A82A7F0ADD295D02DF3EB565E10CA1902E7EE84CC977614F325AA0BCA298F64871C4", // Set 3, vector# 63 + "53AD3698A011F779AD71030F3EFBEBA0A7EE3C55789681B1591EF33A7BE521ED68FC36E58F53FFD6E1369B00E390E973F656ACB097E0D603BE59A0B8F7975B98", // Set 3, vector# 72 + "B2995CDC9255E4E6177398EECE05F338BE14825E8025598C1B4B0B80013E5D4BC195802ACF47326F309C58809E044CA02027CCE97D80F7AEBA6D0376C96BFD7A", // Set 3, vector# 81 + "447D16E09F139ADBFDBC742D248EC35467F165D42937FBA97B816016613DE365B0C23E4145CA71A3680B382CFF6D615CE7B2B02AEE1B6CAE692E4D09B2B47CE4", // Set 3, vector# 90 + "D356187B3A555932420B005EEA1703CB6C568987D54316540561425C078A0BC16011BD3A1E88C62039608DDB65C354538E6E6BE417066D824B4CC3F4842D1B7D", // Set 3, vector# 99 + "4C2EB1D4A9A84064F43082EAC25C741FA49F2579FCB069A2B072B4D7EB704B38E00DB35E0D9C2077E58B9403D73904B9BDAF16A1C79A0A25B0B9BC06E49D2659", // Set 3, vector#108 + "B36D9BB49A62689A751CF5C971A15F70439E56DC516F15F958369E3DA2500EC4D51CE469B050037570D03B0948D9FF82F2AD1B1D65FA5D782CAE515E03BA6A60", // Set 3, vector#117 + "4E7DB2320A4A7717959C27182A53072B9D18874644B42B319963B5512340AA4DC7088FE4803EE59CC25E77AC29D13E7220654487F4A3BF2D39C073C7D231DB17", // Set 3, vector#126 + "EE17A6C5E4275B77E5CE6B0549B556A6C3B98B508CC370E5FA9C4EA928F7B516D8C481B89E3B6BE41F964EE23F226A97E13F0B1D7F3C3FBBFF2E49A9A9B2A87F", // Set 3, vector#135 + "14530F67317B09CB008EA4FD08813F804AC63D6B1D595D21E244E11AA4F153E1256DF77976F713B4F7DD1DF64E7016BBF9460A1A7CC7F3E9D28D8D19A69EB0B4", // Set 3, vector#144 + "9B05907B8F2EE3E831D9A0BE6203DBED012C381B7E3225B52282B9D0BA5A5A6AA367F7C553177557B87FFAA73C59E123B8B2F069B6C0F6DF25CC0A340CD2550D", // Set 3, vector#153 + "7D0FF0DCB7CAAC90E548E24BEEA22D101C927E0A9BD559BC32BA70B346659F418FD9E36202D3AF35CB836F1BD15087DE0D01FFF0BD42BC24B01A65CAD6F38E2C", // Set 3, vector#162 + "F943B21C04A85C22ED1FC5BFBACAAF932CB889EF7CD4472089B16B6DDA5C72E9A8F11B66CFC7677D72FB8908018B2A32F6B37A2AC811665D8266841199C066AE", // Set 3, vector#171 + "5F76E49A712A9B36D646FDB1355FA862DE02BDC06E9AA4DF8DC0749102ADB071D575101D0CA6E36034EE3A039CF5239B817466A88DE350081D91090D79842DF5", // Set 3, vector#180 + "1D8D3CB0B17972779FBD8339BDBC5D0C4178C943381AFA6FA974FF792C78B4BB5E0D8A2D2F9988C01F0FF7CE8AD310B66FA3B8D8CB507E507C4516BC9E7603B6", // Set 3, vector#189 + "9D2EB0E9A93A0EF9F8ABCE0916C06EEBE9C8EBB52A8112CD352A8E2E4EE84DFD44B7C8251D0D1A36EA69CEB8C595D527DA0EF26A2C5A5F443DC3040C6BF2DA49", // Set 3, vector#198 + "1D99BD420A9EBE17CF6144EEBE46A4B5D8CE913F571DCEDEE6C6E3CFA27572F59983D4B2CADC292A956983AF7250CA81A23A9EDA42417CC150597891045FF321", // Set 3, vector#207 + "B9751AF24FCF14907948F7AD36E2649A9A07B637F84D34E961EE82B7C33A9CC37B96DA6A956AFF4A629546C422802767AD9F24BB2E79F09FCD43775FAC965123", // Set 3, vector#216 + "EA444200CDE137A48DD3728CFC0FE82A1CD6F0F412C0343639052B6471F8321C3C9A38986A5F882A26ABCFB342D3FF504E2EBF01D8CDA2408AE1A9023F4D64CA", // Set 3, vector#225 + "99A8CCEC6C5B2A0B6E336CB20652241C32B24D34ACC0457EF679178EDE7CF805805A9305C7C49909683BD1A803327817627CA46FE8B929B6DF0012BD864183BE", // Set 3, vector#234 + "B4C0AFA503BE7FC29A62058166D56F8F5D27DC246F75B9AD8760C8C39DFD87492D3B76D5D9637F009EADA14458A52DFB09815337E72672681DDDC24633750D83", // Set 3, vector#243 + "2064790538ACDF1DE3852C465070D962FE2993BDD20C96DED5B2E5FA332833742A6B03966D47F8874D39C501ECFE0045725C463530967ED1499097906B9775C3", // Set 3, vector#252 + "F9D2DC274BB55AEFC2A0D9F8A982830F6916122BC0A6870F991C6ED8D00D2F8594E3151DE4C5A19A9A06FBC191C87BF039ADF971314BAF6D02337080F2DAE5CE", // Set 4, vector# 0 + "2F634849A4EDC206CE3E3F89949DF4E6EA9A0E3EE87F0AB108C4D3B789ACE67307AC8C54F07F30BAD9640B7F6EDEEC9DB15E51599EB15E1CA94739FEA5F1E3D7", // Set 4, vector# 1 + "0A8BBD088ABADC4D57D3389E32175878125BD89DE7E9D05DBF29B753F5F0C2CBF0EEF9333526E9308A114E06EB9564EB35C28EA93C17BEF0466748079A355B9C", // Set 4, vector# 2 + "4A671A2AE75DB7555BEA5995DC53AF8DC1E8776AF917A3AB2CA9827BCED53DA700B779820F17294751A2C37EF5CCCFE97BF7481E85AFC9ECAE431B7CF05F6153", // Set 4, vector# 3 + "2ABA3DC45B4947007B14C851CD694456B303AD59A465662803006705673D6C3E29F1D3510DFC0405463C03414E0E07E359F1F1816C68B2434A19D3EEE0464873", // Set 5, vector# 0 + "F28343BCF4C946FC95DCAAED9DA10B277E573FC8EBC8CEE246FDDC533D29C2EA05451ED9A821C4161EE0AFA32EC0FCA0DAD124B702DA9248B3D2AA64489C9D26", // Set 5, vector# 9 + "621F3014E0ADC8022868C3D9070BC49E48BC6B504AFF11CB17957F0EBFB7612F7FCB67C60A2FBD7A4BD7C312E8F50AF3CA7520821D73DB47189DAD557C436DDC", // Set 5, vector# 18 + "D2DB1A5CF1C1ACDBE81A7A4340EF53435E7F4B1A50523F8D283DCF851D696E60F2DE7456181B8410D462BA6050F061F21C787FC12434AF58BF2C59CA9077F3B0", // Set 5, vector# 27 + "22E129373F7589D9EAFFF18DEA63432E38D0245BAE221D3635BEE176760552B89B6BC49CFEB7D9A5B358963C488ED8FAD01F1C72307CADEEF9C20273FB5D6775", // Set 5, vector# 36 + "DC302570A4D1C44F31D9FA55C7712B11AE770BFAA3F8631DFF924BCF00A09C906571B024CE5264215E516D73416BF3E3CE373CAE669DB1A057EFD7EB184243B6", // Set 5, vector# 45 + "98951956F4BD5E2E9DC624CCD2D79E606D24A4DB51D413FDAF9A9741A6F079B421400FDA0B4D8785578BB318BDAD4ABCA8C2D1BA3BA4E18C2F5572499F345BC1", // Set 5, vector# 54 + "B47F96AA96786135297A3C4EC56A613D0B80095324FF43239D684C57FFE42E1C44F3CC011613DB6CDC880999A1E65AED1287FCB11C839C37120765AFA73E5075", // Set 5, vector# 63 + "F5FAD53F79F9DF58C4AEA0D0ED9A9601F278112CA7180D565B420A48019670EAF24CE493A86263F677B46ACE1924773D2BB25571E1AA8593758FC382B1280B71", // Set 6, vector# 0 + "3944F6DC9F85B128083879FDF190F7DEE4053A07BC09896D51D0690BD4DA4AC1062F1E47D3D0716F80A9B4D85E6D6085EE06947601C85F1A27A2F76E45A6AA87", // Set 6, vector# 1 + "3FE85D5BB1960A82480B5E6F4E965A4460D7A54501664F7D60B54B06100A37FFDCF6BDE5CE3F4886BA77DD5B44E95644E40A8AC65801155DB90F02522B644023", // Set 6, vector# 2 + "5E5E71F90199340304ABB22A37B6625BF883FB89CE3B21F54A10B81066EF87DA30B77699AA7379DA595C77DD59542DA208E5954F89E40EB7AA80A84A6176663F", // Set 6, vector# 3 + ] + + for idx in 0..(repeating: 0, count: (expectedHex.count / 2)) + + do { + let encrypted = try message.encrypt(cipher: Salsa20(key: keys[idx], iv: ivs[idx])) + let decrypted = try encrypted.decrypt(cipher: Salsa20(key: keys[idx], iv: ivs[idx])) + XCTAssertEqual(message, decrypted, "Salsa20 decryption failed") + XCTAssertEqual(encrypted, Array(hex: expectedHex)) + } catch CipherError.encrypt { + XCTAssert(false, "Encryption failed") + } catch CipherError.decrypt { + XCTAssert(false, "Decryption failed") + } catch { + XCTAssert(false, "Failed") + } + } + } + + func testCore() { + let key: Array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31] + var counter: Array = [1, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 74, 0, 0, 0, 0] + let input = Array.init(repeating: 0, count: 129) + let salsa = try! Salsa20(key: key, iv: Array(key[4..<16])) + let result = salsa.process(bytes: input.slice, counter: &counter, key: key) + + XCTAssertEqual(result.toHexString(), "a8fb9ed4293ab0e60d2751605bfdb7f2c3cbe90cffdd5952f7db1e88a6eb6f191b7018a4d868a1bc0964f3966c9b3c249fe660b456ac27a54c411cd010593c5b4325ca7d1e5c851850b56666adf5b752339790a796a8ee148f128226ea0710c6c4c78a5362cd4307a8dcbe54f3f243cc25af9161c563a81afcc83cf2631b515f1b") + } + + func testVector1Py() { + let key: Array = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + let iv: Array = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + let expected: Array = [0x9A, 0x97, 0xF6, 0x5B, 0x9B, 0x4C, 0x72, 0x1B, 0x96, 0x0A, 0x67, 0x21, 0x45, 0xFC, 0xA8, 0xD4, 0xE3, 0x2E, 0x67, 0xF9, 0x11, 0x1E, 0xA9, 0x79, 0xCE, 0x9C, 0x48, 0x26, 0x80, 0x6A, 0xEE, 0xE6, 0x3D, 0xE9, 0xC0, 0xDA, 0x2B, 0xD7, 0xF9, 0x1E, 0xBC, 0xB2, 0x63, 0x9B, 0xF9, 0x89, 0xC6, 0x25, 0x1B, 0x29, 0xBF, 0x38, 0xD3, 0x9A, 0x9B, 0xDC, 0xE7, 0xC5, 0x5F, 0x4B, 0x2A, 0xC1, 0x2A, 0x39] + let message = Array(repeating: 0, count: expected.count) + + do { + let encrypted = try Salsa20(key: key, iv: iv).encrypt(message) + XCTAssertEqual(encrypted, expected, "Ciphertext failed") + } catch { + XCTFail() + } + } + + func testSalsa20EncryptPartial() { + let key: Array = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f] + let iv: Array = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + let expectedHex = [ + "B580F7671C76E5F7441AF87C146D6B513910DC8B4146EF1B3211CF12AF4A4B49E5C874B3EF4F85E7D7ED539FFEBA73EB73E0CCA74FBD306D8AA716C7783E89AF", + "9B5B5406977968E7F472DE2924EFFD0E8EA74C954D23FCC21E4ED87BBA9E0F79D1477D1810368F02259F7F53966F91CEB50ECD3DA10363E7F08EEAB83A0EF71A" + ] + + + let plaintext: Array = Array(repeating: 0, count: 256) + do { + let cipher = try Salsa20(key: key, iv: iv) + + var ciphertext = Array() + var encryptor = cipher.makeEncryptor() + ciphertext += try encryptor.update(withBytes: Array(plaintext[0..<8])) + ciphertext += try encryptor.update(withBytes: Array(plaintext[8..<16])) + ciphertext += try encryptor.update(withBytes: Array(plaintext[16..<80])) + ciphertext += try encryptor.update(withBytes: Array(plaintext[80..<256])) + ciphertext += try encryptor.finish() + XCTAssertEqual(Array(hex: expectedHex[0]), Array(ciphertext[0..<64])) + XCTAssertEqual(Array(hex: expectedHex[1]), Array(ciphertext[192..<256])) + } catch { + XCTFail() + } + } +} + +extension Salsa20Tests { + static func allTests() -> [(String, (Salsa20Tests) -> () -> Void)] { + let tests = [ + ("testSalsa20", testSalsa20), + ("testCore", testCore), + ("testVector1Py", testVector1Py), + ("testSalsa20EncryptPartial", testSalsa20EncryptPartial), + ] + + return tests + } +}