Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Sources/X509/CertificatePrivateKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,14 @@ extension Certificate {
}
#endif

/// Use the private key to sign the provided bytes with a given signature algorithm.
///
/// - Parameters:
/// - bytes: The data to create the signature for.
/// - signatureAlgorithm: The signature algorithm to use.
/// - Returns: The signature.
@inlinable
internal func sign<Bytes: DataProtocol>(
public func sign<Bytes: DataProtocol>(
bytes: Bytes,
signatureAlgorithm: SignatureAlgorithm
) throws -> Signature {
Expand Down
25 changes: 17 additions & 8 deletions Sources/X509/Signature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,22 +129,31 @@ extension Certificate.Signature {
}

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
extension ASN1BitString {
extension Certificate.Signature {
/// The raw byte representation of the signature.
@inlinable
init(_ signature: Certificate.Signature) {
switch signature.backing {
public var rawRepresentation: [UInt8] {
Comment thread
Lukasa marked this conversation as resolved.
switch self.backing {
case .ecdsa(let sig):
var serializer = DER.Serializer()
try! serializer.serialize(sig)
self = ASN1BitString(bytes: serializer.serializedBytes[...])
case .rsa(let sig):
self = ASN1BitString(bytes: ArraySlice(sig.rawRepresentation))
case .ed25519(let sig):
self = ASN1BitString(bytes: ArraySlice(sig))
return serializer.serializedBytes
case let .ed25519(data):
return .init(data)
case let .rsa(signature):
return .init(signature.rawRepresentation)
}
}
}

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
extension ASN1BitString {
@inlinable
init(_ signature: Certificate.Signature) {
self.init(bytes: signature.rawRepresentation[...])
}
}

@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, macCatalyst 13, visionOS 1.0, *)
extension ASN1OctetString {
@inlinable
Expand Down
36 changes: 36 additions & 0 deletions Tests/X509Tests/SignatureTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,40 @@ final class SignatureTests: XCTestCase {
)
#endif

func testRSASignatureBytes() throws {
let input = Array("Hello World".utf8)
let privateKey = Certificate.PrivateKey(Self.rsaKey)

let expected = try Self.rsaKey.signature(for: SHA256.hash(data: input), padding: .insecurePKCS1v1_5)
let found = try privateKey.sign(bytes: input, signatureAlgorithm: .sha256WithRSAEncryption)

XCTAssertEqual(.init(expected.rawRepresentation), found.rawRepresentation)
}

func testEd25519SignatureBytes() throws {
Comment thread
bauer-andreas marked this conversation as resolved.
let input = Array("Hello World".utf8)

let expected = try Self.ed25519Key.signature(for: input)
let signature = try Certificate.Signature(
signatureAlgorithm: .ed25519,
signatureBytes: .init(bytes: Array(expected)[...])
)

XCTAssertEqual(.init(expected), signature.rawRepresentation)
}

func testECDSASignatureBytes() throws {
let input = Array("Hello World".utf8)

let expected = try Self.p384Key.signature(for: SHA256.hash(data: input))
let signature = try Certificate.Signature(
signatureAlgorithm: .ecdsaWithSHA256,
signatureBytes: .init(bytes: Array(expected.derRepresentation)[...])
)

XCTAssertEqual(.init(expected.derRepresentation), signature.rawRepresentation)
}

func testP384Signature() throws {
// This is the P384 signature over LetsEncrypt Intermediate E1.
let signatureBytes: [UInt8] = [
Expand All @@ -75,6 +109,8 @@ final class SignatureTests: XCTestCase {
return
}

XCTAssertEqual(signature.rawRepresentation, .init(signatureBytes))

// Validate that the signature is valid over the TBS certificate bytes.
let issuingPublicKeyBytes: [UInt8] = [
0x04, 0xCD, 0x9B, 0xD5, 0x9F, 0x80, 0x83, 0x0A, 0xEC, 0x09, 0x4A, 0xF3,
Expand Down
Loading