Documentation
¶
Overview ¶
Package headless provides ECDH-based encryption utilities for the Chainguard headless login flow, enabling secure delivery of OIDC identity tokens to CLI clients without a browser redirect.
Index ¶
Examples ¶
Constants ¶
const (
// X25519 keys are 32 bytes long
ECDHKeyLength = 32
)
Variables ¶
var URLSafeEncoding = base64.RawURLEncoding // Headless codes must be URL-safe
Functions ¶
func DecryptIDToken ¶
func DecryptIDToken(sess *auth.HeadlessSession, pk *ecdh.PrivateKey) ([]byte, error)
DecryptIDToken decrypts the ID token using the private key.
func GenerateKeyPair ¶
func GenerateKeyPair() (*ecdh.PrivateKey, error)
GenerateKeyPair generates a new ECDSA key pair.
Example ¶
ExampleGenerateKeyPair demonstrates generating an ECDH key pair.
package main
import (
"fmt"
"chainguard.dev/sdk/auth/headless"
)
func main() {
pk, err := headless.GenerateKeyPair()
fmt.Println(err)
fmt.Println(pk != nil)
}
Output: <nil> true
func VerifyCode ¶
VerifyCode checks if the code is a valid public key.
Example ¶
ExampleVerifyCode demonstrates that a valid code passes verification.
package main
import (
"fmt"
"chainguard.dev/sdk/auth/headless"
)
func main() {
pk, _ := headless.GenerateKeyPair()
code := headless.NewCode(pk.PublicKey())
err := headless.VerifyCode(string(code))
fmt.Println(err)
}
Output: <nil>
Types ¶
type Code ¶
type Code string
headless.Code is a serialized public key that we use to exchange a shared symmetric key. This shared symmetric key is used to encrypt the ID token (see Code#NewSession).
After obtaining the shared symmetric key, we throw away our own private key to guarantee that the content of the ID token can only be decrypted by the holder of this code's private key.
func NewCode ¶
NewCode creates a code by serializing the public key in an url-safe format.
Example ¶
ExampleNewCode demonstrates creating a headless code from a public key.
package main
import (
"fmt"
"chainguard.dev/sdk/auth/headless"
)
func main() {
pk, _ := headless.GenerateKeyPair()
code := headless.NewCode(pk.PublicKey())
fmt.Println(len(code) > 0)
}
Output: true
func (*Code) NewSession ¶
func (h *Code) NewSession(idtoken []byte) (*auth.HeadlessSession, error)
NewSession encrypts the idtoken using a shared symmetric key that is only available to us and the holder of the private key corresponding to this headless Code.
It is important to recall how ECDH works:
- First, the user generates an EC keypair, and send us their public key as the form of a headless login code.
- We generate a new ephemeral EC keypair for this session.
- With our private key and their public key, a shared symmetric key is obtained by calling ourPriv.ECDH(theirPub).
- When we send our public key to the user, they can generate the same shared symmetric key by calling theirPriv.ECDH(ourPub).
The shared symmetric key obtained by ECDH in this function is used to encrypt the idtoken. After the idtoken is encrypted, we throw away our private key and the shared symmetric key, so that we ourselves cannot decrypt the idtoken ourselves.
We then send the user our public key and the encrypted idtoken. As noted before, ECDH allows the user to generate the same shared symmetric key, which can be used to decrypt the idtoken.