fleet/third_party/httpsig-go/examples_test.go
Victor Lyuboslavsky c25fed2492
Added a vendored version of httpsig-go. (#30820)
For #30473

This change adds a vendored `httpsig-go` library to our repo. We cannot
use the upstream library because it has not merged the change we need:
https://github.com/remitly-oss/httpsig-go/pull/25

Thus, we need our own copy at this point.

The instructions for keeping this library up to date (if needed) are in
`UPDATE_INSTRUCTIONS`.

None of the coderabbitai review comments are relevant to the
code/features we are going to use for HTTP message signatures.

We will use this library in subsequent PRs for the TPM-backed HTTP
message signature feature.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Introduced a Go library for HTTP message signing and verification,
supporting multiple cryptographic algorithms (RSA, ECDSA, Ed25519,
HMAC).
* Added utilities for key management, including JWK and PEM key
handling.
* Provided HTTP client and server helpers for automatic request signing
and signature verification.
* Implemented structured error handling and metadata extraction for
signatures.

* **Documentation**
  * Added comprehensive README, usage examples, and update instructions.
* Included license and configuration files for third-party and testing
tools.

* **Tests**
* Added extensive unit, integration, and fuzz tests covering signing,
verification, and key handling.
* Included official RFC test vectors and various test data files for
robust validation.

* **Chores**
* Integrated continuous integration workflows and ignore files for code
quality and security analysis.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-07-14 20:26:50 +02:00

104 lines
2.9 KiB
Go

package httpsig_test
import (
"crypto"
"fmt"
"html"
"net/http"
"net/http/httptest"
"github.com/remitly-oss/httpsig-go"
"github.com/remitly-oss/httpsig-go/keyman"
"github.com/remitly-oss/httpsig-go/keyutil"
)
func ExampleSign() {
pkeyEncoded := `-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgNTK6255ubaaj1i/c
ppuLouTgjAVyHGSxI0pYX8z1e2GhRANCAASkbVuWv1KXXs2H8b0ruFLyv2lKJWtT
BznPJ5sSI1Jn+srosJB/GbEZ3Kg6PcEi+jODF9fdpNEaHGbbGdaVhJi1
-----END PRIVATE KEY-----`
pkey, _ := keyutil.ReadPrivateKey([]byte(pkeyEncoded))
req := httptest.NewRequest("GET", "https://example.com/data", nil)
profile := httpsig.SigningProfile{
Algorithm: httpsig.Algo_ECDSA_P256_SHA256,
Fields: httpsig.DefaultRequiredFields,
Metadata: []httpsig.Metadata{httpsig.MetaKeyID},
}
skey := httpsig.SigningKey{
Key: pkey,
MetaKeyID: "key123",
}
signer, _ := httpsig.NewSigner(profile, skey)
signer.Sign(req)
}
func ExampleVerify() {
pubkeyEncoded := `-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIUctKvU5L/eEYxua5Zlz0HIQJRQq
MTQ7eYQXwqpTvTJkuTffGXKLilT75wY2YZWfybv9flu5d6bCfw+4UB9+cg==
-----END PUBLIC KEY-----`
pubkey, _ := keyutil.ReadPublicKey([]byte(pubkeyEncoded))
req := httptest.NewRequest("GET", "https://example.com/data", nil)
kf := keyman.NewKeyFetchInMemory(map[string]httpsig.KeySpec{
"key123": {
KeyID: "key123",
Algo: httpsig.Algo_ECDSA_P256_SHA256,
PubKey: pubkey,
},
})
httpsig.Verify(req, kf, httpsig.DefaultVerifyProfile)
}
func ExampleNewHandler() {
myhandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Lookup the results of verification
if veriftyResult, ok := httpsig.GetVerifyResult(r.Context()); ok {
keyid, _ := veriftyResult.KeyID()
fmt.Fprintf(w, "Hello, %s", html.EscapeString(keyid))
} else {
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
}
})
// Create a verifier
verifier, _ := httpsig.NewVerifier(nil, httpsig.DefaultVerifyProfile)
mux := http.NewServeMux()
// Wrap the handler with the a signature verification handler.
mux.Handle("/", httpsig.NewHandler(myhandler, verifier))
}
func ExampleClient() {
profile := httpsig.SigningProfile{
Algorithm: httpsig.Algo_ECDSA_P256_SHA256,
Fields: httpsig.DefaultRequiredFields,
Metadata: []httpsig.Metadata{httpsig.MetaKeyID},
}
var privateKey crypto.PrivateKey // Get your private key
sk := httpsig.SigningKey{
Key: privateKey,
MetaKeyID: "key123",
}
// Create the signature signer
signer, _ := httpsig.NewSigner(profile, sk)
// Create a net/http Client that signs all requests
signingClient := httpsig.NewHTTPClient(nil, signer, nil)
// This call will be signed.
signingClient.Get("https://example.com")
verifier, _ := httpsig.NewVerifier(nil, httpsig.DefaultVerifyProfile)
// Create a net/http Client that signs and verifies all requests
signVerifyClient := httpsig.NewHTTPClient(nil, signer, verifier)
signVerifyClient.Get("https://example.com")
}