silk.tls.signature.
Check a TLS 1.3 or TLS 1.2 handshake signature with the public key of a peer's leaf certificate, and sign one with a leaf's private key.
When to use#
silk.tls.client uses this module for the server's CertificateVerify, and silk.tls.server
uses it for a client certificate's. Call HandshakeSignature.verify directly only when you
build your own TLS 1.3 handshake.
Details#
HandshakeSignature.verify takes a TLS SignatureScheme code and checks that it fits the
certificate's key: ecdsa_secp256r1_sha256 (1027) and ecdsa_secp384r1_sha384 (1283) for an
EC key on that curve, rsa_pss_rsae_sha256, _sha384 and _sha512 (2052, 2053, 2054) for an
rsaEncryption key, with a salt as long as the digest, and ed25519 (2055) for an Ed25519 key.
With TlsVersion Tls12 it also takes rsa_pkcs1_sha256, _sha384 and _sha512 (1025,
1281, 1537) for an rsaEncryption key, and the two ECDSA schemes for a key on either curve,
because TLS 1.2 ties the ECDSA schemes to a hash only. HandshakeSignature.keyType gives the
key type of a certificate.
SigningKey is the private key of a leaf certificate, for the side that signs. It checks that
it matches a certificate, picks a scheme from a peer's SchemeSet, and signs.
Errors#
SignatureFailurefor a scheme that this module does not know, a scheme that does not fit the key, or a signature that does not verify.
Gotchas#
The message is the full signed content: for TLS 1.3, the 64 spaces, the context string, a zero byte, and the transcript hash of RFC 8446 section 4.4.3; for a TLS 1.2 ServerKeyExchange, the two hello random values and the key exchange parameters; for a TLS 1.2 CertificateVerify, all handshake messages so far. This module does not build it.
Examples#
Reject a scheme that this module does not know#
import silk.core.result { Result }
import silk.tls.signature { CertificateKeyType, HandshakeSignature, SignatureFailure }
pub fn main() -> i32 {
// 513 is rsa_pkcs1_sha256, which TLS 1.3 does not use for CertificateVerify.
return match HandshakeSignature.schemeKeyType(513) {
Result<CertificateKeyType, SignatureFailure>.Failure { error } => match error {
SignatureFailure.UnsupportedScheme => 0
_ => 1
}
Result<CertificateKeyType, SignatureFailure>.Success { .. } => 2
}
}Import as HandshakeSignature with import silk.tls.signature { HandshakeSignature }.
Public declarations: 7.
CertificateKeyType#
pub enum CertificateKeyTypeThe type of a certificate's public key, as far as TLS 1.3 signatures go.
EcdsaP256#
EcdsaP256An id-ecPublicKey key on secp256r1.
EcdsaP384#
EcdsaP384An id-ecPublicKey key on secp384r1.
Ed25519#
Ed25519An id-Ed25519 key.
Rsa#
RsaAn rsaEncryption key.
SignatureFailure#
pub union SignatureFailureWhy a CertificateVerify signature did not verify.
UnsupportedScheme#
UnsupportedSchemeThe scheme is not one that this module knows.
KeyMismatch#
KeyMismatchThe scheme does not fit the type of the certificate's key.
Ecdsa#
EcdsaECDSA P-256 with SHA-256 failed.
Field error#
pub error: P256SignatureErrorThe primitive failure.
EcdsaP384#
EcdsaP384ECDSA P-384 with SHA-384 failed.
Field error#
pub error: P384SignatureErrorThe primitive failure.
Rsa#
RsaRSA-PSS or RSA PKCS #1 v1.5 failed, or the certificate's RSA key is not valid.
Field error#
pub error: RsaErrorThe primitive failure.
Ed25519#
Ed25519Ed25519 failed, or the certificate's Ed25519 key is not valid.
Field error#
pub error: Ed25519ErrorThe primitive failure.
Implementation Copy for SignatureFailure#
impl Copy for SignatureFailureImplementation Debug for SignatureFailure#
impl Debug for SignatureFailureOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
! WriterError
? &mut WriterWrites the name of the variant and its fields, such as Ecdsa { ... }.
HandshakeSignature#
pub struct HandshakeSignatureFunctions that check TLS handshake signatures.
Implementation HandshakeSignature#
impl HandshakeSignatureAssociated function keyType#
pub fn keyType(certificate: &Certificate) -> Option<CertificateKeyType>Returns the type of certificate's public key, or None for a key that no TLS 1.3 scheme of
this module signs with.
Associated function schemeKeyType#
pub fn schemeKeyType(scheme: usize) -> Result<CertificateKeyType, SignatureFailure>Returns the key type that the TLS SignatureScheme code scheme signs with.
Errors#
UnsupportedSchemefor a scheme that this module does not know.
Associated function verify#
pub fn verify(
certificate: &Certificate,
scheme: usize,
message: &[u8],
signature: &[u8],
version: TlsVersion,
) -> Result<(), SignatureFailure>Checks that signature signs message under scheme with the public key of certificate,
with the scheme rules of version.
Errors#
UnsupportedSchemeorKeyMismatchfor a scheme that this module does not know, thatversiondoes not allow, or that does not fit the key.Ecdsa,EcdsaP384,Rsa, orEd25519for a key or a signature that is not valid.
Associated function digestLength#
pub fn digestLength(scheme: usize) -> Option<usize>Returns the digest length of a scheme that TLS 1.2 CertificateVerify signs by digest with
SigningKey.signDigest and HandshakeSignature.verifyDigest: 32 for
ecdsa_secp256r1_sha256, rsa_pss_rsae_sha256, and rsa_pkcs1_sha256, and 48 for
ecdsa_secp384r1_sha384, rsa_pss_rsae_sha384, and rsa_pkcs1_sha384. Returns None for
any other scheme.
Associated function verifyDigest#
pub fn verifyDigest(
certificate: &Certificate,
scheme: usize,
digest: &[u8],
signature: &[u8],
) -> Result<(), SignatureFailure>Checks that signature signs digest under scheme with the public key of certificate,
as a TLS 1.2 CertificateVerify does. digest is the hash of the handshake messages under the
hash of scheme, which must be one that HandshakeSignature.digestLength knows. An ECDSA
scheme names only its hash in TLS 1.2, so either curve may sign with either.
Errors#
UnsupportedSchemefor another scheme, or a digest of the wrong length.KeyMismatchfor a scheme that does not fit the key.Ecdsa,EcdsaP384, orRsafor a key or a signature that is not valid.
SchemeSet#
pub struct SchemeSetA set of TLS SignatureScheme codes that this module knows, such as the ones that a peer
offers in signature_algorithms. Unknown codes are left out.
Implementation Copy for SchemeSet#
impl Copy for SchemeSetImplementation SchemeSet#
impl SchemeSetAssociated function empty#
pub fn empty() -> SchemeSetReturns an empty set.
Method insert#
pub fn insert(self: &mut Self, scheme: usize) -> ()Adds scheme to the set. A code that this module does not know is ignored.
Method contains#
pub fn contains(self: &Self, scheme: usize) -> boolReturns whether the set holds scheme.
SIGNATURE_LIMIT#
pub const SIGNATURE_LIMIT: usizeThe longest signature that SigningKey.sign writes: an 8192-bit RSA signature.
SigningError#
pub union SigningErrorWhy SigningKey.sign did not sign.
UnsupportedScheme#
UnsupportedSchemeThe scheme is not one that this key signs with.
OutputTooShort#
OutputTooShortThe output is shorter than the signature.
Rsa#
RsaRSA signing failed.
Field error#
pub error: RsaErrorThe primitive failure.
Implementation Copy for SigningError#
impl Copy for SigningErrorImplementation Debug for SigningError#
impl Debug for SigningErrorOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut WriterWrites the name of the variant and its fields, such as Rsa { ... }.
SigningKey#
pub union SigningKeyThe private key of a leaf certificate, which signs CertificateVerify, or a TLS 1.2 ServerKeyExchange.
EcdsaP256#
EcdsaP256An ECDSA P-256 key, used with the ecdsa_secp256r1_sha256 scheme.
Field key#
pub key: P256The private key.
EcdsaP384#
EcdsaP384An ECDSA P-384 key, used with the ecdsa_secp384r1_sha384 scheme.
Field key#
pub key: P384The private key.
Ed25519#
Ed25519An Ed25519 key, used with the ed25519 scheme.
Field key#
pub key: Ed25519PrivateKeyThe private key.
Rsa#
RsaAn RSA key for an rsaEncryption certificate, used with the rsa_pss_rsae_sha256,
rsa_pss_rsae_sha384, or rsa_pss_rsae_sha512 scheme, in that order of preference. In TLS
1.2, when the peer offers none of them, it signs with rsa_pkcs1_sha256, rsa_pkcs1_sha384,
or rsa_pkcs1_sha512.
Field key#
pub key: RsaPrivateKeyThe private key.
Implementation SigningKey#
impl SigningKeyMethod matches#
pub fn matches(self: &Self, certificate: &Certificate) -> boolReturns whether certificate's public key is the public key of this key, with the matching
algorithm.
Method chooseScheme#
pub fn chooseScheme(self: &Self, offered: &SchemeSet, version: TlsVersion) -> Option<usize>Returns this key's preferred scheme among offered for a handshake of version, or None
when the peer offers none that this key signs with.
Method sign#
pub effect fn sign(self: &Self, scheme: usize, message: &[u8], output: &mut [u8]) -> Result<
usize,
SigningError
>
? &mut RandomSigns message under scheme, writes the signature to the start of output, and returns
its length. ECDSA signatures are DER, as TLS sends them. An output of SIGNATURE_LIMIT
bytes always fits.
Errors#
UnsupportedSchemefor a scheme that this key does not sign with.OutputTooShortwhenoutputcannot hold the signature.Rsawhen RSA signing fails.
Method signDigest#
pub effect fn signDigest(self: &Self, scheme: usize, digest: &[u8], output: &mut [u8]) -> Result<
usize,
SigningError
>
? &mut RandomSigns a TLS 1.2 CertificateVerify digest, the hash of the handshake messages under the
hash of scheme, writes the signature to the start of output, and returns its length.
scheme is one of ecdsa_secp256r1_sha256 and ecdsa_secp384r1_sha384 for the key's own
curve, rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pkcs1_sha256, or
rsa_pkcs1_sha384. HandshakeSignature.digestLength gives the digest length.
Errors#
UnsupportedSchemefor another scheme, a scheme that this key does not sign with, a digest of the wrong length, or an Ed25519 key, which signs only whole messages.OutputTooShortwhenoutputcannot hold the signature.Rsawhen RSA signing fails.
Category: TLS and certificates.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2, x86_64-pc-windows-msvc, wasm64-unknown-unknown.