# std/x509

## Index

- type [`Name`](#name)
  - method [`Name.display`](#namedisplay)
  - method [`Name.attributes`](#nameattributes)
- type [`Extension`](#extension)
- type [`KeyUsage`](#keyusage)
- type [`ExtKeyUsage`](#extkeyusage)
- type [`Certificate`](#certificate)
  - method [`Certificate.verify`](#certificateverify)
  - method [`Certificate.verify_hostname`](#certificateverify_hostname)
  - method [`Certificate.check_signature_from`](#certificatecheck_signature_from)
  - method [`Certificate.pem`](#certificatepem)
- type [`CertErr`](#certerr)
  - method [`CertErr.display`](#certerrdisplay)
- type [`Pkcs12`](#pkcs12)
- type [`VerifyOptions`](#verifyoptions)
- type [`Template`](#template)
- type [`CertificateRequest`](#certificaterequest)
  - method [`CertificateRequest.check_signature`](#certificaterequestcheck_signature)
  - method [`CertificateRequest.pem`](#certificaterequestpem)
- type [`RequestTemplate`](#requesttemplate)
- type [`RevokedCertificate`](#revokedcertificate)
- type [`RevocationList`](#revocationlist)
  - method [`RevocationList.check_signature_from`](#revocationlistcheck_signature_from)
- fn [`parse`](#parse)
- fn [`parse_pkcs12`](#parse_pkcs12)
- fn [`parse_pem`](#parse_pem)
- fn [`create_certificate`](#create_certificate)
- fn [`self_signed`](#self_signed)
- fn [`create_request`](#create_request)
- fn [`parse_request`](#parse_request)
- fn [`parse_revocation_list`](#parse_revocation_list)
- fn [`system_roots`](#system_roots)

## Types

### Name

```xo
struct Name {
  country: List[Str] = []
  organization: List[Str] = []
  organizational_unit: List[Str] = []
  locality: List[Str] = []
  province: List[Str] = []
  street_address: List[Str] = []
  postal_code: List[Str] = []
  serial_number: Str = ""
  common_name: Str = ""
  raw: Bytes = b""
}
```

A distinguished name (Go's pkix.Name): the common attributes, each
list in the order the name has them, and its DER. A Name to build
(Template.subject) leaves raw empty and sets the fields it needs.

[Source: `std/x509.xo:12`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L12)

#### Name.display

```xo
fn (n: Name) display() -> Str
```

RFC 2253 text, as Go's Name.String() (`CN=example.com,O=Example`).

[Source: `std/x509.xo:26`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L26)

#### Name.attributes

```xo
fn (n: Name) attributes() -> List[(Str, Str)]
```

Every attribute in the order the name has them: (OID, value).

[Source: `std/x509.xo:28`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L28)

### Extension

```xo
struct Extension {
  oid: Str
  critical: Bool
  value: Bytes
}
```

A certificate extension: its OID (dotted), whether it is critical, and
its value (the DER inside the OCTET STRING).

[Source: `std/x509.xo:32`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L32)

### KeyUsage

```xo
enum KeyUsage {
  DigitalSignature
  ContentCommitment
  KeyEncipherment
  DataEncipherment
  KeyAgreement
  CertSign
  CrlSign
  EncipherOnly
  DecipherOnly
}
```

The key usages a certificate allows (RFC 5280 4.2.1.3).

[Source: `std/x509.xo:39`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L39)

### ExtKeyUsage

```xo
enum ExtKeyUsage {
  Any
  ServerAuth
  ClientAuth
  CodeSigning
  EmailProtection
  TimeStamping
  OcspSigning
  Other(oid: Str)
}
```

The extended key usages (RFC 5280 4.2.1.12); Other keeps an OID Go has
no name for.

[Source: `std/x509.xo:53`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L53)

### Certificate

```xo
struct Certificate {
  raw: Bytes
  version: Int
  serial: Bytes
  signature_algorithm: Str
  issuer: Name
  subject: Name
  not_before: Time
  not_after: Time
  public_key: crypto.PublicKey?
  dns_names: List[Str]
  ip_addresses: List[netip.Addr]
  email_addresses: List[Str]
  uris: List[Str]
  is_ca: Bool
  max_path_len: Int?
  key_usage: List[KeyUsage]
  ext_key_usage: List[ExtKeyUsage]
  subject_key_id: Bytes
  authority_key_id: Bytes
  extensions: List[Extension]
}
```

A parsed certificate (Go's x509.Certificate).

[Source: `std/x509.xo:65`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L65)

#### Certificate.verify

```xo
fn (c: Certificate) verify(opts: VerifyOptions) -> List[List[Certificate]] ! CertErr
```

Every chain from c to one of the roots, leaf first (Go's
Certificate.Verify), or Err with Go's text.

[Source: `std/x509.xo:142`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L142)

#### Certificate.verify_hostname

```xo
fn (c: Certificate) verify_hostname(host: Str) -> () ! CertErr
```

Whether c is valid for host (a name or an IP address; Go's VerifyHostname).

[Source: `std/x509.xo:144`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L144)

#### Certificate.check_signature_from

```xo
fn (c: Certificate) check_signature_from(parent: Certificate) -> () ! CertErr
```

Whether parent's key signed c (Go's CheckSignatureFrom).

[Source: `std/x509.xo:146`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L146)

#### Certificate.pem

```xo
fn (c: Certificate) pem() -> Bytes
```

The certificate as a PEM CERTIFICATE block.

[Source: `std/x509.xo:194`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L194)

### CertErr

```xo
struct CertErr {
  msg: Str
}
```

An x509 error, with Go's text (`x509: malformed certificate`,
`x509: certificate signed by unknown authority`, ...).

[Source: `std/x509.xo:99`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L99)

#### CertErr.display

```xo
fn (e: CertErr) display() -> Str
```

[Source: `std/x509.xo:103`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L103)

### Pkcs12

```xo
struct Pkcs12 {
  key: crypto.PrivateKey
  certificate: Certificate
  ca: List[Certificate]
}
```

What a PKCS #12 file holds (std.md 18.x, golang.org/x/crypto/pkcs12).

[Source: `std/x509.xo:108`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L108)

### VerifyOptions

```xo
struct VerifyOptions {
  roots: List[Certificate]
  intermediates: List[Certificate] = []
  dns_name: Str = ""
  at: Time
  key_usages: List[ExtKeyUsage] = []
}
```

What verify checks a chain against (Go's VerifyOptions).

[Source: `std/x509.xo:126`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L126)

### Template

```xo
struct Template {
  serial: Bytes = b""
  subject: Name
  not_before: Time
  not_after: Time
  dns_names: List[Str] = []
  ip_addresses: List[netip.Addr] = []
  email_addresses: List[Str] = []
  uris: List[Str] = []
  is_ca: Bool = false
  max_path_len: Int? = None
  key_usage: List[KeyUsage] = []
  ext_key_usage: List[ExtKeyUsage] = []
  subject_key_id: Bytes = b""
  extra_extensions: List[Extension] = []
}
```

What create_certificate puts in a certificate (the fields Go's
CreateCertificate reads from its template).

[Source: `std/x509.xo:150`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L150)

### CertificateRequest

```xo
struct CertificateRequest {
  raw: Bytes
  version: Int
  signature_algorithm: Str
  subject: Name
  public_key: crypto.PublicKey?
  dns_names: List[Str]
  ip_addresses: List[netip.Addr]
  email_addresses: List[Str]
  uris: List[Str]
  extensions: List[Extension]
}
```

A certificate signing request (PKCS #10, Go's CertificateRequest).

[Source: `std/x509.xo:197`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L197)

#### CertificateRequest.check_signature

```xo
fn (q: CertificateRequest) check_signature() -> () ! CertErr
```

Whether the request's own key signed it (Go's CheckSignature).

[Source: `std/x509.xo:232`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L232)

#### CertificateRequest.pem

```xo
fn (q: CertificateRequest) pem() -> Bytes
```

The request as a PEM CERTIFICATE REQUEST block.

[Source: `std/x509.xo:234`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L234)

### RequestTemplate

```xo
struct RequestTemplate {
  subject: Name
  dns_names: List[Str] = []
  ip_addresses: List[netip.Addr] = []
  email_addresses: List[Str] = []
  uris: List[Str] = []
  extra_extensions: List[Extension] = []
}
```

What create_request puts in a request.

[Source: `std/x509.xo:213`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L213)

### RevokedCertificate

```xo
struct RevokedCertificate {
  serial: Bytes
  revoked_at: Time
  reason: Int
  extensions: List[Extension]
}
```

A certificate a CRL revokes (Go's RevocationListEntry).

[Source: `std/x509.xo:237`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L237)

### RevocationList

```xo
struct RevocationList {
  raw: Bytes
  signature_algorithm: Str
  issuer: Name
  number: Bytes
  this_update: Time
  next_update: Time?
  revoked: List[RevokedCertificate]
  authority_key_id: Bytes
  extensions: List[Extension]
}
```

A parsed certificate revocation list (Go's RevocationList).

[Source: `std/x509.xo:247`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L247)

#### RevocationList.check_signature_from

```xo
fn (l: RevocationList) check_signature_from(issuer: Certificate) -> () ! CertErr
```

Whether issuer may sign CRLs and signed l (Go's
RevocationList.CheckSignatureFrom).

[Source: `std/x509.xo:265`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L265)

## Functions

### parse

```xo
fn parse(der: Bytes) -> Certificate ! CertErr
```

The certificate of a DER (Go's ParseCertificate).

[Source: `std/x509.xo:106`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L106)

### parse_pkcs12

```xo
fn parse_pkcs12(data: Bytes, password: Str) -> Pkcs12 ! CertErr
```

The key and certificates of a .pfx or .p12 (Go's pkcs12.Decode, which needs exactly one of each: this reads
chains too). password is the text the file was made with; "" also opens a file made with no
password. 3DES and 40 bit RC2 with SHA-1 are the encryptions read, as Go's. Err is
CertErr with Go's text (`pkcs12: decryption password incorrect`).

[Source: `std/x509.xo:120`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L120)

### parse_pem

```xo
fn parse_pem(pem: Bytes) -> List[Certificate] ! CertErr
```

The certificates of a PEM text's CERTIFICATE blocks, in order; Err at the
first that does not parse.

[Source: `std/x509.xo:123`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L123)

### create_certificate

```xo
fn create_certificate(r: Rand, t: Template, public_key: crypto.PublicKey, parent: Certificate?, key: crypto.PrivateKey) -> Certificate ! CertErr uses rand
```

Go's CreateCertificate: a certificate of t for public_key, issued by
parent and signed with parent's private key, key; self-signed when
parent is None (the issuer is t's subject and key the matching private
key). The signature algorithm is Go's for the key: SHA256-RSA,
ECDSA-SHA256, -SHA384 or -SHA512 by curve, or Ed25519. Err with Go's
text for a name that is not IA5, a max_path_len on a non-CA, a key that
is not parent's, or a P-224 key (Go cannot sign with one).

[Source: `std/x509.xo:184`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L184)

### self_signed

```xo
fn self_signed(r: Rand, hosts: List[Str], now: Time, days: Int = 30) -> (Bytes, Bytes) ! CertErr uses rand
```

A certificate for development and tests, never for production: a new
ECDSA P-256 key and a self-signed certificate for hosts (DNS names or
IP addresses), organization "Xo Development", valid from now for days
(Go's generate_cert.go). Returns the certificate's PEM and the key's
PEM (PKCS #8), ready for http.tls_cert.

[Source: `std/x509.xo:191`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L191)

### create_request

```xo
fn create_request(r: Rand, t: RequestTemplate, key: crypto.PrivateKey) -> CertificateRequest ! CertErr uses rand
```

Go's CreateCertificateRequest: t's request for key's public key, signed
with key (the algorithm as create_certificate's).

[Source: `std/x509.xo:226`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L226)

### parse_request

```xo
fn parse_request(der: Bytes) -> CertificateRequest ! CertErr
```

Go's ParseCertificateRequest of a DER request. Malformed DER is
`CertErr("x509: malformed certificate request")` where Go reports
encoding/asn1's text.

[Source: `std/x509.xo:230`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L230)

### parse_revocation_list

```xo
fn parse_revocation_list(der: Bytes) -> RevocationList ! CertErr
```

Go's ParseRevocationList of a DER CRL.

[Source: `std/x509.xo:262`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L262)

### system_roots

```xo
fn system_roots(fs: Fs) -> List[Certificate] ! CertErr uses fs
```

The roots std/tls verifies servers against on this platform when a
client gives none: the system's root certificates.

[Source: `std/x509.xo:269`](https://github.com/xo-lang/xo/blob/main/std/x509.xo#L269)

