@@ -326,312 +326,6 @@ extension MLDSA65 {
326326 private static let signatureByteCount = Int ( MLDSA65_SIGNATURE_BYTES)
327327}
328328
329- /// A module-lattice-based digital signature algorithm that provides security against quantum computing attacks.
330- @available ( macOS 10 . 15 , iOS 13 , watchOS 6 , tvOS 13 , macCatalyst 13 , visionOS 1 . 0 , * )
331- public enum MLDSA87 { }
332-
333- @available ( macOS 10 . 15 , iOS 13 , watchOS 6 , tvOS 13 , macCatalyst 13 , visionOS 1 . 0 , * )
334- extension MLDSA87 {
335- /// A ML-DSA-87 private key.
336- public struct PrivateKey : Sendable {
337- private var backing : Backing
338-
339- /// Initialize a ML-DSA-87 private key from a random seed.
340- public init ( ) throws {
341- self . backing = try Backing ( )
342- }
343-
344- /// Initialize a ML-DSA-87 private key from a seed.
345- ///
346- /// - Parameter seedRepresentation: The seed to use to generate the private key.
347- ///
348- /// - Throws: `CryptoKitError.incorrectKeySize` if the seed is not 32 bytes long.
349- public init ( seedRepresentation: some DataProtocol ) throws {
350- self . backing = try Backing ( seedRepresentation: seedRepresentation)
351- }
352-
353- /// The seed from which this private key was generated.
354- public var seedRepresentation : Data {
355- self . backing. seed
356- }
357-
358- /// The public key associated with this private key.
359- public var publicKey : PublicKey {
360- self . backing. publicKey
361- }
362-
363- /// Generate a signature for the given data.
364- ///
365- /// - Parameter data: The message to sign.
366- ///
367- /// - Returns: The signature of the message.
368- public func signature< D: DataProtocol > ( for data: D ) throws -> Data {
369- let context : Data ? = nil
370- return try self . backing. signature ( for: data, context: context)
371- }
372-
373- /// Generate a signature for the given data.
374- ///
375- /// - Parameters:
376- /// - data: The message to sign.
377- /// - context: The context to use for the signature.
378- ///
379- /// - Returns: The signature of the message.
380- public func signature< D: DataProtocol , C: DataProtocol > ( for data: D , context: C ) throws -> Data {
381- try self . backing. signature ( for: data, context: context)
382- }
383-
384- /// The size of the private key in bytes.
385- static let byteCount = Backing . byteCount
386-
387- fileprivate final class Backing {
388- fileprivate var key : MLDSA87_private_key
389- var seed : Data
390-
391- /// Initialize a ML-DSA-87 private key from a random seed.
392- init ( ) throws {
393- // We have to initialize all members before `self` is captured by the closure
394- self . key = . init( )
395- self . seed = Data ( )
396-
397- self . seed = try withUnsafeTemporaryAllocation (
398- of: UInt8 . self,
399- capacity: MLDSA . seedByteCount
400- ) { seedPtr in
401- try withUnsafeTemporaryAllocation (
402- of: UInt8 . self,
403- capacity: MLDSA87 . PublicKey. Backing. byteCount
404- ) { publicKeyPtr in
405- guard
406- CCryptoBoringSSL_MLDSA87_generate_key (
407- publicKeyPtr. baseAddress,
408- seedPtr. baseAddress,
409- & self . key
410- ) == 1
411- else {
412- throw CryptoKitError . internalBoringSSLError ( )
413- }
414-
415- return Data ( bytes: seedPtr. baseAddress!, count: MLDSA . seedByteCount)
416- }
417- }
418- }
419-
420- /// Initialize a ML-DSA-87 private key from a seed.
421- ///
422- /// - Parameter seedRepresentation: The seed to use to generate the private key.
423- ///
424- /// - Throws: `CryptoKitError.incorrectKeySize` if the seed is not 32 bytes long.
425- init ( seedRepresentation: some DataProtocol ) throws {
426- guard seedRepresentation. count == MLDSA . seedByteCount else {
427- throw CryptoKitError . incorrectKeySize
428- }
429-
430- self . key = . init( )
431- self . seed = Data ( seedRepresentation)
432-
433- guard
434- self . seed. withUnsafeBytes ( { seedPtr in
435- CCryptoBoringSSL_MLDSA87_private_key_from_seed (
436- & self . key,
437- seedPtr. baseAddress,
438- MLDSA . seedByteCount
439- )
440- } ) == 1
441- else {
442- throw CryptoKitError . internalBoringSSLError ( )
443- }
444- }
445-
446- /// The public key associated with this private key.
447- var publicKey : PublicKey {
448- PublicKey ( privateKeyBacking: self )
449- }
450-
451- /// Generate a signature for the given data.
452- ///
453- /// - Parameters:
454- /// - data: The message to sign.
455- /// - context: The context to use for the signature.
456- ///
457- /// - Returns: The signature of the message.
458- func signature< D: DataProtocol , C: DataProtocol > ( for data: D , context: C ? ) throws -> Data {
459- var signature = Data ( repeating: 0 , count: MLDSA87 . signatureByteCount)
460-
461- let rc : CInt = signature. withUnsafeMutableBytes { signaturePtr in
462- let bytes : ContiguousBytes = data. regions. count == 1 ? data. regions. first! : Array ( data)
463- return bytes. withUnsafeBytes { dataPtr in
464- context. withUnsafeBytes { contextPtr in
465- CCryptoBoringSSL_MLDSA87_sign (
466- signaturePtr. baseAddress,
467- & self . key,
468- dataPtr. baseAddress,
469- dataPtr. count,
470- contextPtr. baseAddress,
471- contextPtr. count
472- )
473- }
474- }
475- }
476-
477- guard rc == 1 else {
478- throw CryptoKitError . internalBoringSSLError ( )
479- }
480-
481- return signature
482- }
483-
484- /// The size of the private key in bytes.
485- static let byteCount = Int ( MLDSA87_PRIVATE_KEY_BYTES)
486- }
487- }
488- }
489-
490- @available ( macOS 10 . 15 , iOS 13 , watchOS 6 , tvOS 13 , macCatalyst 13 , visionOS 1 . 0 , * )
491- extension MLDSA87 {
492- /// A ML-DSA-87 public key.
493- public struct PublicKey : Sendable {
494- private var backing : Backing
495-
496- fileprivate init ( privateKeyBacking: PrivateKey . Backing ) {
497- self . backing = Backing ( privateKeyBacking: privateKeyBacking)
498- }
499-
500- /// Initialize a ML-DSA-87 public key from a raw representation.
501- ///
502- /// - Parameter rawRepresentation: The public key bytes.
503- ///
504- /// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size.
505- public init ( rawRepresentation: some DataProtocol ) throws {
506- self . backing = try Backing ( rawRepresentation: rawRepresentation)
507- }
508-
509- /// The raw binary representation of the public key.
510- public var rawRepresentation : Data {
511- self . backing. rawRepresentation
512- }
513-
514- /// Verify a signature for the given data.
515- ///
516- /// - Parameters:
517- /// - signature: The signature to verify.
518- /// - data: The message to verify the signature against.
519- ///
520- /// - Returns: `true` if the signature is valid, `false` otherwise.
521- public func isValidSignature< S: DataProtocol , D: DataProtocol > ( _ signature: S , for data: D ) -> Bool {
522- let context : Data ? = nil
523- return self . backing. isValidSignature ( signature, for: data, context: context)
524- }
525-
526- /// Verify a signature for the given data.
527- ///
528- /// - Parameters:
529- /// - signature: The signature to verify.
530- /// - data: The message to verify the signature against.
531- /// - context: The context to use for the signature verification.
532- ///
533- /// - Returns: `true` if the signature is valid, `false` otherwise.
534- public func isValidSignature< S: DataProtocol , D: DataProtocol , C: DataProtocol > (
535- _ signature: S ,
536- for data: D ,
537- context: C
538- ) -> Bool {
539- self . backing. isValidSignature ( signature, for: data, context: context)
540- }
541-
542- /// The size of the public key in bytes.
543- static let byteCount = Backing . byteCount
544-
545- fileprivate final class Backing {
546- private var key : MLDSA87_public_key
547-
548- init ( privateKeyBacking: PrivateKey . Backing ) {
549- self . key = . init( )
550- CCryptoBoringSSL_MLDSA87_public_from_private ( & self . key, & privateKeyBacking. key)
551- }
552-
553- /// Initialize a ML-DSA-87 public key from a raw representation.
554- ///
555- /// - Parameter rawRepresentation: The public key bytes.
556- ///
557- /// - Throws: `CryptoKitError.incorrectKeySize` if the raw representation is not the correct size.
558- init ( rawRepresentation: some DataProtocol ) throws {
559- guard rawRepresentation. count == MLDSA87 . PublicKey. Backing. byteCount else {
560- throw CryptoKitError . incorrectKeySize
561- }
562-
563- self . key = . init( )
564-
565- let bytes : ContiguousBytes =
566- rawRepresentation. regions. count == 1
567- ? rawRepresentation. regions. first!
568- : Array ( rawRepresentation)
569- try bytes. withUnsafeBytes { rawBuffer in
570- try rawBuffer. withMemoryRebound ( to: UInt8 . self) { buffer in
571- var cbs = CBS ( data: buffer. baseAddress, len: buffer. count)
572- guard CCryptoBoringSSL_MLDSA87_parse_public_key ( & self . key, & cbs) == 1 else {
573- throw CryptoKitError . internalBoringSSLError ( )
574- }
575- }
576- }
577- }
578-
579- /// The raw binary representation of the public key.
580- var rawRepresentation : Data {
581- var cbb = CBB ( )
582- // The following BoringSSL functions can only fail on allocation failure, which we define as impossible.
583- CCryptoBoringSSL_CBB_init ( & cbb, MLDSA87 . PublicKey. Backing. byteCount)
584- defer { CCryptoBoringSSL_CBB_cleanup ( & cbb) }
585- CCryptoBoringSSL_MLDSA87_marshal_public_key ( & cbb, & self . key)
586- return Data ( bytes: CCryptoBoringSSL_CBB_data ( & cbb) , count: CCryptoBoringSSL_CBB_len ( & cbb) )
587- }
588-
589- /// Verify a signature for the given data.
590- ///
591- /// - Parameters:
592- /// - signature: The signature to verify.
593- /// - data: The message to verify the signature against.
594- /// - context: The context to use for the signature verification.
595- ///
596- /// - Returns: `true` if the signature is valid, `false` otherwise.
597- func isValidSignature< S: DataProtocol , D: DataProtocol , C: DataProtocol > (
598- _ signature: S ,
599- for data: D ,
600- context: C ?
601- ) -> Bool {
602- let signatureBytes : ContiguousBytes =
603- signature. regions. count == 1 ? signature. regions. first! : Array ( signature)
604- return signatureBytes. withUnsafeBytes { signaturePtr in
605- let dataBytes : ContiguousBytes = data. regions. count == 1 ? data. regions. first! : Array ( data)
606- let rc : CInt = dataBytes. withUnsafeBytes { dataPtr in
607- context. withUnsafeBytes { contextPtr in
608- CCryptoBoringSSL_MLDSA87_verify (
609- & self . key,
610- signaturePtr. baseAddress,
611- signaturePtr. count,
612- dataPtr. baseAddress,
613- dataPtr. count,
614- contextPtr. baseAddress,
615- contextPtr. count
616- )
617- }
618- }
619- return rc == 1
620- }
621- }
622-
623- /// The size of the public key in bytes.
624- static let byteCount = Int ( MLDSA87_PUBLIC_KEY_BYTES)
625- }
626- }
627- }
628-
629- @available ( macOS 10 . 15 , iOS 13 , watchOS 6 , tvOS 13 , macCatalyst 13 , visionOS 1 . 0 , * )
630- extension MLDSA87 {
631- /// The size of the signature in bytes.
632- private static let signatureByteCount = Int ( MLDSA87_SIGNATURE_BYTES)
633- }
634-
635329private enum MLDSA {
636330 /// The size of the seed in bytes.
637331 fileprivate static let seedByteCount = 32
0 commit comments