cafe 1.0.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package cafe --version 1.0.1
                    
NuGet\Install-Package cafe -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="cafe" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="cafe" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="cafe" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add cafe --version 1.0.1
                    
#r "nuget: cafe, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package cafe@1.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=cafe&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=cafe&version=1.0.1
                    
Install as a Cake Tool

BouncyCastle TLS 1.3 Handshake Flow

Based on BouncyCastle C# source (bc-csharp-master/crypto/src/tls/).

State Machine

Key states defined in TlsProtocol.cs:

State Value Description
CS_START 0 Initial, waiting for ClientHello
CS_CLIENT_HELLO 1 ClientHello received
CS_SERVER_HELLO_RETRY_REQUEST 2 HelloRetryRequest sent
CS_CLIENT_HELLO_RETRY 3 Second ClientHello received
CS_SERVER_HELLO 4 ServerHello sent
CS_SERVER_ENCRYPTED_EXTENSIONS 5 EncryptedExtensions sent
CS_SERVER_CERTIFICATE 7 Certificate sent
CS_SERVER_FINISHED 20 Server Finished sent
CS_CLIENT_FINISHED 18 Client Finished received
CS_END 21 Handshake complete

Full Handshake Sequence (No HelloRetryRequest)

Client                          Server
  |                               |
  |  1. ClientHello               |
  |------------------------------>|  CS_START -> CS_CLIENT_HELLO
  |                               |  ReceiveClientHelloMessage()
  |                               |  Generate13ServerHello()
  |                               |    - Negotiate version/cipher suite
  |                               |    - ECDHE key exchange (embedded)
  |                               |    - Derive earlySecret, handshakeSecret, masterSecret
  |                               |
  |  2. ServerHello               |
  |<------------------------------|  CS_SERVER_HELLO
  |                               |  SendServerHelloMessage()
  |                               |
  |  [ChangeCipherSpec]           |
  |<------------------------------|  Middlebox compatibility (RFC 8446 D.4)
  |                               |
  |  === Encrypted from here ===  |
  |                               |  Send13ServerHelloCoda()
  |                               |    Establish13PhaseHandshake()
  |                               |      -> derive "c hs traffic", "s hs traffic"
  |                               |    EnablePendingCipherWrite()
  |                               |
  |  3. EncryptedExtensions       |
  |<------------------------------|  CS_SERVER_ENCRYPTED_EXTENSIONS
  |                               |  Send13EncryptedExtensionsMessage()
  |                               |
  |  4. [CertificateRequest]      |
  |<------------------------------|  (optional, client auth)
  |                               |
  |  5. Certificate               |
  |<------------------------------|  CS_SERVER_CERTIFICATE
  |                               |  Establish13ServerCredentials() -> GetCredentials()
  |                               |  Send13CertificateMessage()
  |                               |    Certificate.Encode() requires:
  |                               |      TLS 1.3: certificateRequestContext = EmptyBytes (not null)
  |                               |      TLS 1.2: certificateRequestContext = null
  |                               |
  |  6. CertificateVerify         |
  |<------------------------------|  Generate13CertificateVerify()
  |                               |    TLS 1.3 only allows RSA-PSS (not PKCS#1 v1.5)
  |                               |    SignatureAndHashAlgorithm must use Intrinsic hash
  |                               |
  |  7. Finished                  |
  |<------------------------------|  CS_SERVER_FINISHED
  |                               |  Send13FinishedMessage()
  |                               |  Establish13PhaseApplication()
  |                               |    -> derive "c ap traffic", "s ap traffic"
  |                               |  EnablePendingCipherWrite()
  |                               |
  |  8. [Certificate]             |
  |------------------------------>|  (only if CertificateRequest was sent)
  |  9. [CertificateVerify]       |
  |------------------------------>|
  |                               |
  |  10. Finished                 |
  |------------------------------>|  CS_CLIENT_FINISHED
  |                               |  Receive13ClientFinished()
  |                               |    Verify client's verify_data
  |                               |  EnablePendingCipherRead()
  |                               |  CompleteHandshake()
  |                               |
  | <==== Application Data ====> |  CS_END

Key Exchange (ECDHE)

TLS 1.3 key exchange happens inside Generate13ServerHello(), NOT via the m_keyExchange object:

  1. SelectKeyShareGroup() - negotiate ECDH group from client/server supported groups
  2. FindEarlyKeyShare() - check if client sent a share for the negotiated group
  3. If no match → trigger HelloRetryRequest
  4. If match → create TlsAgreement:
    • agreement.ReceivePeerValue(clientShare.KeyExchange) - feed client's public key
    • agreement.GenerateEphemeral() - generate server ephemeral key pair
    • agreement.CalculateSecret() - compute shared secret

Secret Derivation

Three phases of key derivation via HKDF:

0-RTT:  earlySecret = HKDF-Extract(0, PSK_or_0)
                              |
Handshake: handshakeSecret = HKDF-Extract(derivedSecret, sharedSecret)
                              |
App:       masterSecret = HKDF-Extract(derivedSecret, 0)
  • Establish13PhaseSecrets() - derives all three phase secrets
  • Establish13PhaseHandshake() - derives handshake traffic keys from handshakeSecret
  • Establish13PhaseApplication() - derives application traffic keys from masterSecret

TLS 1.3 vs TLS 1.2 Differences in BouncyCastle

Aspect TLS 1.2 TLS 1.3
KeyExchangeAlgorithm ECDHE_RSA(19), DHE_RSA(5), etc. NULL(0)
Certificate.RequestContext must be null must be non-null (EmptyBytes for server)
CertificateVerify signature RSA PKCS#1 v1.5 allowed RSA-PSS only
SignatureAndHashAlgorithm for PSS GetInstance(sha256, rsa_pss_rsae_sha256) Use static fields: SignatureAndHashAlgorithm.rsa_pss_rsae_sha256 (hash=Intrinsic)
Key exchange object m_keyExchange embedded in Generate13ServerHello()
Encryption start after ChangeCipherSpec after ServerHello (all subsequent messages encrypted)

Pitfalls Encountered

1. KeyExchangeAlgorithm.NULL (0)

TLS 1.3 cipher suites map to KeyExchangeAlgorithm.NULL = 0. DefaultTlsServer.GetCredentials() doesn't handle this case, throws internal_error. Fix: override GetCredentials() to handle NULL.

2. Certificate.Encode() certificateRequestContext

Certificate constructed via new Certificate(TlsCertificate[]) sets certificateRequestContext = null. TLS 1.3's Encode() asserts it must be non-null. Fix: for TLS 1.3, reconstruct with new Certificate(TlsUtilities.EmptyBytes, entries).

3. RSA-PSS SignatureAndHashAlgorithm

GetInstance(HashAlgorithm.sha256, SignatureAlgorithm.rsa_pss_rsae_sha256) creates a wrong instance (hash=4). The correct instance has hash=8 (Intrinsic). Fix: use SignatureAndHashAlgorithm.rsa_pss_rsae_sha256 static field. TLS 1.3 clients reject PKCS#1 v1.5 in CertificateVerify with illegal_parameter(47).

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.138 59 5/17/2026
1.0.1 64 5/8/2026
1.0.0 60 5/7/2026

初始版本