Skip to content

Commit

Permalink
Make pointer private and change DER to raw representation
Browse files Browse the repository at this point in the history
  • Loading branch information
fpseverino committed Oct 18, 2024
1 parent b3c8328 commit 4e29fb1
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 79 deletions.
108 changes: 35 additions & 73 deletions Sources/_CryptoExtras/MLDSA/MLDSA_boring.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,13 @@ extension MLDSA {
self.backing = try Backing(seed: seed)
}

/// Initialize a ML-DSA-65 private key from a DER representation.
/// Initialize a ML-DSA-65 private key from a raw representation.
///
/// - Parameter derRepresentation: The DER representation of the private key.
/// - Parameter rawRepresentation: The private key bytes.
///
/// - Throws: `CryptoKitError.incorrectKeySize` if the DER representation is not the correct size.
public init(derRepresentation: some DataProtocol) throws {
self.backing = try Backing(derRepresentation: derRepresentation)
}

/// Initialize a ML-DSA-65 private key from a PEM representation.
///
/// - Parameter pemRepresentation: The PEM representation of the private key.
public init(pemRepresentation: String) throws {
self.backing = try Backing(pemRepresentation: pemRepresentation)
/// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size.
public init(rawRepresentation: some DataProtocol) throws {
self.backing = try Backing(rawRepresentation: rawRepresentation)
}

/// The public key associated with this private key.
Expand All @@ -79,7 +72,11 @@ extension MLDSA {
static let bytesCount = Backing.bytesCount

fileprivate final class Backing {
let pointer: UnsafeMutablePointer<MLDSA65_private_key>
private let pointer: UnsafeMutablePointer<MLDSA65_private_key>

func withUnsafePointer<T>(_ body: (UnsafePointer<MLDSA65_private_key>) throws -> T) rethrows -> T {
try body(self.pointer)
}

/// Initialize a ML-DSA-65 private key from a random seed.
init() throws {
Expand Down Expand Up @@ -122,19 +119,19 @@ extension MLDSA {
}
}

/// Initialize a ML-DSA-65 private key from a DER representation.
/// Initialize a ML-DSA-65 private key from a raw representation.
///
/// - Parameter derRepresentation: The DER representation of the private key.
/// - Parameter rawRepresentation: The private key bytes.
///
/// - Throws: `CryptoKitError.incorrectKeySize` if the DER representation is not the correct size.
init(derRepresentation: some DataProtocol) throws {
guard derRepresentation.count == MLDSA.PrivateKey.Backing.bytesCount else {
/// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size.
init(rawRepresentation: some DataProtocol) throws {
guard rawRepresentation.count == MLDSA.PrivateKey.Backing.bytesCount else {
throw CryptoKitError.incorrectKeySize
}

self.pointer = UnsafeMutablePointer<MLDSA65_private_key>.allocate(capacity: 1)

try derRepresentation.regions.flatMap { $0 }.withUnsafeBufferPointer { buffer in
try rawRepresentation.regions.flatMap { $0 }.withUnsafeBufferPointer { buffer in
let cbsPointer = UnsafeMutablePointer<CBS>.allocate(capacity: 1)
defer { cbsPointer.deallocate() }
cbsPointer.pointee = CBS(data: buffer.baseAddress, len: buffer.count)
Expand All @@ -145,14 +142,6 @@ extension MLDSA {
}
}

/// Initialize a ML-DSA-65 private key from a PEM representation.
///
/// - Parameter pemRepresentation: The PEM representation of the private key.
convenience init(pemRepresentation: String) throws {
let document = try ASN1.PEMDocument(pemString: pemRepresentation)
try self.init(derRepresentation: document.derBytes)
}

/// The public key associated with this private key.
var publicKey: PublicKey {
PublicKey(privateKeyBacking: self)
Expand Down Expand Up @@ -214,33 +203,19 @@ extension MLDSA {
self.backing = Backing(privateKeyBacking: privateKeyBacking)
}

/// Initialize a ML-DSA-65 public key from a DER representation.
///
/// - Parameter derRepresentation: The DER representation of the public key.
/// Initialize a ML-DSA-65 public key from a raw representation.
///
/// - Throws: `CryptoKitError.incorrectKeySize` if the DER representation is not the correct size.
public init(derRepresentation: some DataProtocol) throws {
self.backing = try Backing(derRepresentation: derRepresentation)
}

/// Initialize a ML-DSA-65 public key from a PEM representation.
/// - Parameter rawRepresentation: The public key bytes.
///
/// - Parameter pemRepresentation: The PEM representation of the public key.
public init(pemRepresentation: String) throws {
self.backing = try Backing(pemRepresentation: pemRepresentation)
/// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size.
public init(rawRepresentation: some DataProtocol) throws {
self.backing = try Backing(rawRepresentation: rawRepresentation)
}

/// The DER representation of the public key.
public var derRepresentation: Data {
/// The raw binary representation of the public key.
public var rawRepresentation: Data {
get throws {
try self.backing.derRepresentation
}
}

/// The PEM representation of the public key.
public var pemRepresentation: String {
get throws {
try self.backing.pemRepresentation
try self.backing.rawRepresentation
}
}

Expand All @@ -264,22 +239,24 @@ extension MLDSA {

init(privateKeyBacking: PrivateKey.Backing) {
self.pointer = UnsafeMutablePointer<MLDSA65_public_key>.allocate(capacity: 1)
CCryptoBoringSSL_MLDSA65_public_from_private(self.pointer, privateKeyBacking.pointer)
let _ = privateKeyBacking.withUnsafePointer { privateKeyPtr in
CCryptoBoringSSL_MLDSA65_public_from_private(self.pointer, privateKeyPtr)
}
}

/// Initialize a ML-DSA-65 public key from a DER representation.
/// Initialize a ML-DSA-65 public key from a raw representation.
///
/// - Parameter derRepresentation: The DER representation of the public key.
/// - Parameter rawRepresentation: The public key bytes.
///
/// - Throws: `CryptoKitError.incorrectKeySize` if the DER representation is not the correct size.
init(derRepresentation: some DataProtocol) throws {
guard derRepresentation.count == MLDSA.PublicKey.Backing.bytesCount else {
/// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size.
init(rawRepresentation: some DataProtocol) throws {
guard rawRepresentation.count == MLDSA.PublicKey.Backing.bytesCount else {
throw CryptoKitError.incorrectKeySize
}

self.pointer = UnsafeMutablePointer<MLDSA65_public_key>.allocate(capacity: 1)

try derRepresentation.regions.flatMap { $0 }.withUnsafeBufferPointer { buffer in
try rawRepresentation.regions.flatMap { $0 }.withUnsafeBufferPointer { buffer in
let cbsPointer = UnsafeMutablePointer<CBS>.allocate(capacity: 1)
defer { cbsPointer.deallocate() }
cbsPointer.pointee = CBS(data: buffer.baseAddress, len: buffer.count)
Expand All @@ -290,16 +267,8 @@ extension MLDSA {
}
}

/// Initialize a ML-DSA-65 public key from a PEM representation.
///
/// - Parameter pemRepresentation: The PEM representation of the public key.
convenience init(pemRepresentation: String) throws {
let document = try ASN1.PEMDocument(pemString: pemRepresentation)
try self.init(derRepresentation: document.derBytes)
}

/// The DER representation of the public key.
var derRepresentation: Data {
/// The raw binary representation of the public key.
var rawRepresentation: Data {
get throws {
var cbb = CBB()
// `CBB_init` can only return 0 on allocation failure, which we define as impossible.
Expand All @@ -318,13 +287,6 @@ extension MLDSA {
}
}

/// The PEM representation of the public key.
var pemRepresentation: String {
get throws {
ASN1.PEMDocument(type: MLDSA.PublicKeyType, derBytes: try self.derRepresentation).pemString
}
}

/// Verify a signature for the given data.
///
/// - Parameters:
Expand Down
12 changes: 6 additions & 6 deletions Tests/_CryptoExtrasTests/MLDSATests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,27 +97,27 @@ final class MLDSATests: XCTestCase {
let seed: [UInt8] = (0..<32).map { _ in UInt8.random(in: 0...255) }
let key = try MLDSA.PrivateKey(seed: seed)
let publicKey = key.publicKey
try encodedPublicKey.replaceSubrange(0..<MLDSA.PublicKey.bytesCount, with: publicKey.derRepresentation)
try encodedPublicKey.replaceSubrange(0..<MLDSA.PublicKey.bytesCount, with: publicKey.rawRepresentation)

// Public key is 1 byte too short.
let shortPublicKey = Array(encodedPublicKey.prefix(MLDSA.PublicKey.bytesCount - 1))
XCTAssertThrowsError(try MLDSA.PublicKey(derRepresentation: shortPublicKey))
XCTAssertThrowsError(try MLDSA.PublicKey(rawRepresentation: shortPublicKey))

// Public key has the correct length.
let correctLengthPublicKey = Array(encodedPublicKey.prefix(MLDSA.PublicKey.bytesCount))
XCTAssertNoThrow(try MLDSA.PublicKey(derRepresentation: correctLengthPublicKey))
XCTAssertNoThrow(try MLDSA.PublicKey(rawRepresentation: correctLengthPublicKey))

// Public key is 1 byte too long.
XCTAssertThrowsError(try MLDSA.PublicKey(derRepresentation: encodedPublicKey))
XCTAssertThrowsError(try MLDSA.PublicKey(rawRepresentation: encodedPublicKey))
}

func testMLDSAKeyGenFile() throws {
try mldsaTest(jsonName: "mldsa_nist_keygen_tests") { (testVector: MLDSAKeyGenTestVector) in
let seed = try Data(hexString: testVector.seed)
let publicKey = try MLDSA.PublicKey(derRepresentation: Data(hexString: testVector.pub))
let publicKey = try MLDSA.PublicKey(rawRepresentation: Data(hexString: testVector.pub))

let expectedkey = try MLDSA.PrivateKey(seed: seed).publicKey
try XCTAssertEqual(publicKey.derRepresentation, expectedkey.derRepresentation)
try XCTAssertEqual(publicKey.rawRepresentation, expectedkey.rawRepresentation)
}
}

Expand Down

0 comments on commit 4e29fb1

Please sign in to comment.