Skip to content

Commit

Permalink
Merge pull request #1027 from LabMobi/RSA-PKCS1-SHA3-signature-verifi…
Browse files Browse the repository at this point in the history
…cation

Rsa pkcs1 sha3 signature verification
  • Loading branch information
krzyzanowskim authored Jan 7, 2024
2 parents d7de7d7 + ba651db commit 037646a
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 25 deletions.
4 changes: 4 additions & 0 deletions CONTRIBUTORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ organizations who have contributed source code to CryptoSwift.
- John Hammerlund <[email protected]>
- Jonas Obrist <[email protected]>
- K.K. POON <[email protected]>
- Katrin Annuk <[email protected]>
- Keith Smiley <[email protected]>
- Koray Koska <[email protected]>
- Kyle Fuller <[email protected]>
Expand All @@ -72,6 +73,7 @@ organizations who have contributed source code to CryptoSwift.
- Matias Cudich <[email protected]>
- Matias Piipari <[email protected]>
- Matthew Chung <[email protected]>
- Matthias Geihs <[email protected]>
- Maxence Mottard <[email protected]>
- Michael Ledin <[email protected]>
- Michael Redig <[email protected]>
Expand Down Expand Up @@ -112,6 +114,8 @@ organizations who have contributed source code to CryptoSwift.
- Xavier Matos <[email protected]>
- Yannick Loriot <[email protected]>
- Yury Lapitsky <[email protected]>
- Zsombor Szabo <[email protected]>
- Zsombor Szabo <[email protected]>
- akreutz <27BBsan08!>
- jose <[email protected]>
- mrahmiao <[email protected]>
Expand Down
6 changes: 5 additions & 1 deletion CryptoSwift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 52;
objectVersion = 54;
objects = {

/* Begin PBXBuildFile section */
Expand All @@ -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 */; };
Expand Down Expand Up @@ -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>"; };
Expand Down Expand Up @@ -581,6 +583,7 @@
75482EA31CB310B7001F66A5 /* PBKDF.swift */,
7576F6F6207290F8006688F8 /* PBKDFPerf.swift */,
6A7CDEEC26CD1E4C00FFB1AF /* RSATests.swift */,
5431FD592B021470001DEE77 /* SignatureVerificationTests.swift */,
75C2E76C1D55F097003D2BCA /* Access.swift */,
756BFDCA1A82B87300B9D9A4 /* Bridging.h */,
);
Expand Down Expand Up @@ -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;
Expand Down
75 changes: 51 additions & 24 deletions Sources/CryptoSwift/RSA/RSA+Signature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 []
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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
}
}

Expand Down
6 changes: 6 additions & 0 deletions Tests/CryptoSwiftTests/RSATests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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
Expand Down
124 changes: 124 additions & 0 deletions Tests/CryptoSwiftTests/SignatureVerificationTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
//// CryptoSwift
//
// Copyright (C) 2014-2023 Marcin Krzyżanowski <[email protected]>
// 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="
)
}

0 comments on commit 037646a

Please sign in to comment.