Documentation
¶
Overview ¶
Package iron provides functions for encrypting and signing Iron tokens using
- PBKDF2 with HMAC-SHA256 for key derivation,
- AES-256-CBC for data encryption,
- and HMAC-SHA256 for integrity checks.
Token Format ¶
Iron tokens are strings in the following format (all parts are base64url encoded without padding):
Fe26.1*{PASSWORD_ID}*{SALT}*{IV}*{ENCRYPTED_DATA}*{EXPIRATION}*{MAC_SALT}*{MAC}
where:
- Fe26.1 is a literal prefix indicating the token version (1),
- {PASSWORD_ID} is the unique ID of the password used to derive the encryption and HMAC keys,
- {SALT} is the salt used for the encryption key,
- {IV} is the initialization vector used for AES encryption,
- {ENCRYPTED_DATA} is the encrypted data itself,
- {EXPIRATION} is the expiration time of the token in milliseconds since the Unix epoch (January 1, 1970),
- {MAC_SALT} is the salt used for the HMAC key,
- {MAC} is the HMAC of the token data (everything before MAC_SALT).
Password Management ¶
iron allows for password rotation. Passwords are identified by a unique ID. Each token is associated with a password that is used to derive the encryption and HMAC keys and has an expiration time that is less than the password's expiration time. New passwords can be added at any time, and the last password (sorted lexicographically by ID) is used for token generation. Old passwords that have expired can be removed because all the tokens they were used to generate must also be expired.
Simple applications that don't require password rotation can use NewIronWithPassword to create an Iron instance with a single password and no expiration.
Example ¶
package main import ( "fmt" "time" "github.com/calico32/iron" ) type MyData struct { UserId int `json:"user_id"` Permissions []string `json:"permissions"` } func main() { i := iron.NewIronWithPassword("secretpasswordatleast32byteslong") data := MyData{ UserId: 12345, Permissions: []string{"read", "write", "delete"}, } token := i.Seal(data, time.Now().Add(time.Second)) var decrypted MyData _, err := i.Unseal(token, &decrypted) if err != nil { fmt.Println("Error unsealing token:", err) return } fmt.Printf("User ID: %d\n", decrypted.UserId) fmt.Printf("Permissions: %v\n", decrypted.Permissions) }
Output: User ID: 12345 Permissions: [read write delete]
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrBadPassword = fmt.Errorf("password must be at least %d bytes long", minPasswordLength) ErrNoValidPasswords = fmt.Errorf("iron: no valid passwords available") ErrInvalidToken = fmt.Errorf("iron: invalid token format or data") ErrInvalidSignature = fmt.Errorf("iron: invalid token signature") ErrExpiredToken = fmt.Errorf("iron: token has expired") ErrPasswordExpired = fmt.Errorf("iron: password has expired") )
Functions ¶
This section is empty.
Types ¶
type Iron ¶
type Iron struct {
// contains filtered or unexported fields
}
An Iron holds the passwords for token generation.
func NewIron ¶
func NewIron() Iron
NewIron returns a new empty Iron instance. Passwords must be added before the instance can be used to generate tokens.
func NewIronWithPassword ¶
NewIronWithPassword returns a new Iron instance with the provided password and no expiration. The password must be at least 32 bytes long.
func (*Iron) AddPassword ¶
AddPassword adds a password to the Iron instance. The password must be at least 32 bytes long, and the ID must be unique. It panics if these requirements are not met.
If the password's expiration time is in the past, it will not be added.
func (Iron) Seal ¶
Seal encrypts the provided data and returns a token that contains the encrypted data and the cryptographic information needed to verify its integrity and decrypt it later.
The provided expiration time will be capped to the expiration time of the currently active password, if it is later than that.
It panics v is not JSON-marshalable, no passwords are available and non-expired, or the expiration time is in the past.
func (Iron) Unseal ¶
Unseal decrypts the provided token and unmarshals the data into v. v must be a pointer to a type that can be unmarshaled from JSON; otherwise, Unseal panics. It returns the expiration time of the token, ErrInvalidToken if the token is invalid, ErrExpiredToken if the token has expired, or another error if the token cannot be decrypted or unmarshaled.