Help us shape the future of Go! Take the 2026 Go Developer Survey

cipher

package
v1.3.101 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 13, 2026 License: AGPL-3.0 Imports: 14 Imported by: 0

README

Cipher Package - Signature Verification

This package provides optimized signature verification for Skywire.

Performance Optimization

The package has two implementations:

1. Pure Go (Default)
  • Build tag: None (default)
  • Dependencies: None
  • Speed: Fast, but 3-5x slower than CGO
  • Used by: go run, go build without tags
2. CGO with libsecp256k1 (Optimized)
  • Build tag: -tags=cgo
  • Dependencies: libsecp256k1-dev
  • Speed: 3-5x faster signature verification
  • Used by: Official Linux releases, optional for local builds

Why This Matters

DMSG uses Noise protocol with frequent signature verifications during handshakes. Under high load, this can cause:

  • High CPU usage
  • Increased memory consumption
  • Slower connection establishment

The CGO implementation using Bitcoin's secp256k1 library provides significant performance improvements.

Building with CGO Optimization

System Requirements

Arch/Manjaro:

sudo pacman -S libsecp256k1

Ubuntu/Debian:

sudo apt install libsecp256k1-dev
Local Development
# Pure Go (default, no dependencies)
make build

# With CGO optimization (requires libsecp256k1-dev)
make build-merged-cgo

Or directly:

go build -tags=cgo ./cmd/skywire
Official Releases

Linux releases are automatically built with CGO optimization using statically-linked secp256k1 libraries. This provides maximum performance while maintaining portability (no runtime dependencies).

Implementation Details

  • cipher_nocgo.go: Pure Go implementation (build tag: !cgo)
  • cipher_cgo.go: CGO implementation (build tag: cgo && !windows)
  • cipher_windows.go: Windows-specific pure Go (build tag: windows)

The appropriate implementation is selected at compile time based on build tags and platform.

Testing

Both implementations are tested to ensure identical behavior:

# Test pure Go version
go test ./pkg/skywire-utilities/pkg/cipher

# Test CGO version (requires libsecp256k1-dev)
go test -tags=cgo ./pkg/skywire-utilities/pkg/cipher

Troubleshooting

Error: secp256k1.h: No such file or directory

This means you're building with -tags=cgo but don't have libsecp256k1-dev installed. Either:

  1. Install the library (see System Requirements above)
  2. Build without -tags=cgo to use pure Go implementation

Documentation

Overview

Package cipher pkg/cipher/cipher.go c0-com-crypto github.com/skycoin/skycoin/src/cipher

Package cipher pkg/cipher/dnslabel.go c0-com-crypto

Skynet URLs of the form `<subdomain>.<pk>.skynet` need to fit each component into a DNS label. The hex form is 66 chars (33 bytes × 2), which exceeds two limits:

  • RFC 1035 caps each DNS label at 63 octets.
  • X.520 ub-common-name caps the X.509 Subject.CommonName at 64.

Either limit causes strict TLS stacks (NSS / Firefox / Chrome) to reject the leaf cert minted by the resolver's TLS-MITM mode as "improperly encoded," so HTTPS over skynet doesn't work at all with the hex form regardless of how the URL is dialed.

RFC 4648 base32 of 33 bytes is 53 chars unpadded (ceil(33*8/5)), well under 63. Lowercase is canonical for DNS (case-insensitive but lowercase is the convention) and decodes case-insensitively regardless. Padding is stripped because DNS labels can't contain '='. We use base32 rather than base64url because DNS labels are case-insensitive: base64's A/a / B/b / + / / would collide or be rewritten by intermediaries.

Package cipher pkg/cipher/utils_pubkey.go c0-com-crypto

Index

Constants

View Source
const PubKeyDNSLabelLen = 53

PubKeyDNSLabelLen is the number of base32 chars produced by DNSLabel for a 33-byte PubKey. Exposed so callers can branch between the new base32 form and the legacy 66-char hex form when parsing skynet URLs.

Variables

This section is empty.

Functions

func DeriveChildKey

func DeriveChildKey(parentSK SecKey, label string, index uint32) (PubKey, SecKey, error)

DeriveChildKey derives a child keypair from a parent secret key, deterministic and one-way: the seed is HMAC-SHA256(parentSK, label||index), a PRF whose output reveals nothing about parentSK, fed to GenerateDeterministicKeyPair. So a leaked child key can't expose the parent, the same (parentSK, label, index) always yields the same key (regenerable — no separate backup), and label + index namespace distinct child identities from one root. The label should be a purpose-scoped domain string (e.g. "skywire-standalone-hypervisor:v1:").

func GenerateDeterministicKeyPair

func GenerateDeterministicKeyPair(seed []byte) (PubKey, SecKey, error)

GenerateDeterministicKeyPair generates deterministic key pair

func GenerateKeyPair

func GenerateKeyPair() (PubKey, SecKey)

GenerateKeyPair creates key pair

func RandByte

func RandByte(n int) []byte

RandByte returns rand N bytes

func SamePubKeys

func SamePubKeys(pks1, pks2 []PubKey) bool

SamePubKeys returns true when the provided public key slices have the same keys. The slices do not need to be in the same order. It is assumed that there are no duplicate elements within the slices.

func VerifyPubKeySignedHashLight

func VerifyPubKeySignedHashLight(pubkey cipher.PubKey, sig cipher.Sig, hash cipher.SHA256) error

VerifyPubKeySignedHashLight uses standard Skycoin implementation This is your original optimized version that skips pubkey recovery

func VerifyPubKeySignedPayload

func VerifyPubKeySignedPayload(pubkey PubKey, sig Sig, payload []byte) error

VerifyPubKeySignedPayload verifies that SHA256 hash of the payload was signed by PubKey

Types

type PubKey

type PubKey cipher.PubKey

PubKey is a wrapper type for cipher.PubKey that implements common golang interfaces.

func NewPubKey

func NewPubKey(b []byte) (PubKey, error)

NewPubKey converts []byte to a PubKey

func ParseDNSLabel

func ParseDNSLabel(label string) (PubKey, error)

ParseDNSLabel decodes a base32 PubKey label produced by DNSLabel back into a PubKey. Input is treated case-insensitively. Returns an error when the input is not a valid 33-byte base32 encoding.

func (PubKey) Big

func (pk PubKey) Big() *big.Int

Big returns the big.Int representation of the public key.

func (PubKey) DNSLabel

func (pk PubKey) DNSLabel() string

DNSLabel returns the PubKey as a lowercase, unpadded base32 string suitable for use as a single DNS label inside a skynet hostname.

func (PubKey) Hex

func (pk PubKey) Hex() string

Hex returns a hex encoded PubKey string

func (PubKey) MarshalBinary

func (pk PubKey) MarshalBinary() ([]byte, error)

MarshalBinary implements encoding.BinaryMarshaler.

func (PubKey) MarshalText

func (pk PubKey) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler. Writes hex bytes directly into a freshly-allocated buffer instead of going through `[]byte(pk.Hex())`, which would round-trip through an intermediate string allocation. Halves the per-marshal allocation in the jsoniter / dmsg-discovery hot path that serializes lots of PKs.

func (PubKey) Null

func (pk PubKey) Null() bool

Null returns true if PubKey is the null PubKey

func (*PubKey) Set

func (pk *PubKey) Set(s string) error

Set implements pflag.Value for PubKey.

func (PubKey) String

func (pk PubKey) String() string

String implements fmt.Stringer for PubKey. Returns Hex representation.

func (PubKey) Type

func (pk PubKey) Type() string

Type implements pflag.Value for PubKey.

func (*PubKey) UnmarshalBinary

func (pk *PubKey) UnmarshalBinary(data []byte) error

UnmarshalBinary implements encoding.BinaryUnmarshaler.

func (*PubKey) UnmarshalText

func (pk *PubKey) UnmarshalText(data []byte) error

UnmarshalText implements encoding.TextUnmarshaler.

type PubKeys

type PubKeys []PubKey

PubKeys represents a slice of PubKeys.

func (*PubKeys) Set

func (p *PubKeys) Set(list string) error

Set implements pflag.Value for PubKeys.

func (PubKeys) String

func (p PubKeys) String() string

String implements stringer for PubKeys.

func (PubKeys) Type

func (p PubKeys) Type() string

Type implements pflag.Value for PubKeys.

type SHA256

type SHA256 cipher.SHA256

SHA256 is a wrapper type for cipher.SHA256 that implements common golang interfaces.

func SHA256FromBytes

func SHA256FromBytes(b []byte) (SHA256, error)

SHA256FromBytes converts []byte to SHA256

func SumSHA256

func SumSHA256(b []byte) SHA256

SumSHA256 sum sha256

type SecKey

type SecKey cipher.SecKey

SecKey is a wrapper type for cipher.SecKey that implements common golang interfaces.

func (SecKey) Hex

func (sk SecKey) Hex() string

Hex returns a hex encoded SecKey string

func (SecKey) MarshalBinary

func (sk SecKey) MarshalBinary() ([]byte, error)

MarshalBinary implements encoding.BinaryMarshaler.

func (SecKey) MarshalText

func (sk SecKey) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler. See PubKey.MarshalText for the rationale on skipping the intermediate string allocation.

func (SecKey) Null

func (sk SecKey) Null() bool

Null returns true if SecKey is the null SecKey.

func (SecKey) PubKey

func (sk SecKey) PubKey() (PubKey, error)

PubKey recovers the public key for a secret key

func (*SecKey) Set

func (sk *SecKey) Set(s string) error

Set implements pflag.Value for SecKey.

func (SecKey) String

func (sk SecKey) String() string

String implements fmt.Stringer for SecKey. Returns Hex representation.

func (*SecKey) Type

func (sk *SecKey) Type() string

Type implements pflag.Value for SecKey.

func (*SecKey) UnmarshalBinary

func (sk *SecKey) UnmarshalBinary(data []byte) error

UnmarshalBinary implements encoding.BinaryUnmarshaler.

func (*SecKey) UnmarshalText

func (sk *SecKey) UnmarshalText(data []byte) error

UnmarshalText implements encoding.TextUnmarshaler.

type Sig

type Sig cipher.Sig

Sig is a wrapper type for cipher.Sig that implements common golang interfaces.

func SignPayload

func SignPayload(payload []byte, sec SecKey) (Sig, error)

SignPayload creates Sig for payload using SHA256

func (Sig) Hex

func (sig Sig) Hex() string

Hex returns a hex encoded Sig string

func (Sig) MarshalText

func (sig Sig) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler. See PubKey.MarshalText for the rationale on skipping the intermediate string allocation.

func (Sig) Null

func (sig Sig) Null() bool

Null returns true if Sig is a null Sig

func (Sig) String

func (sig Sig) String() string

String implements fmt.Stringer for Sig. Returns Hex representation.

func (*Sig) UnmarshalText

func (sig *Sig) UnmarshalText(data []byte) error

UnmarshalText implements encoding.TextUnmarshaler.

type VerifyCacheStats

type VerifyCacheStats struct {
	Hits      uint64
	Misses    uint64
	Evictions uint64
	Size      int
	Capacity  int
}

VerifyCacheStats is a snapshot of the signature-verify cache counters. Hits/Misses are counted on every verifyCacheCheck; Evictions is incremented each time the cache hits maxVerifyCacheSize and is wiped. Size is the current entry count.

func GetVerifyCacheStats

func GetVerifyCacheStats() VerifyCacheStats

GetVerifyCacheStats returns a snapshot of the signature-verify cache counters. Safe to call concurrently with verification.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL