فهرست منبع

Working RSA implementation in reasonable time

Nathan Fallet 4 سال پیش
والد
کامیت
0fa1d01572

+ 2 - 0
CryptoSwift.podspec

@@ -16,4 +16,6 @@ Pod::Spec.new do |s|
   s.tvos.deployment_target = "9.0"
   s.source_files  = "Sources/CryptoSwift/**/*.swift"
   s.requires_arc = true
+  
+  s.dependency 'BigInt', '~> 5.2'
 end

+ 27 - 8
CryptoSwift.xcodeproj/project.pbxproj

@@ -16,9 +16,8 @@
 		42012783267A6F1C00F82506 /* ISO10126Padding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42012782267A6F1C00F82506 /* ISO10126Padding.swift */; };
 		674A736F1BF5D85B00866C5B /* RabbitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 674A736E1BF5D85B00866C5B /* RabbitTests.swift */; };
 		6A072FF726CAB3F900F4E94F /* RSA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A072FF626CAB3F900F4E94F /* RSA.swift */; };
-		6A43B45C26CBC928002AD852 /* GiantUIntTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A43B45B26CBC928002AD852 /* GiantUIntTests.swift */; };
 		6A7CDEED26CD1E4C00FFB1AF /* RSATests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A7CDEEC26CD1E4C00FFB1AF /* RSATests.swift */; };
-		6ADC6EEF26CBAC0C00AFBF4E /* GiantUInt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ADC6EEE26CBAC0C00AFBF4E /* GiantUInt.swift */; };
+		6AAD31D426DA33E900C09B53 /* BigInt in Frameworks */ = {isa = PBXBuildFile; productRef = 6AAD31D326DA33E900C09B53 /* BigInt */; };
 		750509991F6BEF2A00394A1B /* PKCS7.swift in Sources */ = {isa = PBXBuildFile; fileRef = 750509981F6BEF2A00394A1B /* PKCS7.swift */; };
 		750CC3EB1DC0CACE0096BE6E /* BlowfishTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 750CC3EA1DC0CACE0096BE6E /* BlowfishTests.swift */; };
 		75100F8F19B0BC890005C5F5 /* Poly1305Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75100F8E19B0BC890005C5F5 /* Poly1305Tests.swift */; };
@@ -212,9 +211,7 @@
 		42012782267A6F1C00F82506 /* ISO10126Padding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ISO10126Padding.swift; sourceTree = "<group>"; };
 		674A736E1BF5D85B00866C5B /* RabbitTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RabbitTests.swift; sourceTree = "<group>"; };
 		6A072FF626CAB3F900F4E94F /* RSA.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSA.swift; sourceTree = "<group>"; };
-		6A43B45B26CBC928002AD852 /* GiantUIntTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GiantUIntTests.swift; sourceTree = "<group>"; };
 		6A7CDEEC26CD1E4C00FFB1AF /* RSATests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSATests.swift; sourceTree = "<group>"; };
-		6ADC6EEE26CBAC0C00AFBF4E /* GiantUInt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GiantUInt.swift; sourceTree = "<group>"; };
 		750509981F6BEF2A00394A1B /* PKCS7.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PKCS7.swift; sourceTree = "<group>"; };
 		750CC3EA1DC0CACE0096BE6E /* BlowfishTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlowfishTests.swift; sourceTree = "<group>"; };
 		75100F8E19B0BC890005C5F5 /* Poly1305Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Poly1305Tests.swift; sourceTree = "<group>"; };
@@ -349,6 +346,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				6AAD31D426DA33E900C09B53 /* BigInt in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -443,7 +441,6 @@
 				E3FD2D511D6B813C00A9F35F /* Error+Extension.swift */,
 				754BE46719693E190098E6F3 /* DigestTests.swift */,
 				7576F6EB20726319006688F8 /* DigestTestsPerf.swift */,
-				6A43B45B26CBC928002AD852 /* GiantUIntTests.swift */,
 				75100F8E19B0BC890005C5F5 /* Poly1305Tests.swift */,
 				758A94271A65C59200E46135 /* HMACTests.swift */,
 				0EE73E72204D599C00110E11 /* CMACTests.swift */,
@@ -565,7 +562,6 @@
 				75EC52741EE8B6CA0048EB3B /* UInt32+Extension.swift */,
 				75EC52751EE8B6CA0048EB3B /* UInt64+Extension.swift */,
 				75D7AF37208BFB1600D22BEB /* UInt128.swift */,
-				6ADC6EEE26CBAC0C00AFBF4E /* GiantUInt.swift */,
 				75EC52771EE8B6CA0048EB3B /* Updatable.swift */,
 				75EC52781EE8B6CA0048EB3B /* Utils.swift */,
 				75EC52791EE8B6CA0048EB3B /* ZeroPadding.swift */,
@@ -675,6 +671,9 @@
 			dependencies = (
 			);
 			name = CryptoSwift;
+			packageProductDependencies = (
+				6AAD31D326DA33E900C09B53 /* BigInt */,
+			);
 			productName = CryptoSwift;
 			productReference = 754BE45519693E190098E6F3 /* CryptoSwift.framework */;
 			productType = "com.apple.product-type.framework";
@@ -781,6 +780,9 @@
 				Base,
 			);
 			mainGroup = 754BE44B19693E190098E6F3;
+			packageReferences = (
+				6AAD31D226DA33E900C09B53 /* XCRemoteSwiftPackageReference "BigInt" */,
+			);
 			productRefGroup = 754BE45619693E190098E6F3 /* Products */;
 			projectDirPath = "";
 			projectRoot = "";
@@ -876,7 +878,6 @@
 				75EC529B1EE8B8200048EB3B /* Rabbit+Foundation.swift in Sources */,
 				756A64C62111083B00BE8805 /* StreamEncryptor.swift in Sources */,
 				75EC52A61EE8B8390048EB3B /* PBKDF1.swift in Sources */,
-				6ADC6EEF26CBAC0C00AFBF4E /* GiantUInt.swift in Sources */,
 				75EC52B41EE8B83D0048EB3B /* UInt32+Extension.swift in Sources */,
 				75EC52911EE8B81A0048EB3B /* Cryptors.swift in Sources */,
 				75EC52881EE8B8170048EB3B /* ECB.swift in Sources */,
@@ -938,7 +939,6 @@
 				758A94291A65C67400E46135 /* HMACTests.swift in Sources */,
 				75100F8F19B0BC890005C5F5 /* Poly1305Tests.swift in Sources */,
 				E6200E171FB9B68C00258382 /* HKDFTests.swift in Sources */,
-				6A43B45C26CBC928002AD852 /* GiantUIntTests.swift in Sources */,
 				754BE46819693E190098E6F3 /* DigestTests.swift in Sources */,
 				E3FD2D531D6B81CE00A9F35F /* Error+Extension.swift in Sources */,
 				757DA2591A4ED4D7002BA3EF /* ChaCha20Tests.swift in Sources */,
@@ -1208,6 +1208,25 @@
 			defaultConfigurationName = Release;
 		};
 /* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+		6AAD31D226DA33E900C09B53 /* XCRemoteSwiftPackageReference "BigInt" */ = {
+			isa = XCRemoteSwiftPackageReference;
+			repositoryURL = "https://github.com/attaswift/BigInt";
+			requirement = {
+				kind = upToNextMajorVersion;
+				minimumVersion = 5.2.1;
+			};
+		};
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+		6AAD31D326DA33E900C09B53 /* BigInt */ = {
+			isa = XCSwiftPackageProductDependency;
+			package = 6AAD31D226DA33E900C09B53 /* XCRemoteSwiftPackageReference "BigInt" */;
+			productName = BigInt;
+		};
+/* End XCSwiftPackageProductDependency section */
 	};
 	rootObject = 754BE44C19693E190098E6F3 /* Project object */;
 }

+ 4 - 1
Package.swift

@@ -13,8 +13,11 @@ let package = Package(
       targets: ["CryptoSwift"]
     )
   ],
+  dependencies: [
+    .package(url: "https://github.com/attaswift/BigInt.git", from: "5.2.1")
+  ],
   targets: [
-    .target(name: "CryptoSwift"),
+    .target(name: "CryptoSwift", dependencies: ["BigInt"]),
     .testTarget(name: "CryptoSwiftTests", dependencies: ["CryptoSwift"]),
     .testTarget(name: "TestsPerformance", dependencies: ["CryptoSwift"])
   ],

+ 0 - 187
Sources/CryptoSwift/GiantUInt.swift

@@ -1,187 +0,0 @@
-//
-//  CryptoSwift
-//
-//  Copyright (C) 2014-2021 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.
-//
-
-precedencegroup PowerPrecedence { higherThan: MultiplicationPrecedence }
-infix operator ^^ : PowerPrecedence
-
-public struct GiantUInt: Equatable, Comparable, ExpressibleByIntegerLiteral, ExpressibleByArrayLiteral {
-  
-  // Properties
-  
-  public let bytes: Array<UInt8>
-  
-  // Initialization
-  
-  public init(_ raw: Array<UInt8>) {
-    var bytes = raw
-    
-    while bytes.last == 0 {
-      bytes.removeLast()
-    }
-    
-    self.bytes = bytes
-  }
-  
-  // ExpressibleByIntegerLiteral
-  
-  public typealias IntegerLiteralType = UInt8
-  
-  public init(integerLiteral value: UInt8) {
-    self = GiantUInt([value])
-  }
-  
-  // ExpressibleByArrayLiteral
-  
-  public typealias ArrayLiteralElement = UInt8
-  
-  public init(arrayLiteral elements: UInt8...) {
-    self = GiantUInt(elements)
-  }
-    
-  // Equatable
-  
-  public static func == (lhs: GiantUInt, rhs: GiantUInt) -> Bool {
-    lhs.bytes == rhs.bytes
-  }
-  
-  // Comparable
-  
-  public static func < (rhs: GiantUInt, lhs: GiantUInt) -> Bool {
-    for i in (0 ..< max(rhs.bytes.count, lhs.bytes.count)).reversed() {
-      let r = rhs.bytes[safe: i] ?? 0
-      let l = lhs.bytes[safe: i] ?? 0
-      if r < l {
-        return true
-      } else if r > l {
-        return false
-      }
-    }
-    
-    return false
-  }
-  
-  // Operations
-  
-  public static func + (rhs: GiantUInt, lhs: GiantUInt) -> GiantUInt {
-    var bytes = [UInt8]()
-    var r: UInt8 = 0
-    
-    for i in 0 ..< max(rhs.bytes.count, lhs.bytes.count) {
-      let res = UInt16(rhs.bytes[safe: i] ?? 0) + UInt16(lhs.bytes[safe: i] ?? 0) + UInt16(r)
-      r = UInt8(res >> 8)
-      bytes.append(UInt8(res & 0xff))
-    }
-    
-    if r != 0 {
-      bytes.append(r)
-    }
-    
-    return GiantUInt(bytes)
-  }
-  
-  public static func - (rhs: GiantUInt, lhs: GiantUInt) -> GiantUInt {
-    var bytes = [UInt8]()
-    var r: UInt8 = 0
-    
-    for i in 0 ..< max(rhs.bytes.count, lhs.bytes.count) {
-      let rhsb = UInt16(rhs.bytes[safe: i] ?? 0)
-      let lhsb = UInt16(lhs.bytes[safe: i] ?? 0) + UInt16(r)
-      r = UInt8(rhsb < lhsb ? 1 : 0)
-      let res = (UInt16(r) << 8) + rhsb - lhsb
-      bytes.append(UInt8(res & 0xff))
-    }
-    
-    if r != 0 {
-      bytes.append(r)
-    }
-    
-    return GiantUInt(bytes)
-  }
-  
-  public static func * (rhs: GiantUInt, lhs: GiantUInt) -> GiantUInt {
-    var offset = 0
-    var sum = [GiantUInt]()
-    
-    for rbyte in rhs.bytes {
-      var bytes = [UInt8](repeating: 0, count: offset)
-      var r: UInt8 = 0
-      
-      for lbyte in lhs.bytes {
-        let res = UInt16(rbyte) * UInt16(lbyte) + UInt16(r)
-        r = UInt8(res >> 8)
-        bytes.append(UInt8(res & 0xff))
-      }
-      
-      if r != 0 {
-        bytes.append(r)
-      }
-      
-      sum.append(GiantUInt(bytes))
-      offset += 1
-    }
-    
-    return sum.reduce(0, +)
-  }
-  
-  public static func % (rhs: GiantUInt, lhs: GiantUInt) -> GiantUInt {
-    var remainder = rhs
-    
-    // This needs serious optimization (but works)
-    while remainder >= lhs {
-      remainder = remainder - lhs
-    }
-  
-    return remainder
-  }
-  
-  static func ^^ (rhs: GiantUInt, lhs: GiantUInt) -> GiantUInt {
-    let count = lhs.bytes.count
-    var result = GiantUInt([1])
-    
-    for iByte in 0 ..< count {
-      let byte = lhs.bytes[iByte]
-      for i in 0 ..< 8 {
-        if iByte != count - 1 || byte >> i > 0 {
-          result = result * result
-          if (byte >> i) & 1 == 1 {
-            result = result * rhs
-          }
-        }
-      }
-    }
-    
-    return result
-  }
-  
-  public static func exponentiateWithModulus(rhs: GiantUInt, lhs: GiantUInt, modulus: GiantUInt) -> GiantUInt {
-    let count = lhs.bytes.count
-    var result = GiantUInt([1])
-    
-    for iByte in 0 ..< count {
-      let byte = lhs.bytes[iByte]
-      for i in 0 ..< 8 {
-        if iByte != count - 1 || byte >> i > 0 {
-          result = (result * result) % modulus
-          if (byte >> i) & 1 == 1 {
-            result = (result * rhs) % modulus
-          }
-        }
-      }
-    }
-    
-    return result
-  }
-  
-}

+ 16 - 9
Sources/CryptoSwift/RSA.swift

@@ -13,6 +13,13 @@
 //  - This notice may not be removed or altered from any source or binary distribution.
 //
 
+// Foundation is required for `Data` to be found
+import Foundation
+
+// This is https://github.com/attaswift/BigInt
+// It allows fast calculation for RSA big numbers
+import BigInt
+
 public final class RSA {
   
   public enum Error: Swift.Error {
@@ -21,13 +28,13 @@ public final class RSA {
   }
   
   /// RSA Modulus
-  public let n: GiantUInt
+  public let n: BigUInt
   
   /// RSA Public Exponent
-  public let e: GiantUInt
+  public let e: BigUInt
   
   /// RSA Private Exponent
-  public let d: GiantUInt?
+  public let d: BigUInt?
   
   /// The size of the modulus, in bits
   public let keySize: Int
@@ -37,12 +44,12 @@ public final class RSA {
   ///   - n: The RSA Modulus
   ///   - e: The RSA Public Exponent
   ///   - d: The RSA Private Exponent (or nil if unknown, e.g. if only public key is known)
-  public init(n: GiantUInt, e: GiantUInt, d: GiantUInt? = nil) {
+  public init(n: BigUInt, e: BigUInt, d: BigUInt? = nil) {
     self.n = n
     self.e = e
     self.d = d
     
-    self.keySize = n.bytes.count * 8
+    self.keySize = n.bitWidth
   }
   
   /// Initialize with RSA parameters
@@ -52,9 +59,9 @@ public final class RSA {
   ///   - d: The RSA Private Exponent (or nil if unknown, e.g. if only public key is known)
   public convenience init(n: Array<UInt8>, e: Array<UInt8>, d: Array<UInt8>? = nil) {
     if let d = d {
-      self.init(n: GiantUInt(n), e: GiantUInt(e), d: GiantUInt(d))
+      self.init(n: BigUInt(Data(n)), e: BigUInt(Data(e)), d: BigUInt(Data(d)))
     } else {
-      self.init(n: GiantUInt(n), e: GiantUInt(e))
+      self.init(n: BigUInt(Data(n)), e: BigUInt(Data(e)))
     }
   }
   
@@ -71,7 +78,7 @@ extension RSA: Cipher {
   @inlinable
   public func encrypt(_ bytes: ArraySlice<UInt8>) throws -> Array<UInt8> {
     // Calculate encrypted data
-    return GiantUInt.exponentiateWithModulus(rhs: GiantUInt(Array(bytes)), lhs: e, modulus: n).bytes
+    return BigUInt(Data(bytes)).power(e, modulus: n).serialize().bytes
   }
 
   @inlinable
@@ -82,7 +89,7 @@ extension RSA: Cipher {
     }
     
     // Calculate decrypted data
-    return GiantUInt.exponentiateWithModulus(rhs: GiantUInt(Array(bytes)), lhs: d, modulus: n).bytes
+    return BigUInt(Data(bytes)).power(d, modulus: n).serialize().bytes
   }
   
 }

+ 0 - 89
Tests/CryptoSwiftTests/GiantUIntTests.swift

@@ -1,89 +0,0 @@
-//
-// CryptoSwift
-//
-//  Copyright (C) 2014-2021 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
-import XCTest
-@testable import CryptoSwift
-
-final class GiantUIntTests: XCTestCase {
-  
-  func testComparable() {
-    XCTAssertTrue(GiantUInt([1, 2, 3]) == GiantUInt([1, 2, 3]), "equality check failed")
-    XCTAssertTrue(GiantUInt([1, 2, 3]) > GiantUInt([1, 3, 2]), "greater than check failed")
-    XCTAssertTrue(GiantUInt([1, 3, 2]) < GiantUInt([1, 2, 3]), "lower than check failed")
-  }
-  
-  func testAddition() {
-    let a = GiantUInt([1]) + GiantUInt([1])
-    XCTAssertEqual(a, GiantUInt([2]), "simple addition failed")
-    
-    let b = GiantUInt([200]) + GiantUInt([200])
-    XCTAssertEqual(b, GiantUInt([144, 1]), "addition with retenue failed")
-    
-    let c = GiantUInt([200, 200]) + GiantUInt([200, 200])
-    XCTAssertEqual(c, GiantUInt([144, 145, 1]), "addition with double retenue failed")
-  }
-  
-  func testSubtraction() {
-    let a = GiantUInt([2]) - GiantUInt([1])
-    XCTAssertEqual(a, GiantUInt([1]), "simple subtraction failed")
-    
-    let b = GiantUInt([0, 1]) - GiantUInt([255])
-    XCTAssertEqual(b, GiantUInt([1]), "subtraction with retenue failed")
-  }
-  
-  func testMultiplication() {
-    let a = GiantUInt([2]) * GiantUInt([2])
-    XCTAssertEqual(a, GiantUInt([4]), "simple multiplication failed")
-    
-    let b = GiantUInt([200]) * GiantUInt([200])
-    XCTAssertEqual(b, GiantUInt([64, 156]), "multiplication with retenue failed")
-    
-    let c = GiantUInt([200, 200]) * GiantUInt([200, 200])
-    XCTAssertEqual(c, GiantUInt([64, 28, 121, 157]), "multiplication with double retenue failed")
-  }
-  
-  func testExponentiation() {
-    let a = GiantUInt([3]) ^^ GiantUInt([7])
-    XCTAssertEqual(a, GiantUInt([139, 8]), "simple exponentiation failed")
-  }
-  
-  func testModulus() {
-    let a = GiantUInt([10]) % GiantUInt([3])
-    XCTAssertEqual(a, GiantUInt([1]), "simple modulus failed")
-  }
-  
-  func testExponentiationWithModulus() {
-    let a = GiantUInt.exponentiateWithModulus(rhs: GiantUInt([3]), lhs: GiantUInt([7]), modulus: GiantUInt([0, 1]))
-    XCTAssertEqual(a, GiantUInt([139]), "simple exponentiation with modulus failed")
-  }
-  
-}
-
-extension GiantUIntTests {
-  static func allTests() -> [(String, (GiantUIntTests) -> () -> Void)] {
-    let tests = [
-      ("testComparable", testComparable),
-      ("testAddition", testAddition),
-      ("testSubtraction", testSubtraction),
-      ("testMultiplication", testMultiplication),
-      ("testExponentiation", testExponentiation),
-      ("testModulus", testModulus),
-      ("testExponentiationWithModulus", testExponentiationWithModulus)
-    ]
-
-    return tests
-  }
-}

+ 41 - 84
Tests/CryptoSwiftTests/RSATests.swift

@@ -29,114 +29,71 @@ final class RSATests: XCTestCase {
     let n: Array<UInt8> = [33]
     let e: Array<UInt8> = [3]
     let d: Array<UInt8> = [7]
-    let EM: Array<UInt8> = [4]
-    let S: Array<UInt8> = [31]
+    let message: Array<UInt8> = [4]
+    let expected: Array<UInt8> = [31]
     
     let rsa = RSA(n: n, e: e, d: d)
-    XCTAssertEqual(rsa.keySize, 8, "key size is not correct")
+    XCTAssertEqual(rsa.keySize, 6, "key size is not correct")
     
-    let encrypted = try! rsa.encrypt(EM)
-    XCTAssertEqual(encrypted, S, "small encrypt failed")
+    let encrypted = try! rsa.encrypt(message)
+    XCTAssertEqual(encrypted, expected, "small encrypt failed")
     
-    let decrypted = try! rsa.decrypt(S)
-    XCTAssertEqual(decrypted, EM, "small decrypt failed")
+    let decrypted = try! rsa.decrypt(encrypted)
+    XCTAssertEqual(decrypted, message, "small decrypt failed")
   }
 
   func testRSA1() {
     /*
-     * Taken from https://csrc.nist.gov/Projects/cryptographic-algorithm-validation-program
+     * Taken from http://cryptomanager.com/tv.html
      *
-     * RSA PKCS1-v1.5 RSASP1 (FIPS 186-4)
+     * 1. 1024-bit RSA bare exponentiation
      */
     
     let n: Array<UInt8> = [
-      0xba, 0xd4, 0x7a, 0x84, 0xc1, 0x78, 0x2e, 0x4d, 0xbd, 0xd9, 0x13, 0xf2, 0xa2, 0x61, 0xfc, 0x8b,
-      0x65, 0x83, 0x84, 0x12, 0xc6, 0xe4, 0x5a, 0x20, 0x68, 0xed, 0x6d, 0x7f, 0x16, 0xe9, 0xcd, 0xf4,
-      0x46, 0x2b, 0x39, 0x11, 0x95, 0x63, 0xca, 0xfb, 0x74, 0xb9, 0xcb, 0xf2, 0x5c, 0xfd, 0x54, 0x4b,
-      0xda, 0xe2, 0x3b, 0xff, 0x0e, 0xbe, 0x7f, 0x64, 0x41, 0x04, 0x2b, 0x7e, 0x10, 0x9b, 0x9a, 0x8a,
-      0xfa, 0xa0, 0x56, 0x82, 0x1e, 0xf8, 0xef, 0xaa, 0xb2, 0x19, 0xd2, 0x1d, 0x67, 0x63, 0x48, 0x47,
-      0x85, 0x62, 0x2d, 0x91, 0x8d, 0x39, 0x5a, 0x2a, 0x31, 0xf2, 0xec, 0xe8, 0x38, 0x5a, 0x81, 0x31,
-      0xe5, 0xff, 0x14, 0x33, 0x14, 0xa8, 0x2e, 0x21, 0xaf, 0xd7, 0x13, 0xba, 0xe8, 0x17, 0xcc, 0x0e,
-      0xe3, 0x51, 0x4d, 0x48, 0x39, 0x00, 0x7c, 0xcb, 0x55, 0xd6, 0x84, 0x09, 0xc9, 0x7a, 0x18, 0xab,
-      0x62, 0xfa, 0x6f, 0x9f, 0x89, 0xb3, 0xf9, 0x4a, 0x27, 0x77, 0xc4, 0x7d, 0x61, 0x36, 0x77, 0x5a,
-      0x56, 0xa9, 0xa0, 0x12, 0x7f, 0x68, 0x24, 0x70, 0xbe, 0xf8, 0x31, 0xfb, 0xec, 0x4b, 0xcd, 0x7b,
-      0x50, 0x95, 0xa7, 0x82, 0x3f, 0xd7, 0x07, 0x45, 0xd3, 0x7d, 0x1b, 0xf7, 0x2b, 0x63, 0xc4, 0xb1,
-      0xb4, 0xa3, 0xd0, 0x58, 0x1e, 0x74, 0xbf, 0x9a, 0xde, 0x93, 0xcc, 0x46, 0x14, 0x86, 0x17, 0x55,
-      0x39, 0x31, 0xa7, 0x9d, 0x92, 0xe9, 0xe4, 0x88, 0xef, 0x47, 0x22, 0x3e, 0xe6, 0xf6, 0xc0, 0x61,
-      0x88, 0x4b, 0x13, 0xc9, 0x06, 0x5b, 0x59, 0x11, 0x39, 0xde, 0x13, 0xc1, 0xea, 0x29, 0x27, 0x49,
-      0x1e, 0xd0, 0x0f, 0xb7, 0x93, 0xcd, 0x68, 0xf4, 0x63, 0xf5, 0xf6, 0x4b, 0xaa, 0x53, 0x91, 0x6b,
-      0x46, 0xc8, 0x18, 0xab, 0x99, 0x70, 0x65, 0x57, 0xa1, 0xc2, 0xd5, 0x0d, 0x23, 0x25, 0x77, 0xd1
+      0xF0, 0xC4, 0x2D, 0xB8, 0x48, 0x6F, 0xEB, 0x95, 0x95, 0xD8, 0xC7, 0x8F, 0x90, 0x8D, 0x04, 0xA9,
+      0xB6, 0xC8, 0xC7, 0x7A, 0x36, 0x10, 0x5B, 0x1B, 0xF2, 0x75, 0x53, 0x77, 0xA6, 0x89, 0x3D, 0xC4,
+      0x38, 0x3C, 0x54, 0xEC, 0x6B, 0x52, 0x62, 0xE5, 0x68, 0x8E, 0x5F, 0x9D, 0x9D, 0xD1, 0x64, 0x97,
+      0xD0, 0xE3, 0xEA, 0x83, 0x3D, 0xEE, 0x2C, 0x8E, 0xBC, 0xD1, 0x43, 0x83, 0x89, 0xFC, 0xCA, 0x8F,
+      0xED, 0xE7, 0xA8, 0x8A, 0x81, 0x25, 0x7E, 0x8B, 0x27, 0x09, 0xC4, 0x94, 0xD4, 0x2F, 0x72, 0x3D,
+      0xEC, 0x2E, 0x0B, 0x5C, 0x09, 0x73, 0x1C, 0x55, 0x0D, 0xCC, 0x9D, 0x7E, 0x75, 0x25, 0x89, 0x89,
+      0x1C, 0xBB, 0xC3, 0x02, 0x13, 0x07, 0xDD, 0x91, 0x8E, 0x10, 0x0B, 0x34, 0xC0, 0x14, 0xA5, 0x59,
+      0xE0, 0xE1, 0x82, 0xAF, 0xB2, 0x1A, 0x72, 0xB3, 0x07, 0xCC, 0x39, 0x5D, 0xEC, 0x99, 0x57, 0x47
     ]
     let e: Array<UInt8> = [
       0x01, 0x00, 0x01
     ]
     let d: Array<UInt8> = [
-      0x40, 0xd6, 0x0f, 0x24, 0xb6, 0x1d, 0x76, 0x78, 0x3d, 0x3b, 0xb1, 0xdc, 0x00, 0xb5, 0x5f, 0x96,
-      0xa2, 0xa6, 0x86, 0xf5, 0x9b, 0x37, 0x50, 0xfd, 0xb1, 0x5c, 0x40, 0x25, 0x1c, 0x37, 0x0c, 0x65,
-      0xca, 0xda, 0x22, 0x26, 0x73, 0x81, 0x1b, 0xc6, 0xb3, 0x05, 0xed, 0x7c, 0x90, 0xff, 0xcb, 0x3a,
-      0xbd, 0xdd, 0xc8, 0x33, 0x66, 0x12, 0xff, 0x13, 0xb4, 0x2a, 0x75, 0xcb, 0x7c, 0x88, 0xfb, 0x93,
-      0x62, 0x91, 0xb5, 0x23, 0xd8, 0x0a, 0xcc, 0xe5, 0xa0, 0x84, 0x2c, 0x72, 0x4e, 0xd8, 0x5a, 0x13,
-      0x93, 0xfa, 0xf3, 0xd4, 0x70, 0xbd, 0xa8, 0x08, 0x3f, 0xa8, 0x4d, 0xc5, 0xf3, 0x14, 0x99, 0x84,
-      0x4f, 0x0c, 0x7c, 0x1e, 0x93, 0xfb, 0x1f, 0x73, 0x4a, 0x5a, 0x29, 0xfb, 0x31, 0xa3, 0x5c, 0x8a,
-      0x08, 0x22, 0x45, 0x5f, 0x1c, 0x85, 0x0a, 0x49, 0xe8, 0x62, 0x97, 0x14, 0xec, 0x6a, 0x26, 0x57,
-      0xef, 0xe7, 0x5e, 0xc1, 0xca, 0x6e, 0x62, 0xf9, 0xa3, 0x75, 0x6c, 0x9b, 0x20, 0xb4, 0x85, 0x5b,
-      0xdc, 0x9a, 0x3a, 0xb5, 0x8c, 0x43, 0xd8, 0xaf, 0x85, 0xb8, 0x37, 0xa7, 0xfd, 0x15, 0xaa, 0x11,
-      0x49, 0xc1, 0x19, 0xcf, 0xe9, 0x60, 0xc0, 0x5a, 0x9d, 0x4c, 0xea, 0x69, 0xc9, 0xfb, 0x6a, 0x89,
-      0x71, 0x45, 0x67, 0x48, 0x82, 0xbf, 0x57, 0x24, 0x1d, 0x77, 0xc0, 0x54, 0xdc, 0x4c, 0x94, 0xe8,
-      0x34, 0x9d, 0x37, 0x62, 0x96, 0x13, 0x7e, 0xb4, 0x21, 0x68, 0x61, 0x59, 0xcb, 0x87, 0x8d, 0x15,
-      0xd1, 0x71, 0xed, 0xa8, 0x69, 0x28, 0x34, 0xaf, 0xc8, 0x71, 0x98, 0x8f, 0x20, 0x3f, 0xc8, 0x22,
-      0xc5, 0xdc, 0xee, 0x7f, 0x6c, 0x48, 0xdf, 0x66, 0x3e, 0xa3, 0xdc, 0x75, 0x5e, 0x7d, 0xc0, 0x6a,
-      0xeb, 0xd4, 0x1d, 0x05, 0xf1, 0xca, 0x28, 0x91, 0xe2, 0x67, 0x97, 0x83, 0x24, 0x4d, 0x06, 0x8f
+      0x24, 0x89, 0x10, 0x8B, 0x0B, 0x6A, 0xF8, 0x6B, 0xED, 0x9E, 0x44, 0xC2, 0x33, 0x64, 0x42, 0xD5,
+      0xE2, 0x27, 0xDB, 0xA5, 0x5E, 0xF8, 0xE2, 0x6A, 0x7E, 0x43, 0x71, 0x94, 0x11, 0x90, 0x77, 0xF0,
+      0x03, 0xBC, 0x9C, 0x02, 0x78, 0x52, 0xBB, 0x31, 0x26, 0xC9, 0x9C, 0x16, 0xD5, 0xF1, 0x05, 0x7B,
+      0xC8, 0x36, 0x1D, 0xCB, 0x26, 0xA5, 0xB2, 0xDB, 0x42, 0x29, 0xDB, 0x3D, 0xE5, 0xBD, 0x97, 0x9B,
+      0x2E, 0x59, 0x7D, 0x19, 0x16, 0xD7, 0xBB, 0xC9, 0x27, 0x46, 0xFC, 0x07, 0x59, 0x5C, 0x76, 0xB4,
+      0x4B, 0x39, 0xA4, 0x76, 0xA6, 0x5C, 0x86, 0xF0, 0x86, 0xDC, 0x92, 0x83, 0xCA, 0x6D, 0x1E, 0xEF,
+      0xC1, 0x49, 0x15, 0x98, 0x2F, 0x9C, 0x4C, 0xED, 0x5F, 0x62, 0xA9, 0xFF, 0x3B, 0xE2, 0x42, 0x18,
+      0xA9, 0x93, 0x57, 0xB5, 0xB6, 0x5C, 0x3B, 0x10, 0xAE, 0xB3, 0x67, 0xE9, 0x11, 0xEB, 0x9E, 0x21
     ]
-    /*
-    let EM: Array<UInt8> = [
-      0x70, 0x99, 0x2c, 0x9d, 0x95, 0xa4, 0x90, 0x8d, 0x2a, 0x94, 0xb3, 0xab, 0x9f, 0xa1, 0xcd, 0x64,
-      0x3f, 0x12, 0x0e, 0x32, 0x6f, 0x9d, 0x78, 0x08, 0xaf, 0x50, 0xca, 0xc4, 0x2c, 0x4b, 0x0b, 0x4e,
-      0xeb, 0x7f, 0x0d, 0x4d, 0xf3, 0x03, 0xa5, 0x68, 0xfb, 0xfb, 0x82, 0xb0, 0xf5, 0x83, 0x00, 0xd2,
-      0x53, 0x57, 0x64, 0x57, 0x21, 0xbb, 0x71, 0x86, 0x1c, 0xaf, 0x81, 0xb2, 0x7a, 0x56, 0x08, 0x2c,
-      0x80, 0xa1, 0x46, 0x49, 0x9f, 0xb4, 0xea, 0xb5, 0xbd, 0xe4, 0x49, 0x3f, 0x5d, 0x00, 0xf1, 0xa4,
-      0x37, 0xbb, 0xc3, 0x60, 0xdf, 0xcd, 0x80, 0x56, 0xfe, 0x6b, 0xe1, 0x0e, 0x60, 0x8a, 0xdb, 0x30,
-      0xb6, 0xc2, 0xf7, 0x65, 0x24, 0x28, 0xb8, 0xd3, 0x2d, 0x36, 0x29, 0x45, 0x98, 0x2a, 0x46, 0x58,
-      0x5d, 0x21, 0x02, 0xef, 0x79, 0x95, 0xa8, 0xba, 0x6e, 0x8a, 0xd8, 0xfd, 0x16, 0xbd, 0x7a, 0xe8,
-      0xf5, 0x3c, 0x3d, 0x7f, 0xcf, 0xba, 0x29, 0x0b, 0x57, 0xce, 0x7f, 0x8f, 0x09, 0xc8, 0x28, 0xd6,
-      0xf2, 0xd3, 0xce, 0x56, 0xf1, 0x31, 0xbd, 0x94, 0x61, 0xe5, 0x66, 0x7e, 0x5b, 0x73, 0xed, 0xac,
-      0x77, 0xf5, 0x04, 0xda, 0xc4, 0xf2, 0x02, 0xa9, 0x57, 0x0e, 0xb4, 0x51, 0x5b, 0x2b, 0xf5, 0x16,
-      0x40, 0x7d, 0xb8, 0x31, 0x51, 0x8d, 0xb8, 0xa2, 0x08, 0x3e, 0xc7, 0x01, 0xe8, 0xfd, 0x38, 0x7c,
-      0x43, 0x0b, 0xb1, 0xa7, 0x2d, 0xec, 0xa5, 0xb4, 0x9d, 0x42, 0x9c, 0xf9, 0xde, 0xb0, 0x9c, 0xc4,
-      0x51, 0x8d, 0xc5, 0xf5, 0x7c, 0x08, 0x9a, 0xa2, 0xd3, 0x42, 0x0e, 0x56, 0x7e, 0x73, 0x21, 0x02,
-      0xc2, 0xc9, 0x2b, 0x88, 0xa0, 0x7c, 0x69, 0xd7, 0x09, 0x17, 0x14, 0x0a, 0xb3, 0x82, 0x3c, 0x63,
-      0xf3, 0x12, 0xd3, 0xf1, 0x1f, 0xa8, 0x7b, 0xa2, 0x9d, 0xa3, 0xc7, 0x22, 0x4b, 0x4f, 0xb4, 0xbc
+    let message: Array<UInt8> = [
+      0x11, 0x22, 0x33, 0x44
     ]
-    let S: Array<UInt8> = [
-      0x7e, 0x65, 0xb9, 0x98, 0xa0, 0x5f, 0x62, 0x6b, 0x02, 0x8c, 0x75, 0xdc, 0x3f, 0xbf, 0x98, 0x96,
-      0x3d, 0xce, 0x66, 0xd0, 0xf4, 0xc3, 0xae, 0x42, 0x37, 0xcf, 0xf3, 0x04, 0xd8, 0x4d, 0x88, 0x36,
-      0xcb, 0x6b, 0xad, 0x9a, 0xc8, 0x6f, 0x9d, 0x1b, 0x8a, 0x28, 0xdd, 0x70, 0x40, 0x47, 0x88, 0xb8,
-      0x69, 0xd2, 0x42, 0x9f, 0x1e, 0xc0, 0x66, 0x3e, 0x51, 0xb7, 0x53, 0xf7, 0x45, 0x1c, 0x6b, 0x46,
-      0x45, 0xd9, 0x91, 0x26, 0xe4, 0x57, 0xc1, 0xda, 0xc4, 0x95, 0x51, 0xd8, 0x6a, 0x8a, 0x97, 0x4a,
-      0x31, 0x31, 0xe9, 0xb3, 0x71, 0xd5, 0xc2, 0x14, 0xcc, 0x9f, 0xf2, 0x40, 0xc2, 0x99, 0xbd, 0x0e,
-      0x62, 0xdb, 0xc7, 0xa9, 0xa2, 0xda, 0xd9, 0xfa, 0x54, 0x04, 0xad, 0xb0, 0x06, 0x32, 0xd3, 0x63,
-      0x32, 0xd5, 0xbe, 0x61, 0x06, 0xe9, 0xe6, 0xec, 0x81, 0xca, 0xc4, 0x5c, 0xd3, 0x39, 0xcc, 0x87,
-      0xab, 0xbe, 0x7f, 0x89, 0x43, 0x08, 0x00, 0xe1, 0x6e, 0x03, 0x2a, 0x66, 0x21, 0x0b, 0x25, 0xe9,
-      0x26, 0xed, 0xa2, 0x43, 0xd9, 0xf0, 0x99, 0x55, 0x49, 0x6d, 0xdb, 0xc7, 0x7e, 0xf7, 0x4f, 0x17,
-      0xfe, 0xe4, 0x1c, 0x44, 0x35, 0xe7, 0x8b, 0x46, 0x96, 0x5b, 0x71, 0x3d, 0x72, 0xce, 0x8a, 0x31,
-      0xaf, 0x64, 0x15, 0x38, 0xad, 0xd3, 0x87, 0xfe, 0xdf, 0xd8, 0x8b, 0xb2, 0x2a, 0x42, 0xeb, 0x3b,
-      0xda, 0x40, 0xf7, 0x2e, 0xca, 0xd9, 0x41, 0xdb, 0xff, 0xdd, 0x47, 0xb3, 0xe7, 0x77, 0x37, 0xda,
-      0x74, 0x15, 0x53, 0xa4, 0x5b, 0x63, 0x0d, 0x07, 0x0b, 0xcc, 0x52, 0x05, 0x80, 0x4b, 0xf8, 0x0e,
-      0xe2, 0xd5, 0x16, 0x12, 0x87, 0x5d, 0xbc, 0x47, 0x96, 0x96, 0x00, 0x52, 0xf1, 0x68, 0x7e, 0x00,
-      0x74, 0x00, 0x7e, 0x6a, 0x33, 0xab, 0x8b, 0x20, 0x85, 0xc0, 0x33, 0xf9, 0x89, 0x2b, 0x6f, 0x74
+    let expected: Array<UInt8> = [
+      0x50, 0x5B, 0x09, 0xBD, 0x5D, 0x0E, 0x66, 0xD7, 0xC8, 0x82, 0x9F, 0x5B, 0x47, 0x3E, 0xD3, 0x4D,
+      0xB5, 0xCF, 0xDB, 0xB5, 0xD5, 0x8C, 0xE7, 0x83, 0x29, 0xC8, 0xBF, 0x85, 0x20, 0xE4, 0x86, 0xD3,
+      0xC4, 0xCF, 0x9B, 0x70, 0xC6, 0x34, 0x65, 0x94, 0x35, 0x80, 0x80, 0xF4, 0x3F, 0x47, 0xEE, 0x86,
+      0x3C, 0xFA, 0xF2, 0xA2, 0xE5, 0xF0, 0x3D, 0x1E, 0x13, 0xD6, 0xFE, 0xC5, 0x7D, 0xFB, 0x1D, 0x55,
+      0x22, 0x24, 0xC4, 0x61, 0xDA, 0x41, 0x1C, 0xFE, 0x5D, 0x0B, 0x05, 0xBA, 0x87, 0x7E, 0x3A, 0x42,
+      0xF6, 0xDE, 0x4D, 0xA4, 0x6A, 0x96, 0x5C, 0x9B, 0x69, 0x5E, 0xE2, 0xD5, 0x0E, 0x40, 0x08, 0x94,
+      0x06, 0x1C, 0xB0, 0xA2, 0x1C, 0xA3, 0xA5, 0x24, 0xB4, 0x07, 0xE9, 0xFF, 0xBA, 0x87, 0xFC, 0x96,
+      0x6B, 0x3B, 0xA9, 0x45, 0x90, 0x84, 0x9A, 0xEB, 0x90, 0x8A, 0xAF, 0xF4, 0xC7, 0x19, 0xC2, 0xE4
     ]
-    */
     
     let rsa = RSA(n: n, e: e, d: d)
-    XCTAssertEqual(rsa.keySize, 2048, "key size is not correct")
-    
-    // Note: For now, Integer computation is too slow to execute this part
+    XCTAssertEqual(rsa.keySize, 1024, "key size is not correct")
     
-    //let encrypted = try! rsa.encrypt(EM)
-    //XCTAssertEqual(encrypted, S, "encrypt failed")
+    let encrypted = try! rsa.encrypt(message)
+    XCTAssertEqual(encrypted, expected, "encrypt failed")
     
-    //let decrypted = try! rsa.decrypt(S)
-    //XCTAssertEqual(decrypted, EM, "decrypt failed")
+    let decrypted = try! rsa.decrypt(encrypted)
+    XCTAssertEqual(decrypted, message, "decrypt failed")
   }
 
 }