crypto

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Jun 24, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package crypto implements the cryptographic primitives used by the RADIUS protocol:

  • Response Authenticator (RFC 2865 §3): MD5 over Code+ID+Length+RequestAuth+Attributes+Secret
  • Accounting-Request Authenticator (RFC 2866 §3): MD5 over Code+ID+Length+16 zeros+Attributes+Secret
  • User-Password hiding (RFC 2865 §5.2): chained MD5 + XOR
  • Message-Authenticator (RFC 2869 §5.14): HMAC-MD5 over the entire packet

All functions are pure: callers pass the shared secret explicitly, and no state is retained. Constant-time comparison is used for verification paths.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ComputeAccountingRequestAuthenticator

func ComputeAccountingRequestAuthenticator(code byte, id byte, length uint16, attributes []byte, secret []byte) [16]byte

ComputeAccountingRequestAuthenticator calculates the Request Authenticator for an Accounting-Request packet (RFC 2866 §3).

Unlike Access-Request (which uses a random value), the Accounting-Request authenticator is itself an MD5 digest because there is no User-Password attribute to hide:

MD5(Code + ID + Length + 16 zero octets + Attributes + Secret)

func ComputeMessageAuthenticator

func ComputeMessageAuthenticator(packetBytes []byte, secret []byte) [16]byte

ComputeMessageAuthenticator calculates the HMAC-MD5 Message-Authenticator (RFC 2869 §5.14) over an entire RADIUS packet.

The caller MUST zero the 16-octet Value field of the Message-Authenticator attribute within packetBytes before calling this function. The returned digest is written into that field by the packet codec.

The shared secret is used as the HMAC key.

func ComputeResponseAuthenticator

func ComputeResponseAuthenticator(code byte, id byte, length uint16, requestAuth [16]byte, attributes []byte, secret []byte) [16]byte

ComputeResponseAuthenticator calculates the Response Authenticator used by Access-Accept, Access-Reject, Access-Challenge (RFC 2865 §3), and Accounting-Response (RFC 2866 §3).

Formula: MD5(Code + ID + Length + RequestAuth + Attributes + Secret) where Length is big-endian uint16 and RequestAuth is the 16-byte Request Authenticator from the corresponding request packet.

func DecodeTunnelInteger

func DecodeTunnelInteger(value []byte) (tag byte, hasTag bool, n uint32, err error)

DecodeTunnelInteger decodes a tagged integer tunnel attribute. Returns the tag (or 0 with hasTag=false when no tag prefix is present) and the integer value.

Ambiguity note: RFC 2868 §3.1 lets integer tunnel attributes omit the tag. When the first byte of the value falls in 0x01..0x1F the decoder cannot tell whether it is a tag or the high byte of the integer. Callers that know from context whether a tag is present should validate accordingly; this helper follows the spec's literal "0x01..0x1F means tag" rule.

func DecodeTunnelTag

func DecodeTunnelTag(value []byte) (tag byte, hasTag bool, payload []byte)

DecodeTunnelTag returns the tag and the remaining value bytes from a tagged tunnel attribute Value. If the first byte is in 0x00..0x1F it is treated as a tag and the rest is the payload; otherwise the entire Value is the payload and hasTag=false.

Per RFC 2868 §3.1 the tag field is optional: a first byte in 0x20..0xFF is the start of the actual data, not a tag.

func DecryptTunnelPassword

func DecryptTunnelPassword(value []byte, requestAuth [16]byte, secret []byte) (password []byte, tag byte, hasTag bool, err error)

DecryptTunnelPassword reverses EncryptTunnelPassword. value is the Tunnel-Password attribute Value (Salt [+ tag] + encrypted password). requestAuth is the Request Authenticator of the enclosing Access-Request.

Returns the plaintext password (with NUL padding stripped) and, when present, the tag and hasTag=true.

func DecryptUserPassword

func DecryptUserPassword(ciphertext []byte, requestAuth [16]byte, secret []byte) ([]byte, error)

DecryptUserPassword reverses EncryptUserPassword. The ciphertext length must be a non-zero multiple of 16 and at most 128 octets. Trailing NUL padding introduced during encryption is stripped from the returned plaintext.

func EncodeTunnelInteger

func EncodeTunnelInteger(tag byte, n uint32) []byte

EncodeTunnelInteger encodes a tagged integer tunnel attribute (Tunnel-Type, Tunnel-Medium-Type, Tunnel-Preference) per RFC 2868 §3.1. The wire layout is: [Tag] + 4-byte big-endian integer. When tag is 0 the prefix is omitted.

func EncodeTunnelTag

func EncodeTunnelTag(tag byte) (byte, bool)

EncodeTunnelTag encodes a 1-byte tag prefix for a tagged tunnel attribute per RFC 2868 §3.1. Tags 0x01..0x1F are valid; tag 0x00 means "no tag" and the returned ok=false signals the caller to omit the prefix.

func EncryptTunnelPassword

func EncryptTunnelPassword(password []byte, requestAuth [16]byte, secret []byte, tag byte, hasTag bool) ([]byte, error)

EncryptTunnelPassword encrypts a tunnel password per RFC 2868 §3.3. requestAuth is the 16-byte Request Authenticator from the enclosing Access-Request packet. tag is the optional 1-byte tunnel tag; pass hasTag=false to omit it. When hasTag is true, tag MUST be in 0x01..0x1F.

Returns the Value field (Salt + encrypted password, with the tag flag baked into the Salt's high bit) ready to be placed in a Tunnel-Password attribute.

func EncryptUserPassword

func EncryptUserPassword(password []byte, requestAuth [16]byte, secret []byte) ([]byte, error)

EncryptUserPassword hides a cleartext password using the RFC 2865 §5.2 algorithm: the password is null-padded to a 16-byte boundary, then each 16-octet block is XORed with MD5(secret || previous_ciphertext_block), where the first block uses the Request Authenticator as the previous block.

The result length is a multiple of 16, between 16 and 128 octets inclusive. Returns ErrPasswordTooLong if len(password) > 128, and ErrSecretEmpty if the shared secret is empty.

func EqualConstantTime

func EqualConstantTime(a, b []byte) bool

EqualConstantTime reports whether a and b are byte-for-byte equal without leaking timing information about the position of the first difference. Returns false when lengths differ.

func VerifyMessageAuthenticator

func VerifyMessageAuthenticator(packetBytes []byte, received [16]byte, secret []byte) bool

VerifyMessageAuthenticator recomputes the HMAC-MD5 over packetBytes and compares it against received in constant time. As with ComputeMessageAuthenticator, the Value field of the Message-Authenticator attribute in packetBytes must be zeroed before calling.

Types

This section is empty.

Jump to

Keyboard shortcuts

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