Index | Files | Directories

package gpgchallenge

import ""

Package gpgchallenge provides a Client and a Server so that a Client can prove ownership of an IP address by solving a GPG challenge sent by the Server at the claimed IP. The protocol is as follows:

- The Client GETs a random token from the server, at the /token endpoint, and signs that token with its GPG private key (armor detached signature).

- When it is ready[*], the client POSTs an application/x-www-form-urlencoded over HTTPS to the server, at the /claim endpoint. It sends the following URL-encoded values as the request body: its armor encoded public key as "pubkey", the IP address it's claiming as "challengeIP", the token it got from the server as "token", and the signature for the token as "signature".

- The Server receives the claim. It verifies that the token (nonce) is indeed one that it had generated. It parses the client's public key. It verifies with that public key that the sent signature matches the token. The serve ACKs to the client.

- The Server generates a random token, and POSTs it to the challenged IP (over HTTPS, with certificate verification disabled) at the /challenge endpoint.

- The Client receives the random token, signs it (armored detached signature), and sends the signature as a reply.

- The Server receives the signed token and verifies it with the Client's public key.

- At this point, the challenge is successful, so the Server performs the action registered through the OnSuccess function.

- The Server sends a last message to the Client at the /ack endpoint, depending on the result of the OnSuccess action. "ACK" if it was successful, the error message otherwise.

[*]As the Server connects to the Client to challenge it, the Client must obviously have a way, which does not need to be described by the protocol, to listen to and accept these connections.


Package Files



const SNISuffix = "-gpgchallenge"

SNISuffix is the Server Name Indication prefix used when dialing the client's handler. The SNI is challengeIP+SNISuffix.


var ClientChallengedPort = 443

ClientChallengedPort is the port that the client will be challenged on by the server.

type Client Uses

type Client struct {
    // contains filtered or unexported fields

Client is used to prove ownership of an IP address, by answering a GPG challenge that the server sends at the address. A client must first register its Handler with an HTTPS server, before it can perform the challenge.

func NewClient Uses

func NewClient(keyRing, keyId, challengeIP string) (*Client, error)

NewClient returns a Client. keyRing and keyId are the GPG key ring and key ID used to fulfill the challenge. challengeIP is the address that client proves that it owns, by answering the challenge the server sends at this address.

func (*Client) Challenge Uses

func (cl *Client) Challenge(serverAddr string) error

Challenge requests a challenge from the server running at serverAddr, which should be a host name or of the hostname:port form, and then fulfills that challenge.

func (*Client) Handler Uses

func (cl *Client) Handler() (prefix string, h http.Handler)

Handler returns the client's handler, that should be registered with an HTTPS server for the returned prefix, for the client to be able to receive the challenge.

type Server Uses

type Server struct {
    // OnSuccess is user-defined, and it is run by the server upon
    // successuful verification of the client's challenge. Identity is the
    // short form of the client's public key's fingerprint in capital hex.
    // Address is the IP address that the client was claiming.
    OnSuccess func(identity, address string) error

    IPSeenMu sync.Mutex
    IPSeen   map[string]time.Time // last time we saw a claimedIP, for rate-limiting purposes.
    // contains filtered or unexported fields

Server sends a challenge when a client that wants to claim ownership of an IP address requests so. Server runs OnSuccess when the challenge is successful.

func (*Server) ServeHTTP Uses

func (cs *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)


clientThe client command is an example client of the gpgchallenge package.
serverThe server command is an example server of the gpgchallenge package.

Package gpgchallenge imports 25 packages (graph) and is imported by 7 packages. Updated 2019-06-26. Refresh now. Tools for package owners.