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
|