Skip to content

Commit ecaec8a

Browse files
committed
Check key size
1 parent d22774c commit ecaec8a

File tree

4 files changed

+38
-3
lines changed

4 files changed

+38
-3
lines changed

Sources/PackageCollectionsSigning/Key/Key+RSA.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ typealias RSAPrivateKey = BoringSSLRSAPrivateKey
4343
struct CoreRSAPrivateKey: PrivateKey {
4444
let underlying: SecKey
4545

46+
var sizeInBits: Int {
47+
toBits(bytes: SecKeyGetBlockSize(self.underlying))
48+
}
49+
4650
init<Data>(pem data: Data) throws where Data: DataProtocol {
4751
let pemString = String(decoding: data, as: UTF8.self)
4852
let pemDocument = try ASN1.PEMDocument(pemString: pemString)
@@ -67,6 +71,10 @@ struct CoreRSAPrivateKey: PrivateKey {
6771
struct CoreRSAPublicKey: PublicKey {
6872
let underlying: SecKey
6973

74+
var sizeInBits: Int {
75+
toBits(bytes: SecKeyGetBlockSize(self.underlying))
76+
}
77+
7078
/// `data` should be in PKCS #1 format
7179
init(data: Data) throws {
7280
let options: [String: Any] = [
@@ -104,6 +112,10 @@ final class BoringSSLRSAPrivateKey: PrivateKey, BoringSSLKey {
104112
CCryptoBoringSSL_RSA_free(self.underlying)
105113
}
106114

115+
var sizeInBits: Int {
116+
toBits(bytes: Int(CCryptoBoringSSL_RSA_size(self.underlying)))
117+
}
118+
107119
init<Data>(pem data: Data) throws where Data: DataProtocol {
108120
let key = try Self.load(pem: data) { bio in
109121
CCryptoBoringSSL_PEM_read_bio_PrivateKey(bio, nil, nil, nil)
@@ -126,6 +138,10 @@ final class BoringSSLRSAPublicKey: PublicKey, BoringSSLKey {
126138
CCryptoBoringSSL_RSA_free(self.underlying)
127139
}
128140

141+
var sizeInBits: Int {
142+
toBits(bytes: Int(CCryptoBoringSSL_RSA_size(self.underlying)))
143+
}
144+
129145
/// `data` should be in the PKCS #1 format
130146
init(data: Data) throws {
131147
let bytes = data.copyBytes()

Sources/PackageCollectionsSigning/Key/Key.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,7 @@ enum KeyType {
4040
case RSA
4141
case EC
4242
}
43+
44+
func toBits(bytes: Int) -> Int {
45+
bytes * 8
46+
}

Sources/PackageCollectionsSigning/PackageCollectionSigning.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import PackageCollectionsModel
1515
public struct PackageCollectionSigning {
1616
public typealias Model = PackageCollectionModel.V1
1717

18+
private static let minimumRSAKeySizeInBits = 2048
19+
1820
let certPolicy: CertificatePolicy
1921

2022
public init() {
@@ -84,6 +86,7 @@ public struct PackageCollectionSigning {
8486
case .EC:
8587
privateKey = try ECPrivateKey(pem: privateKeyPEM)
8688
}
89+
try self.validateKey(privateKey)
8790

8891
// Generate the signature
8992
let signatureBytes = try Signature.generate(for: collection, with: header, using: privateKey, jsonEncoder: jsonEncoder)
@@ -173,11 +176,20 @@ public struct PackageCollectionSigning {
173176
callback(.failure(error))
174177
}
175178
}
179+
180+
private func validateKey(_ privateKey: PrivateKey) throws {
181+
if let rsaKey = privateKey as? RSAPrivateKey {
182+
guard rsaKey.sizeInBits >= Self.minimumRSAKeySizeInBits else {
183+
throw PackageCollectionSigningError.invalidKeySize(minimumBits: Self.minimumRSAKeySizeInBits)
184+
}
185+
}
186+
}
176187
}
177188

178189
enum PackageCollectionSigningError: Error {
179190
case emptyCertChain
180191
case invalidCertChain
181192
case invalidSignature
182193
case missingCertInfo
194+
case invalidKeySize(minimumBits: Int)
183195
}

Tests/PackageCollectionsSigningTests/KeyTests+RSA.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,18 @@ class RSAKeyTests: XCTestCase {
2222
let data = Data(try localFileSystem.readFileContents(path).contents)
2323

2424
let certificate = try Certificate(derEncoded: data)
25-
XCTAssertNoThrow(try certificate.publicKey())
25+
let key = try certificate.publicKey() as! RSAPublicKey
26+
XCTAssertEqual(2048, key.sizeInBits)
2627
}
2728
}
2829

2930
func testPublicKeyFromPEM() throws {
30-
XCTAssertNoThrow(try RSAPublicKey(pem: rsaPublicKey.bytes))
31+
let key = try RSAPublicKey(pem: rsaPublicKey.bytes)
32+
XCTAssertEqual(2048, key.sizeInBits)
3133
}
3234

3335
func testPrivateKeyFromPEM() throws {
34-
XCTAssertNoThrow(try RSAPrivateKey(pem: rsaPrivateKey.bytes))
36+
let key = try RSAPrivateKey(pem: rsaPrivateKey.bytes)
37+
XCTAssertEqual(2048, key.sizeInBits)
3538
}
3639
}

0 commit comments

Comments
 (0)