Skip to content

Commit

Permalink
Add more tests and document the default signature algorithm.
Browse files Browse the repository at this point in the history
  • Loading branch information
baarde committed Jan 19, 2025
1 parent fb45ba8 commit 6bbb4fb
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Sources/X509/CSR/CertificateSigningRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ public struct CertificateSigningRequest {
/// This API can be used to construct a certificate signing request that can be passed to a certificate
/// authority. It will correctly generate a signature over the request.
///
/// A default signature algorithm to use for the signature of this CSR is automatically chosen based on
/// the type of the private key.
///
/// - Parameters:
/// - version: The CSR version.
/// - subject: The ``DistinguishedName`` of the subject of this CSR
Expand Down
3 changes: 3 additions & 0 deletions Sources/X509/Certificate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,9 @@ public struct Certificate {
/// Certificate Signing Request. The ``signature-swift.property`` for this certificate will be produced
/// automatically, using `issuerPrivateKey`.
///
/// A default signature algorithm to use for the signature of this certificate is automatically chosen based
/// on the type of the issuer's private key.
///
/// This API can be used to construct a self-signed key by passing the private key for `publicKey` as the
/// `issuerPrivateKey` argument.
///
Expand Down
2 changes: 2 additions & 0 deletions Sources/X509/X509BaseTypes/AlgorithmIdentifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ extension AlgorithmIdentifier: CustomStringConvertible {
return "sha384"
case .sha512, .sha512UsingNil:
return "sha512"
case .ed25519:
return "ed25519"
default:
return "AlgorithmIdentifier(\(self.algorithm) - \(String(reflecting: self.parameters)))"
}
Expand Down
50 changes: 50 additions & 0 deletions Tests/X509Tests/CMSTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import Foundation
import XCTest
import Crypto
import _CryptoExtras
import SwiftASN1
@testable @_spi(CMS) import X509

Expand Down Expand Up @@ -1166,6 +1167,55 @@ final class CMSTests: XCTestCase {
CMSSignerIdentifier.subjectKeyIdentifier(.init(keyIdentifier: [10, 20, 30, 40]))
)
}

func testDefaultRSASignatureAlgorithm() throws {
let privateKey = try Certificate.PrivateKey(_RSA.Signing.PrivateKey(keySize: .bits2048))
let signerInfo = try self.signAndExtractSignerInfo(privateKey: privateKey)
XCTAssertEqual(signerInfo?.signatureAlgorithm.description, "sha256WithRSAEncryption")
}

func testDefaultP256SignatureAlgorithm() throws {
let privateKey = Certificate.PrivateKey(P256.Signing.PrivateKey())
let signerInfo = try self.signAndExtractSignerInfo(privateKey: privateKey)
XCTAssertEqual(signerInfo?.signatureAlgorithm.description, "ecdsaWithSHA256")
}

func testDefaultP384SignatureAlgorithm() throws {
let privateKey = Certificate.PrivateKey(P384.Signing.PrivateKey())
let signerInfo = try self.signAndExtractSignerInfo(privateKey: privateKey)
XCTAssertEqual(signerInfo?.signatureAlgorithm.description, "ecdsaWithSHA384")
}

func testDefaultP521SignatureAlgorithm() throws {
let privateKey = Certificate.PrivateKey(P521.Signing.PrivateKey())
let signerInfo = try self.signAndExtractSignerInfo(privateKey: privateKey)
XCTAssertEqual(signerInfo?.signatureAlgorithm.description, "ecdsaWithSHA512")
}

func testDefaultEd25519SignatureAlgorithm() throws {
let privateKey = Certificate.PrivateKey(Curve25519.Signing.PrivateKey())
let signerInfo = try self.signAndExtractSignerInfo(privateKey: privateKey)
XCTAssertEqual(signerInfo?.signatureAlgorithm.description, "ed25519")
}

private func signAndExtractSignerInfo(privateKey: Certificate.PrivateKey) throws -> CMSSignerInfo? {
let name = try DistinguishedName { CommonName("test") }
let certificate = try Certificate(
version: .v3,
serialNumber: .init(bytes: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]),
publicKey: privateKey.publicKey,
notValidBefore: Date(),
notValidAfter: Date() + 3600,
issuer: name,
subject: name,
extensions: Certificate.Extensions {},
issuerPrivateKey: privateKey
)
let data: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
let signatureBytes = try CMS.sign(data, certificate: certificate, privateKey: privateKey)
let contentInfo = try CMSContentInfo(derEncoded: signatureBytes)
return try contentInfo.signedData?.signerInfos.first
}
}

extension DERSerializable {
Expand Down
39 changes: 39 additions & 0 deletions Tests/X509Tests/CSRTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,45 @@ final class CSRTests: XCTestCase {
CertificateSigningRequest.Attributes(attributes.prefix(2))
)
}

func testDefaultRSASignatureAlgorithm() throws {
let privateKey = try Certificate.PrivateKey(_RSA.Signing.PrivateKey(keySize: .bits2048))
let csr = try self.generateCertificateSigningRequest(privateKey: privateKey)
XCTAssertEqual(csr.signatureAlgorithm.description, "SignatureAlgorithm.sha256WithRSAEncryption")
}

func testDefaultP256SignatureAlgorithm() throws {
let privateKey = Certificate.PrivateKey(P256.Signing.PrivateKey())
let csr = try self.generateCertificateSigningRequest(privateKey: privateKey)
XCTAssertEqual(csr.signatureAlgorithm.description, "SignatureAlgorithm.ecdsaWithSHA256")
}

func testDefaultP384SignatureAlgorithm() throws {
let privateKey = Certificate.PrivateKey(P384.Signing.PrivateKey())
let csr = try self.generateCertificateSigningRequest(privateKey: privateKey)
XCTAssertEqual(csr.signatureAlgorithm.description, "SignatureAlgorithm.ecdsaWithSHA384")
}

func testDefaultP521SignatureAlgorithm() throws {
let privateKey = Certificate.PrivateKey(P521.Signing.PrivateKey())
let csr = try self.generateCertificateSigningRequest(privateKey: privateKey)
XCTAssertEqual(csr.signatureAlgorithm.description, "SignatureAlgorithm.ecdsaWithSHA512")
}

func testDefaultEd25519SignatureAlgorithm() throws {
let privateKey = Certificate.PrivateKey(Curve25519.Signing.PrivateKey())
let csr = try self.generateCertificateSigningRequest(privateKey: privateKey)
XCTAssertEqual(csr.signatureAlgorithm.description, "SignatureAlgorithm.ed25519")
}

private func generateCertificateSigningRequest(privateKey: Certificate.PrivateKey) throws -> CertificateSigningRequest {
try CertificateSigningRequest(
version: .v1,
subject: DistinguishedName { CommonName("test") },
privateKey: privateKey,
attributes: CertificateSigningRequest.Attributes()
)
}
}

extension RandomAccessCollection {
Expand Down

0 comments on commit 6bbb4fb

Please sign in to comment.