Sfoglia il codice sorgente

Merge pull request #1027 from LabMobi/RSA-PKCS1-SHA3-signature-verification

Rsa pkcs1 sha3 signature verification
Marcin Krzyzanowski 2 anni fa
parent
commit
037646a371

+ 4 - 0
CONTRIBUTORS.txt

@@ -56,6 +56,7 @@ organizations who have contributed source code to CryptoSwift.
 - John Hammerlund <johnhammerlund@gmail.com>
 - Jonas Obrist <ojiidotch@gmail.com>
 - K.K. POON <noopkk@gmail.com>
+- Katrin Annuk <katrin.annuk@lab.mobi>
 - Keith Smiley <keithbsmiley@gmail.com>
 - Koray Koska <koray@koska.at>
 - Kyle Fuller <kyle@fuller.li>
@@ -72,6 +73,7 @@ organizations who have contributed source code to CryptoSwift.
 - Matias Cudich <mcudich@gmail.com>
 - Matias Piipari <matias.piipari@gmail.com>
 - Matthew Chung <matthewchung74@gmail.com>
+- Matthias Geihs <matthias@geihs.de>
 - Maxence Mottard <mottard.maxence@gmail.com>
 - Michael Ledin <m.ledin@appheads.ru>
 - Michael Redig <mredig@gmail.com>
@@ -112,6 +114,8 @@ organizations who have contributed source code to CryptoSwift.
 - Xavier Matos <matos.xav@gmail.com>
 - Yannick Loriot <yannick.loriot@gmail.com>
 - Yury Lapitsky <yury.lapitsky@gmail.com>
+- Zsombor Szabo <zsombor@gmail.com>
+- Zsombor Szabo <zsombor@proxy.com>
 - akreutz <27BBsan08!>
 - jose <nextgenappsllc@gmail.com>
 - mrahmiao <mrahmiao@gmail.com>

+ 5 - 1
CryptoSwift.xcodeproj/project.pbxproj

@@ -3,7 +3,7 @@
 	archiveVersion = 1;
 	classes = {
 	};
-	objectVersion = 52;
+	objectVersion = 54;
 	objects = {
 
 /* Begin PBXBuildFile section */
@@ -14,6 +14,7 @@
 		1467460F2017BB3600DF04ED /* AEAD.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1467460E2017BB3600DF04ED /* AEAD.swift */; };
 		35F3E51C23BF9A6700A024A1 /* OCB.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35F3E51B23BF9A6700A024A1 /* OCB.swift */; };
 		42012783267A6F1C00F82506 /* ISO10126Padding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42012782267A6F1C00F82506 /* ISO10126Padding.swift */; };
+		5431FD5B2B021476001DEE77 /* SignatureVerificationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5431FD592B021470001DEE77 /* SignatureVerificationTests.swift */; };
 		674A736F1BF5D85B00866C5B /* RabbitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 674A736E1BF5D85B00866C5B /* RabbitTests.swift */; };
 		6A7CDEED26CD1E4C00FFB1AF /* RSATests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A7CDEEC26CD1E4C00FFB1AF /* RSATests.swift */; };
 		6AC893F626DB950F00F7E787 /* Addition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AC893E026DB950C00F7E787 /* Addition.swift */; };
@@ -240,6 +241,7 @@
 		35F3E51B23BF9A6700A024A1 /* OCB.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OCB.swift; sourceTree = "<group>"; };
 		35F3E51D23BF9AD300A024A1 /* AESOCBTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AESOCBTests.swift; sourceTree = "<group>"; };
 		42012782267A6F1C00F82506 /* ISO10126Padding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ISO10126Padding.swift; sourceTree = "<group>"; };
+		5431FD592B021470001DEE77 /* SignatureVerificationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignatureVerificationTests.swift; sourceTree = "<group>"; };
 		674A736E1BF5D85B00866C5B /* RabbitTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RabbitTests.swift; sourceTree = "<group>"; };
 		6A7CDEEC26CD1E4C00FFB1AF /* RSATests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSATests.swift; sourceTree = "<group>"; };
 		6AC893E026DB950C00F7E787 /* Addition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Addition.swift; sourceTree = "<group>"; };
@@ -581,6 +583,7 @@
 				75482EA31CB310B7001F66A5 /* PBKDF.swift */,
 				7576F6F6207290F8006688F8 /* PBKDFPerf.swift */,
 				6A7CDEEC26CD1E4C00FFB1AF /* RSATests.swift */,
+				5431FD592B021470001DEE77 /* SignatureVerificationTests.swift */,
 				75C2E76C1D55F097003D2BCA /* Access.swift */,
 				756BFDCA1A82B87300B9D9A4 /* Bridging.h */,
 			);
@@ -1106,6 +1109,7 @@
 				757DA2531A4ED0A4002BA3EF /* PaddingTests.swift in Sources */,
 				14156CE52011422400DDCFBC /* ChaCha20Poly1305Tests.swift in Sources */,
 				757DA2551A4ED408002BA3EF /* AESTests.swift in Sources */,
+				5431FD5B2B021476001DEE77 /* SignatureVerificationTests.swift in Sources */,
 				7594CCBC217A76DC0055C95D /* AESCCMTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;

+ 51 - 24
Sources/CryptoSwift/RSA/RSA+Signature.swift

@@ -121,6 +121,12 @@ extension RSA {
     case message_pkcs1v15_SHA512_224
     /// Hashes the raw message using SHA512-256 before signing the data
     case message_pkcs1v15_SHA512_256
+    /// Hashes the raw message using SHA3_256 before signing the data
+    case message_pkcs1v15_SHA3_256
+    /// Hashes the raw message using SHA3_384 before signing the data
+    case message_pkcs1v15_SHA3_384
+    /// Hashes the raw message using SHA3_512 before signing the data
+    case message_pkcs1v15_SHA3_512
     /// This variant isn't supported yet
     case digest_pkcs1v15_RAW
     /// This variant expects that the data to be signed is a valid MD5 Hash Digest
@@ -139,7 +145,13 @@ extension RSA {
     case digest_pkcs1v15_SHA512_224
     /// This variant expects that the data to be signed is a valid SHA512-256 Hash Digest
     case digest_pkcs1v15_SHA512_256
-
+    /// This variant expects that the data to be signed is a valid SHA3-256 Hash Digest
+    case digest_pkcs1v15_SHA3_256
+    /// This variant expects that the data to be signed is a valid SHA3-384 Hash Digest
+    case digest_pkcs1v15_SHA3_384
+    /// This variant expects that the data to be signed is a valid SHA3-512 Hash Digest
+    case digest_pkcs1v15_SHA3_512
+    
     internal var identifier: Array<UInt8> {
       switch self {
         case .raw, .digest_pkcs1v15_RAW: return []
@@ -151,9 +163,12 @@ extension RSA {
         case .message_pkcs1v15_SHA224, .digest_pkcs1v15_SHA224: return Array<UInt8>(arrayLiteral: 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04)
         case .message_pkcs1v15_SHA512_224, .digest_pkcs1v15_SHA512_224: return Array<UInt8>(arrayLiteral: 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x05)
         case .message_pkcs1v15_SHA512_256, .digest_pkcs1v15_SHA512_256: return Array<UInt8>(arrayLiteral: 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x06)
+        case .message_pkcs1v15_SHA3_256, .digest_pkcs1v15_SHA3_256: return Array<UInt8>(arrayLiteral: 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08)
+        case .message_pkcs1v15_SHA3_384, .digest_pkcs1v15_SHA3_384: return Array<UInt8>(arrayLiteral: 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x09)
+        case .message_pkcs1v15_SHA3_512, .digest_pkcs1v15_SHA3_512: return Array<UInt8>(arrayLiteral: 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0A)
       }
     }
-
+    
     internal func calculateHash(_ bytes: Array<UInt8>) -> Array<UInt8> {
       switch self {
         case .message_pkcs1v15_MD5:
@@ -172,20 +187,29 @@ extension RSA {
           return Digest.sha2(bytes, variant: .sha224)
         case .message_pkcs1v15_SHA512_256:
           return Digest.sha2(bytes, variant: .sha256)
+        case .message_pkcs1v15_SHA3_256:
+          return Digest.sha3(bytes, variant: .sha256)
+        case .message_pkcs1v15_SHA3_384:
+          return Digest.sha3(bytes, variant: .sha384)
+        case .message_pkcs1v15_SHA3_512:
+          return Digest.sha3(bytes, variant: .sha512)
         case .raw,
-             .digest_pkcs1v15_RAW,
-             .digest_pkcs1v15_MD5,
-             .digest_pkcs1v15_SHA1,
-             .digest_pkcs1v15_SHA224,
-             .digest_pkcs1v15_SHA256,
-             .digest_pkcs1v15_SHA384,
-             .digest_pkcs1v15_SHA512,
-             .digest_pkcs1v15_SHA512_224,
-             .digest_pkcs1v15_SHA512_256:
-          return bytes
+            .digest_pkcs1v15_RAW,
+            .digest_pkcs1v15_MD5,
+            .digest_pkcs1v15_SHA1,
+            .digest_pkcs1v15_SHA224,
+            .digest_pkcs1v15_SHA256,
+            .digest_pkcs1v15_SHA384,
+            .digest_pkcs1v15_SHA512,
+            .digest_pkcs1v15_SHA512_224,
+            .digest_pkcs1v15_SHA512_256,
+            .digest_pkcs1v15_SHA3_256,
+            .digest_pkcs1v15_SHA3_384,
+            .digest_pkcs1v15_SHA3_512:
+        return bytes
       }
     }
-
+    
     internal func enforceLength(_ bytes: Array<UInt8>, keySizeInBytes: Int) -> Bool {
       switch self {
         case .raw, .digest_pkcs1v15_RAW:
@@ -196,25 +220,28 @@ extension RSA {
           return bytes.count <= 20
         case .digest_pkcs1v15_SHA224:
           return bytes.count <= 28
-        case .digest_pkcs1v15_SHA256:
+        case .digest_pkcs1v15_SHA256, .digest_pkcs1v15_SHA3_256:
           return bytes.count <= 32
-        case .digest_pkcs1v15_SHA384:
+        case .digest_pkcs1v15_SHA384, .digest_pkcs1v15_SHA3_384:
           return bytes.count <= 48
-        case .digest_pkcs1v15_SHA512:
+        case .digest_pkcs1v15_SHA512, .digest_pkcs1v15_SHA3_512:
           return bytes.count <= 64
         case .digest_pkcs1v15_SHA512_224:
           return bytes.count <= 28
         case .digest_pkcs1v15_SHA512_256:
           return bytes.count <= 32
         case .message_pkcs1v15_MD5,
-             .message_pkcs1v15_SHA1,
-             .message_pkcs1v15_SHA224,
-             .message_pkcs1v15_SHA256,
-             .message_pkcs1v15_SHA384,
-             .message_pkcs1v15_SHA512,
-             .message_pkcs1v15_SHA512_224,
-             .message_pkcs1v15_SHA512_256:
-          return true
+            .message_pkcs1v15_SHA1,
+            .message_pkcs1v15_SHA224,
+            .message_pkcs1v15_SHA256,
+            .message_pkcs1v15_SHA384,
+            .message_pkcs1v15_SHA512,
+            .message_pkcs1v15_SHA512_224,
+            .message_pkcs1v15_SHA512_256,
+            .message_pkcs1v15_SHA3_256,
+            .message_pkcs1v15_SHA3_384,
+            .message_pkcs1v15_SHA3_512:
+        return true
       }
     }
 

+ 6 - 0
Tests/CryptoSwiftTests/RSATests.swift

@@ -341,6 +341,9 @@ final class RSATests: XCTestCase {
     XCTAssertThrowsError(try rsa.sign(message, variant: .digest_pkcs1v15_SHA512))
     XCTAssertThrowsError(try rsa.sign(message, variant: .digest_pkcs1v15_SHA512_224))
     XCTAssertThrowsError(try rsa.sign(message, variant: .digest_pkcs1v15_SHA512_256))
+    XCTAssertThrowsError(try rsa.sign(message, variant: .digest_pkcs1v15_SHA3_256))
+    XCTAssertThrowsError(try rsa.sign(message, variant: .digest_pkcs1v15_SHA3_384))
+    XCTAssertThrowsError(try rsa.sign(message, variant: .digest_pkcs1v15_SHA3_512))
 
     // But if we hash the message first, then the signature works as expected...
     XCTAssertNoThrow(try rsa.sign(message, variant: .message_pkcs1v15_SHA1))
@@ -350,6 +353,9 @@ final class RSATests: XCTestCase {
     XCTAssertNoThrow(try rsa.sign(message, variant: .message_pkcs1v15_SHA512))
     XCTAssertNoThrow(try rsa.sign(message, variant: .message_pkcs1v15_SHA512_224))
     XCTAssertNoThrow(try rsa.sign(message, variant: .message_pkcs1v15_SHA512_256))
+    XCTAssertNoThrow(try rsa.sign(message, variant: .message_pkcs1v15_SHA3_256))
+    XCTAssertNoThrow(try rsa.sign(message, variant: .message_pkcs1v15_SHA3_384))
+    XCTAssertNoThrow(try rsa.sign(message, variant: .message_pkcs1v15_SHA3_512))
   }
 
   /// This test uses the Fixtures (generated using Apple's `Security` framework) to test the entirety of an RSA keys functionality

+ 124 - 0
Tests/CryptoSwiftTests/SignatureVerificationTests.swift

@@ -0,0 +1,124 @@
+////  CryptoSwift
+//
+//  Copyright (C) 2014-2023 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 SignatureVerificationTests: XCTestCase {
+    
+  func testVerifySHA3Variants() {
+      let testVectors: [SignatureVerificationTests.TestVector] = [
+        SignatureVerificationTests.testVectorMessage_pkcs1v15_SHA3_256,
+        SignatureVerificationTests.testVectorMessage_pkcs1v15_SHA3_384,
+        SignatureVerificationTests.testVectorMessage_pkcs1v15_SHA3_512,
+        SignatureVerificationTests.testVectorDigest_pkcs1v15_SHA3_256,
+        SignatureVerificationTests.testVectorDigest_pkcs1v15_SHA3_384,
+        SignatureVerificationTests.testVectorDigest_pkcs1v15_SHA3_512
+      ]
+      
+    for testVector in testVectors {
+      do {
+        guard
+          let publicDerData = Data(base64Encoded: testVector.publicDER)
+        else {
+          XCTFail("Corrupted data - publicDER")
+          continue
+        }
+        
+        let rsa = try RSA(publicDER: publicDerData.bytes)
+        
+        guard
+          let signedMessageData = Data(base64Encoded: testVector.signedMessage)
+        else {
+          XCTFail("Corrupted data - signedMessage")
+          continue
+        }
+        
+        let result = try rsa.verify(signature: signedMessageData.bytes,
+                                    for: testVector.originalMessage.bytes,
+                                    variant: testVector.variant)
+        XCTAssertTrue(result, "Verification failed for test vector with id `\(testVector.id)`")
+        
+      } catch let error {
+        XCTFail("Failed with error \(error)")
+      }
+    }
+  }
+
+}
+
+extension SignatureVerificationTests {
+  struct TestVector {
+    
+    /// String to identify test vector. Used for logging purposes
+    let id: String
+    /// Public DER for RSA key
+    let publicDER: String
+    /// RSA signature variant
+    let variant: RSA.SignatureVariant
+    /// Original message that was signed
+    let originalMessage: String
+    /// Signed message
+    let signedMessage: String
+  }
+  
+  static let testVectorMessage_pkcs1v15_SHA3_256 = TestVector(
+    id: "1",
+    publicDER: "MIGJAoGBAJPTOQB0cqHPbrZO8Bnl77uFR8jgcYWmudETdRP57lCn/Q4v4Ga9OTqTkfbzX7DKq4WrrcPkx6/u4U4EVS6y7jyuq3Qn4VZMQPKiMiqRyRKhNKfC0i8SpMEhnIXGl824bi/YfV6arz0gicl24dP8C+HsO+WJGa7gtRs2d8hY2s+NAgMBAAE=",
+    variant: .message_pkcs1v15_SHA3_256,
+    originalMessage: "CryptoSwift Test",
+    signedMessage: "IOIA/8NgoLVwtfto5Lnea7GLBXMddCAgQFBt38HVJpbEtuEcmu8uFs4sJuAHalH1iIe/cGPrwASRM94fSDKzuQ7XNX2Dwt8DBzu9BlAtEWq9GUSL/6DED0xJfqrl6G5rh+RRk9YYIk3TeI9H4HzsmIDFjp5hxFu0SedoR5DzEVM="
+  )
+  
+  static let testVectorMessage_pkcs1v15_SHA3_384 = TestVector(
+    id: "2",
+    publicDER: "MIGJAoGBAJPTOQB0cqHPbrZO8Bnl77uFR8jgcYWmudETdRP57lCn/Q4v4Ga9OTqTkfbzX7DKq4WrrcPkx6/u4U4EVS6y7jyuq3Qn4VZMQPKiMiqRyRKhNKfC0i8SpMEhnIXGl824bi/YfV6arz0gicl24dP8C+HsO+WJGa7gtRs2d8hY2s+NAgMBAAE=",
+    variant: .message_pkcs1v15_SHA3_384,
+    originalMessage: "CryptoSwift Test",
+    signedMessage: "J1qAdFj7iwlW6Mhyf5MfG2CN7BeUjKCFeCunBs2Hginwpcz/YfJgzNpGA93T+RBR4kLVuhs3OVILhwaMnTbgsMVNz0xLoZ5oegRADXDT1Ln3WuTUuqQH+RiMSILelgaHsU4fjj7jCC8wLFA2DtYm7aje1HF3ZRc/9SQSTREM5Gw="
+  )
+  
+  static let testVectorMessage_pkcs1v15_SHA3_512 = TestVector(
+    id: "3",
+    publicDER: "MIGJAoGBAJPTOQB0cqHPbrZO8Bnl77uFR8jgcYWmudETdRP57lCn/Q4v4Ga9OTqTkfbzX7DKq4WrrcPkx6/u4U4EVS6y7jyuq3Qn4VZMQPKiMiqRyRKhNKfC0i8SpMEhnIXGl824bi/YfV6arz0gicl24dP8C+HsO+WJGa7gtRs2d8hY2s+NAgMBAAE=",
+    variant: .message_pkcs1v15_SHA3_512,
+    originalMessage: "CryptoSwift Test",
+    signedMessage: "KMmRIptAPCZV7I/6gRN6wUQekRm+sxXWtoAyxC7PPiSBNd9XJTVVrEUnEfpnupI6uum+r9YxAT5Ha0S5XrYlojHZFLW3gZHLAKmRBushg8YRfqK68cDLYBshuqBlf5nuQZDU+7LTBh6Jnup2rGbQj1Bra9X9Hl9uZmoPY8Uoh/g="
+  )
+  
+  static let testVectorDigest_pkcs1v15_SHA3_256 = TestVector(
+    id: "4",
+    publicDER: "MIGJAoGBAJPTOQB0cqHPbrZO8Bnl77uFR8jgcYWmudETdRP57lCn/Q4v4Ga9OTqTkfbzX7DKq4WrrcPkx6/u4U4EVS6y7jyuq3Qn4VZMQPKiMiqRyRKhNKfC0i8SpMEhnIXGl824bi/YfV6arz0gicl24dP8C+HsO+WJGa7gtRs2d8hY2s+NAgMBAAE=",
+    variant: .digest_pkcs1v15_SHA3_256,
+    originalMessage: "CryptoSwift Test",
+    signedMessage: "Oj3CBwMQIEGrQwFuqIXklqOJG6pdaS5Kjal+sAKoMvEzXCB0h8K8w9YNt/XIOD9fJXdUaG0XR6RB8eEQxh/u6pYZPVUwssyA//FUjWLgKOecNkaca+EK98iIkivjVdEGK7yVhcQHJF19EfpZahVWWlEUCT02g8niomkWUHWIlo8="
+  )
+  
+  static let testVectorDigest_pkcs1v15_SHA3_384 = TestVector(
+    id: "5",
+    publicDER: "MIGJAoGBAJPTOQB0cqHPbrZO8Bnl77uFR8jgcYWmudETdRP57lCn/Q4v4Ga9OTqTkfbzX7DKq4WrrcPkx6/u4U4EVS6y7jyuq3Qn4VZMQPKiMiqRyRKhNKfC0i8SpMEhnIXGl824bi/YfV6arz0gicl24dP8C+HsO+WJGa7gtRs2d8hY2s+NAgMBAAE=",
+    variant: .digest_pkcs1v15_SHA3_384,
+    originalMessage: "CryptoSwift Test",
+    signedMessage: "ZCn19KmnT/QdzcNm077uopZeIxkR5EECX0po2QypPTYorYa9dGTm3nKR0mMr/G2C7ukrR2a8j5WPf4hXi1rlzOoFNufpbyQB33I9INleN7FjASmoxFcw6TyFNeMPN+TwKj9MVTEkZ7HtPL0bBsD8E08eRCDwk3UYdUjcvZcOdzw="
+  )
+  
+  static let testVectorDigest_pkcs1v15_SHA3_512 = TestVector(
+    id: "6",
+    publicDER: "MIGJAoGBAJPTOQB0cqHPbrZO8Bnl77uFR8jgcYWmudETdRP57lCn/Q4v4Ga9OTqTkfbzX7DKq4WrrcPkx6/u4U4EVS6y7jyuq3Qn4VZMQPKiMiqRyRKhNKfC0i8SpMEhnIXGl824bi/YfV6arz0gicl24dP8C+HsO+WJGa7gtRs2d8hY2s+NAgMBAAE=",
+    variant: .digest_pkcs1v15_SHA3_512,
+    originalMessage: "CryptoSwift Test",
+    signedMessage: "bk1/rtzt64ZApavxPrUEnsG/tN7nN6ITV3NKY0IR1i/3S4bkxIMulRsBPINpksTAafxrSm6EsLAmOPrqjwGycqRjSRi8/S6roUE/TIno2dGfO5e4eVKCQtD6I+CHA0Xji3X1k627vaYZqpTMFuMk8serfjMTHFe46s6S+f/64as="
+  )
+}