File: DHKEM.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (147 lines) | stat: -rw-r--r-- 7,189 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftCrypto open source project
//
// Copyright (c) 2019-2020 Apple Inc. and the SwiftCrypto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.md for the list of SwiftCrypto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
#if CRYPTO_IN_SWIFTPM && !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
@_exported import CryptoKit
#else
import Foundation

/// A type that ``HPKE`` uses to encode the public key.
public protocol HPKEPublicKeySerialization {
	/// Creates a public key from an encoded representation.
	///
	/// - Parameters:
	///  - serialization: The serialized key data.
	///  - kem: The key encapsulation mechanism that the sender used to encapsulate the key.
    init<D: ContiguousBytes>(_ serialization: D, kem: HPKE.KEM) throws
	/// Creates an encoded representation of the public key.
	///
	/// - Parameters:
	///  - kem: The key encapsulation mechanism for encapsulating the key.
    ///  
	/// - Returns: The encoded key data.
    func hpkeRepresentation(kem: HPKE.KEM) throws -> Data
}

/// A type that represents the public key in a Diffie-Hellman key exchange.
public protocol HPKEDiffieHellmanPublicKey: HPKEPublicKeySerialization where EphemeralPrivateKey.PublicKey == Self {
	/// The type of the ephemeral private key.
    associatedtype EphemeralPrivateKey: HPKEDiffieHellmanPrivateKeyGeneration
}

/// A type that represents the private key in a Diffie-Hellman key exchange.

public protocol HPKEDiffieHellmanPrivateKey: DiffieHellmanKeyAgreement where PublicKey: HPKEDiffieHellmanPublicKey {}

/// A type that represents the generation of private keys in a Diffie-Hellman key exchange.
public protocol HPKEDiffieHellmanPrivateKeyGeneration: HPKEDiffieHellmanPrivateKey {
	/// Creates a private key generator.
    init()
}

extension HPKE {
	/// A container for Diffie-Hellman key encapsulation mechanisms (KEMs).
    public enum DHKEM {
        struct PublicKey<DHPK: HPKEDiffieHellmanPublicKey>: KEMPublicKey where DHPK == DHPK.EphemeralPrivateKey.PublicKey {
            let kem: HPKE.KEM
            let key: DHPK

            #if !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
            typealias EncapsulationResult = CryptoKit.KEM.EncapsulationResult
            #else
            typealias EncapsulationResult = Crypto.KEM.EncapsulationResult
            #endif

            init(_ publicKey: DHPK, kem: HPKE.KEM) throws {
                // TODO: Validate Ciphersuite Mismatches
                _ = try publicKey.hpkeRepresentation(kem: kem)
                self.key = publicKey
                self.kem = kem
            }
            
            func encapsulate() throws -> EncapsulationResult {
                let ephemeralKeys = DHPK.EphemeralPrivateKey()
                let dh =
                try ephemeralKeys.sharedSecretFromKeyAgreement(with: key)
                
                let enc = try! ephemeralKeys.publicKey.hpkeRepresentation(kem: kem)
                let selfRepresentation = try self.key.hpkeRepresentation(kem: kem)
                return EncapsulationResult(sharedSecret: HPKE.KexUtils.ExtractAndExpand(dh: dh,
                                                                                            enc: enc,
                                                                                            pkRm: selfRepresentation,
                                                                                            kem: kem,
                                                                                            kdf: kem.kdf), encapsulated: enc)
            }
        }
        
        struct PrivateKey<DHSK: HPKEDiffieHellmanPrivateKey>: KEMPrivateKey {
            let kem: HPKE.KEM
            let key: DHSK
            
            init(_ privateKey: DHSK, kem: HPKE.KEM) throws {
                // TODO: Validate Ciphersuite Mismatches
                _ = try privateKey.publicKey.hpkeRepresentation(kem: kem)
                self.key = privateKey
                self.kem = kem
            }
            
            static func generate() throws -> Self {
                fatalError("generate() is not available on HPKE.DHKEM.PrivateKey, use generate(kem:) instead.")
            }
            
            public func decapsulate(_ encapsulated: Data) throws -> SymmetricKey {
                let pkE = try DHSK.PublicKey(encapsulated, kem: kem)
                let dh = try key.sharedSecretFromKeyAgreement(with: pkE)
                
                return HPKE.KexUtils.ExtractAndExpand(dh: dh,
                                                      enc: encapsulated,
                                                      pkRm: try key.publicKey.hpkeRepresentation(kem: kem),
                                                      kem: kem, kdf: kem.kdf)
            }
            
            func decapsulate(_ encapsulated: Data, authenticating pkS: DHSK.PublicKey) throws -> SymmetricKey {
                let pkE = try DHSK.PublicKey(encapsulated, kem: kem)
                
                var dh = try Data(unsafeFromContiguousBytes: key.sharedSecretFromKeyAgreement(with: pkE))
                try dh.append(Data(unsafeFromContiguousBytes: key.sharedSecretFromKeyAgreement(with: pkS)))
                
                return HPKE.KexUtils.ExtractAndExpand(dh: dh,
                                                      enc: encapsulated,
                                                      pkRm: try key.publicKey.hpkeRepresentation(kem: kem),
                                                      pkSm: try pkS.hpkeRepresentation(kem: kem),
                                                      kem: kem,
                                                      kdf: kem.kdf)
            }
            
            func authenticateAndEncapsulateTo(_ publicKey: Self.PublicKey) throws -> (sharedSecret: SymmetricKey, encapsulated: Data) {
                let ephemeralKeys = DHSK.PublicKey.EphemeralPrivateKey()
                
                var dh = try Data(unsafeFromContiguousBytes: ephemeralKeys.sharedSecretFromKeyAgreement(with: publicKey.key))
                try dh.append(Data(unsafeFromContiguousBytes: key.sharedSecretFromKeyAgreement(with: publicKey.key)))
                let enc = try ephemeralKeys.publicKey.hpkeRepresentation(kem: kem)
                
                return (HPKE.KexUtils.ExtractAndExpand(dh: dh,
                                                       enc: enc,
                                                       pkRm: try publicKey.key.hpkeRepresentation(kem: kem),
                                                       pkSm: try key.publicKey.hpkeRepresentation(kem: kem),
                                                       kem: kem, kdf: kem.kdf), enc)
            }
            
            var publicKey: HPKE.DHKEM.PublicKey<DHSK.PublicKey> {
                return try! HPKE.DHKEM.PublicKey(key.publicKey, kem: kem)
            }
        }
    }
}

#endif // Linux or !SwiftPM