This document covers utility packages for ASN.1 encoding, OCSP certificate validation, OTR messaging, PKCS#12 handling, and NSS certificate parsing.
Package for parsing and constructing length-prefixed binary messages, including ASN.1 DER encoding.
// Builder constructs byte strings.
type Builder struct {
// contains unexported fields
}
// NewBuilder returns a new Builder using buffer for storage.
func NewBuilder(buffer []byte) *Builder
// NewFixedBuilder returns a Builder that writes to a fixed-size buffer.
func NewFixedBuilder(buffer []byte) *Builder
// SetError sets the builder's error state.
func (b *Builder) SetError(err error)
// Bytes returns the bytes written to the builder.
func (b *Builder) Bytes() []byte
// BytesOrPanic returns the bytes or panics if there's an error.
func (b *Builder) BytesOrPanic() []byte
// AddBytes appends a sequence of bytes.
func (b *Builder) AddBytes(v []byte)
// AddUint8 appends an 8-bit value.
func (b *Builder) AddUint8(v uint8)
// AddUint16 appends a big-endian 16-bit value.
func (b *Builder) AddUint16(v uint16)
// AddUint24 appends a big-endian 24-bit value.
func (b *Builder) AddUint24(v uint32)
// AddUint32 appends a big-endian 32-bit value.
func (b *Builder) AddUint32(v uint32)
// AddUint48 appends a big-endian 48-bit value.
func (b *Builder) AddUint48(v uint64)
// AddUint64 appends a big-endian 64-bit value.
func (b *Builder) AddUint64(v uint64)
// AddUint8LengthPrefixed adds a uint8 length prefix and calls f.
func (b *Builder) AddUint8LengthPrefixed(f BuilderContinuation)
// AddUint16LengthPrefixed adds a uint16 length prefix and calls f.
func (b *Builder) AddUint16LengthPrefixed(f BuilderContinuation)
// AddUint24LengthPrefixed adds a uint24 length prefix and calls f.
func (b *Builder) AddUint24LengthPrefixed(f BuilderContinuation)
// AddUint32LengthPrefixed adds a uint32 length prefix and calls f.
func (b *Builder) AddUint32LengthPrefixed(f BuilderContinuation)
// AddValue appends a MarshalingValue.
func (b *Builder) AddValue(v MarshalingValue)
// Unwrite rolls back the last n bytes written.
func (b *Builder) Unwrite(n int)
// BuilderContinuation is called to build length-prefixed sequences.
type BuilderContinuation func(child *Builder)
// MarshalingValue can marshal itself into a Builder.
type MarshalingValue interface {
Marshal(b *Builder) error
}
// BuildError wraps errors from Builder operations.
type BuildError struct {
Err error
}// AddASN1 appends an ASN.1 object.
func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation)
// AddASN1Int64 appends an ASN.1 INTEGER.
func (b *Builder) AddASN1Int64(v int64)
// AddASN1Int64WithTag appends an ASN.1 INTEGER with a specific tag.
func (b *Builder) AddASN1Int64WithTag(v int64, tag asn1.Tag)
// AddASN1Uint64 appends an ASN.1 INTEGER from uint64.
func (b *Builder) AddASN1Uint64(v uint64)
// AddASN1BigInt appends an ASN.1 INTEGER from big.Int.
func (b *Builder) AddASN1BigInt(n *big.Int)
// AddASN1Boolean appends an ASN.1 BOOLEAN.
func (b *Builder) AddASN1Boolean(v bool)
// AddASN1NULL appends an ASN.1 NULL.
func (b *Builder) AddASN1NULL()
// AddASN1OctetString appends an ASN.1 OCTET STRING.
func (b *Builder) AddASN1OctetString(bytes []byte)
// AddASN1BitString appends an ASN.1 BIT STRING.
func (b *Builder) AddASN1BitString(data []byte)
// AddASN1Enum appends an ASN.1 ENUM.
func (b *Builder) AddASN1Enum(v int64)
// AddASN1ObjectIdentifier appends an ASN.1 OBJECT IDENTIFIER.
func (b *Builder) AddASN1ObjectIdentifier(oid asn1.ObjectIdentifier)
// AddASN1GeneralizedTime appends an ASN.1 GENERALIZED TIME.
func (b *Builder) AddASN1GeneralizedTime(t time.Time)
// AddASN1UTCTime appends an ASN.1 UTC TIME.
func (b *Builder) AddASN1UTCTime(t time.Time)
// MarshalASN1 appends an ASN.1 SEQUENCE containing the values.
func (b *Builder) MarshalASN1(tag asn1.Tag, f BuilderContinuation)// String represents a byte string for parsing.
type String []byte
// Empty reports whether the string is empty.
func (s String) Empty() bool
// ReadBytes reads n bytes.
func (s *String) ReadBytes(out *[]byte, n int) bool
// CopyBytes copies n bytes to a new slice.
func (s *String) CopyBytes(n int) []byte
// Skip skips n bytes.
func (s *String) Skip(n int) bool
// ReadUint8 reads an 8-bit value.
func (s *String) ReadUint8(out *uint8) bool
// ReadUint16 reads a big-endian 16-bit value.
func (s *String) ReadUint16(out *uint16) bool
// ReadUint24 reads a big-endian 24-bit value.
func (s *String) ReadUint24(out *uint32) bool
// ReadUint32 reads a big-endian 32-bit value.
func (s *String) ReadUint32(out *uint32) bool
// ReadUint48 reads a big-endian 48-bit value.
func (s *String) ReadUint48(out *uint64) bool
// ReadUint64 reads a big-endian 64-bit value.
func (s *String) ReadUint64(out *uint64) bool
// ReadUint8LengthPrefixed reads a uint8 length-prefixed value.
func (s *String) ReadUint8LengthPrefixed(out *String) bool
// ReadUint16LengthPrefixed reads a uint16 length-prefixed value.
func (s *String) ReadUint16LengthPrefixed(out *String) bool
// ReadUint24LengthPrefixed reads a uint24 length-prefixed value.
func (s *String) ReadUint24LengthPrefixed(out *String) bool// PeekASN1Tag reports the next ASN.1 tag without reading.
func (s String) PeekASN1Tag(tag asn1.Tag) bool
// ReadASN1 reads an ASN.1 element.
func (s *String) ReadASN1(out *String, tag asn1.Tag) bool
// ReadASN1Element reads an entire ASN.1 element.
func (s *String) ReadASN1Element(out *String, tag asn1.Tag) bool
// ReadAnyASN1 reads any ASN.1 element.
func (s *String) ReadAnyASN1(out *String, outTag *asn1.Tag) bool
// ReadAnyASN1Element reads any ASN.1 element including tag.
func (s *String) ReadAnyASN1Element(out *String, outTag *asn1.Tag) bool
// ReadOptionalASN1 reads an optional ASN.1 element.
func (s *String) ReadOptionalASN1(out *String, present *bool, tag asn1.Tag) bool
// SkipASN1 skips an ASN.1 element.
func (s *String) SkipASN1(tag asn1.Tag) bool
// SkipOptionalASN1 skips an optional ASN.1 element.
func (s *String) SkipOptionalASN1(tag asn1.Tag) bool
// ReadASN1Boolean reads an ASN.1 BOOLEAN.
func (s *String) ReadASN1Boolean(out *bool) bool
// ReadOptionalASN1Boolean reads an optional ASN.1 BOOLEAN.
func (s *String) ReadOptionalASN1Boolean(out *bool, present *bool, tag asn1.Tag) bool
// ReadASN1Integer reads an ASN.1 INTEGER into big.Int.
func (s *String) ReadASN1Integer(out *big.Int) bool
// ReadOptionalASN1Integer reads an optional ASN.1 INTEGER.
func (s *String) ReadOptionalASN1Integer(out *big.Int, present *bool, tag asn1.Tag) bool
// ReadASN1Int64WithTag reads an ASN.1 INTEGER with specific tag.
func (s *String) ReadASN1Int64WithTag(out *int64, tag asn1.Tag) bool
// ReadASN1Enum reads an ASN.1 ENUM.
func (s *String) ReadASN1Enum(out *int) bool
// ReadASN1ObjectIdentifier reads an ASN.1 OBJECT IDENTIFIER.
func (s *String) ReadASN1ObjectIdentifier(out *asn1.ObjectIdentifier) bool
// ReadASN1GeneralizedTime reads an ASN.1 GENERALIZED TIME.
func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool
// ReadASN1UTCTime reads an ASN.1 UTC TIME.
func (s *String) ReadASN1UTCTime(out *time.Time) bool
// ReadASN1BitString reads an ASN.1 BIT STRING.
func (s *String) ReadASN1BitString(out *asn1.BitString) bool
// ReadASN1BitStringAsBytes reads an ASN.1 BIT STRING into bytes.
func (s *String) ReadASN1BitStringAsBytes(out *[]byte) bool
// ReadASN1Bytes reads an ASN.1 value as bytes.
func (s *String) ReadASN1Bytes(out *[]byte, tag asn1.Tag) bool
// ReadOptionalASN1OctetString reads an optional ASN.1 OCTET STRING.
func (s *String) ReadOptionalASN1OctetString(out *[]byte, present *bool, tag asn1.Tag) boolASN.1 constants and tag handling for the cryptobyte package.
const (
BOOLEAN = Tag(1)
INTEGER = Tag(2)
BIT_STRING = Tag(3)
OCTET_STRING = Tag(4)
NULL = Tag(5)
OBJECT_IDENTIFIER = Tag(6)
ENUM = Tag(10)
UTF8String = Tag(12)
SEQUENCE = Tag(16 | classConstructed)
SET = Tag(17 | classConstructed)
PrintableString = Tag(19)
T61String = Tag(20)
IA5String = Tag(22)
UTCTime = Tag(23)
GeneralizedTime = Tag(24)
GeneralString = Tag(27)
)// Tag is an ASN.1 identifier octet.
type Tag uint8
// Constructed returns the constructed form of the tag.
func (t Tag) Constructed() Tag
// ContextSpecific returns the context-specific form of the tag.
func (t Tag) ContextSpecific() TagOCSP (Online Certificate Status Protocol) implementation for certificate revocation checking (RFC 2560).
// Certificate status values
const (
Good = 0
Revoked = 1
Unknown = 2
ServerFailed = 3 // Deprecated
)
// Revocation reason codes
const (
Unspecified = 0
KeyCompromise = 1
CACompromise = 2
AffiliationChanged = 3
Superseded = 4
CessationOfOperation = 5
CertificateHold = 6
RemoveFromCRL = 8
PrivilegeWithdrawn = 9
AACompromise = 10
)var (
MalformedRequestErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x01}
InternalErrorErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x02}
TryLaterErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x03}
SigRequredErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x05}
UnauthorizedErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x06}
)// Request represents an OCSP request.
type Request struct {
HashAlgorithm crypto.Hash
IssuerNameHash []byte
IssuerKeyHash []byte
SerialNumber *big.Int
}
// ParseRequest parses an OCSP request from DER bytes.
func ParseRequest(bytes []byte) (*Request, error)
// Marshal serializes the request to DER.
func (req *Request) Marshal() ([]byte, error)
// RequestOptions contains options for creating OCSP requests.
type RequestOptions struct {
Hash crypto.Hash
}
// CreateRequest creates an OCSP request.
func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error)
// Response represents an OCSP response.
type Response struct {
Raw []byte
Status int
SerialNumber *big.Int
ProducedAt time.Time
ThisUpdate time.Time
NextUpdate time.Time
RevokedAt time.Time
RevocationReason int
Certificate *x509.Certificate
TBSResponseData []byte
Signature []byte
SignatureAlgorithm x509.SignatureAlgorithm
IssuerHash crypto.Hash
RawResponderName []byte
ResponderKeyHash []byte
Extensions []pkix.Extension
ExtraExtensions []pkix.Extension
}
// ParseResponse parses an OCSP response.
func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error)
// ParseResponseForCert parses an OCSP response for a specific certificate.
func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Response, error)
// CheckSignatureFrom verifies the response signature.
func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error
// CreateResponse creates an OCSP response.
func CreateResponse(issuer, responderCert *x509.Certificate, template Response, priv crypto.Signer) ([]byte, error)
// ResponseStatus represents the OCSP response status.
type ResponseStatus int
const (
Success ResponseStatus = 0
Malformed ResponseStatus = 1
InternalError ResponseStatus = 2
TryLater ResponseStatus = 3
SignatureRequired ResponseStatus = 5
Unauthorized ResponseStatus = 6
)
func (r ResponseStatus) String() string
// ResponseError represents an OCSP error response.
type ResponseError struct {
Status ResponseStatus
}
func (r ResponseError) Error() string
// ParseError represents a parse error.
type ParseError string
func (p ParseError) Error() stringpackage main
import (
"crypto/x509"
"log"
"net/http"
"io"
"golang.org/x/crypto/ocsp"
)
func main() {
// Load certificate and issuer
cert, _ := x509.ParseCertificate(certDER)
issuer, _ := x509.ParseCertificate(issuerDER)
// Create OCSP request
ocspReq, _ := ocsp.CreateRequest(cert, issuer, nil)
// Send request to OCSP server
httpReq, _ := http.NewRequest("POST", cert.OCSPServer[0], bytes.NewReader(ocspReq))
httpReq.Header.Set("Content-Type", "application/ocsp-request")
httpResp, _ := http.DefaultClient.Do(httpReq)
defer httpResp.Body.Close()
// Parse response
ocspResp, _ := io.ReadAll(httpResp.Body)
resp, _ := ocsp.ParseResponse(ocspResp, issuer)
// Check certificate status
switch resp.Status {
case ocsp.Good:
log.Println("Certificate is valid")
case ocsp.Revoked:
log.Printf("Certificate revoked at %v", resp.RevokedAt)
case ocsp.Unknown:
log.Println("Certificate status unknown")
}
}Off-The-Record messaging protocol v2. Deprecated - OTRv2 is deprecated.
var ErrorPrefix = "?OTR Error:"
var QueryMessage = "?OTRv2?"// Conversation represents a relation with a peer.
type Conversation struct {
// PrivateKey is the local private key.
PrivateKey *PrivateKey
// Rand provides entropy.
Rand io.Reader
// FragmentSize is the maximum message size before fragmentation.
FragmentSize int
// SSID is the session ID.
SSID [8]byte
// TheirPublicKey is the peer's public key (once established).
TheirPublicKey PublicKey
// contains unexported fields
}
// Receive processes an incoming message.
func (c *Conversation) Receive(in []byte) (out []byte, encrypted bool, change SecurityChange, toSend [][]byte, err error)
// Send encrypts and authenticates a message.
func (c *Conversation) Send(msg []byte) ([][]byte, error)
// End terminates the conversation.
func (c *Conversation) End() (toSend [][]byte)
// IsEncrypted reports whether the conversation is encrypted.
func (c *Conversation) IsEncrypted() bool
// Authenticate initiates Socialist Millionaire Protocol.
func (c *Conversation) Authenticate(question string, mutualSecret []byte) (toSend [][]byte, err error)
// SMPQuestion returns the SMP question, if any.
func (c *Conversation) SMPQuestion() string
// PrivateKey represents an OTR private key.
type PrivateKey struct {
PublicKey
dsa.PrivateKey
}
// Generate generates a new OTR key pair.
func (priv *PrivateKey) Generate(rand io.Reader) error
// Import imports a private key from libotr format.
func (priv *PrivateKey) Import(in []byte) error
// Parse parses a private key.
func (priv *PrivateKey) Parse(r io.Reader) error
// Serialize serializes the private key.
func (priv *PrivateKey) Serialize(w io.Writer)
// Sign signs data.
func (priv *PrivateKey) Sign(rand io.Reader, data []byte) ([]byte, error)
// PublicKey represents an OTR public key.
type PublicKey struct {
dsa.PublicKey
}
// Parse parses a public key.
func (pub *PublicKey) Parse(r io.Reader) (int, error)
// Serialize serializes the public key.
func (pub *PublicKey) Serialize(w io.Writer)
// Fingerprint returns the key fingerprint.
func (pub *PublicKey) Fingerprint() []byte
// Verify verifies a signature.
func (pub *PublicKey) Verify(data, sig []byte) error
// SecurityChange indicates security state changes.
type SecurityChange int
const (
NoChange SecurityChange = iota
NewKeys
SMPSecretNeeded
SMPComplete
SMPFailed
ConversationEnded
)PKCS#12 file format support for loading certificates and private keys.
var (
ErrDecryption = errors.New("pkcs12: decryption error, incorrect padding")
ErrIncorrectPassword = errors.New("pkcs12: decryption password incorrect")
)// Decode extracts certificate and private key from PFX/P12 data.
func Decode(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, err error)
// ToPEM converts PFX/P12 data to PEM blocks.
func ToPEM(pfxData []byte, password string) ([]*pem.Block, error)// NotImplementedError indicates an unimplemented PKCS#12 feature.
type NotImplementedError string
func (e NotImplementedError) Error() stringpackage main
import (
"crypto/tls"
"io/ioutil"
"log"
"golang.org/x/crypto/pkcs12"
)
func main() {
// Read P12 file
p12Data, _ := ioutil.ReadFile("certificate.p12")
// Decode with password
privateKey, cert, err := pkcs12.Decode(p12Data, "password")
if err != nil {
log.Fatal(err)
}
// Create TLS certificate
tlsCert := tls.Certificate{
Certificate: [][]byte{cert.Raw},
PrivateKey: privateKey,
Leaf: cert,
}
// Use in TLS config
config := &tls.Config{
Certificates: []tls.Certificate{tlsCert},
}
log.Println("Loaded certificate:", cert.Subject)
}Provides a fallback certificate bundle for TLS certificate verification when the system root store is unavailable or outdated.
// Roots returns an iterator over the bundle of root certificates from the NSS trust store.
// The Root.Certificate slice must be treated as read-only and should not be modified.
func Roots() iter.Seq[Root]// Root represents a root certificate parsed from the NSS trust store.
type Root struct {
// Certificate is the DER-encoded certificate (read-only; do not modify!).
Certificate []byte
// Constraint is nil if the root is unconstrained. If Constraint is non-nil,
// the certificate has additional constraints that cannot be encoded in
// X.509, and when building a certificate chain anchored with this root the
// chain should be passed to this function to check its validity.
Constraint func([]*x509.Certificate) error
}package main
import (
"crypto/tls"
"crypto/x509"
"log"
"golang.org/x/crypto/x509roots/fallback/bundle"
)
func main() {
// Create a new cert pool
pool := x509.NewCertPool()
// Iterate over the fallback root certificates
for root := range bundle.Roots() {
cert, err := x509.ParseCertificate(root.Certificate)
if err != nil {
log.Printf("Failed to parse certificate: %v", err)
continue
}
// Add certificate to pool with constraint if present
if root.Constraint != nil {
pool.AddCertWithConstraint(cert, root.Constraint)
} else {
pool.AddCert(cert)
}
}
// Use in TLS configuration
config := &tls.Config{
RootCAs: pool,
}
log.Printf("Loaded %d root certificates", len(pool.Subjects()))
}Parser for NSS certdata.txt formatted certificate lists.
// Certificate represents a trusted server authentication certificate.
type Certificate struct {
X509 *x509.Certificate
Constraints []Constraint
}
// Parse parses an NSS certdata.txt file.
func Parse(r io.Reader) ([]*Certificate, error)
// Constraint represents a certificate constraint.
type Constraint interface {
Kind() Kind
}
// Kind represents the type of constraint.
type Kind int
const (
CKA_NSS_SERVER_DISTRUST_AFTER Kind = iota
)
// DistrustAfter is a constraint indicating when to stop trusting a certificate.
type DistrustAfter time.Time
func (DistrustAfter) Kind() Kindpackage main
import (
"crypto/x509"
"log"
"os"
"golang.org/x/crypto/x509roots/nss"
)
func main() {
// Open certdata.txt
file, _ := os.Open("certdata.txt")
defer file.Close()
// Parse certificates
certs, err := nss.Parse(file)
if err != nil {
log.Fatal(err)
}
// Create cert pool
pool := x509.NewCertPool()
for _, cert := range certs {
pool.AddCert(cert.X509)
// Check constraints
for _, constraint := range cert.Constraints {
if constraint.Kind() == nss.CKA_NSS_SERVER_DISTRUST_AFTER {
distrustAfter := constraint.(nss.DistrustAfter)
log.Printf("Certificate %s distrusted after %v",
cert.X509.Subject, time.Time(distrustAfter))
}
}
}
log.Printf("Loaded %d certificates", len(certs))
}