Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions activation/certifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,15 +306,15 @@ func (c *CertifierClient) Certify(
Signature: certResponse.Signature,
}

cert, err := shared.VerifyCertificate(opaqueCert, pubkey, id.Bytes())
cert, err := shared.VerifyCertificate(opaqueCert, [][]byte{pubkey}, id.Bytes())
if err != nil {
return nil, fmt.Errorf("verifying certificate: %w", err)
}

if cert.Expiration != nil {
c.logger.Info("certificate has expiration date", zap.Time("expiration", *cert.Expiration))
if time.Until(*cert.Expiration) < 0 {
return nil, errors.New("certificate is expired")
return nil, shared.ErrCertExpired
}
}

Expand Down
15 changes: 14 additions & 1 deletion activation/poet.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ type PoetPoW struct {
type PoetAuth struct {
*PoetPoW
*certifier.PoetCert

CertPubKey []byte
}

type PoetClient interface {
Expand Down Expand Up @@ -234,6 +236,12 @@ func (c *HTTPPoetClient) Submit(
Data: auth.PoetCert.Data,
Signature: auth.PoetCert.Signature,
}

if len(auth.CertPubKey) > shared.CertPubkeyHintSize {
request.CertificatePubkeyHint = auth.CertPubKey[:shared.CertPubkeyHintSize]
} else {
request.CertificatePubkeyHint = auth.CertPubKey
}
}

resBody := rpcapi.SubmitResponse{}
Expand Down Expand Up @@ -492,7 +500,12 @@ func (c *poetService) authorize(
cert, err := c.Certify(ctx, nodeID)
switch {
case err == nil:
return &PoetAuth{PoetCert: cert}, nil
info, err := c.getInfo(ctx)
if err != nil {
return nil, err
}

return &PoetAuth{PoetCert: cert, CertPubKey: info.ServicePubkey}, nil
case errors.Is(err, ErrCertificatesNotSupported):
logger.Debug("poet doesn't support certificates")
default:
Expand Down
83 changes: 83 additions & 0 deletions activation/poet_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

rpcapi "github.com/spacemeshos/poet/release/proto/go/rpc/api/v1"
"github.com/spacemeshos/poet/server"
"github.com/spacemeshos/poet/shared"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"go.uber.org/zap"
Expand Down Expand Up @@ -377,6 +378,88 @@ func TestPoetClient_ObtainsCertOnSubmit(t *testing.T) {
require.NoError(t, err)
}

func TestCheckCertifierPublickeyHint(t *testing.T) {
sig, err := signing.NewEdSigner()
require.NoError(t, err)

certifierAddress := &url.URL{Scheme: "http", Host: "certifier"}
certifierPubKey := []byte("certifier-pubkey")
infoResp, err := protojson.Marshal(&rpcapi.InfoResponse{
ServicePubkey: []byte("pubkey"),
Certifier: &rpcapi.InfoResponse_Cerifier{
Url: certifierAddress.String(),
Pubkey: certifierPubKey,
},
})
require.NoError(t, err)

submitResp, err := protojson.Marshal(&rpcapi.SubmitResponse{})
require.NoError(t, err)

mux := http.NewServeMux()
mux.HandleFunc("GET /v1/info", func(w http.ResponseWriter, r *http.Request) { w.Write(infoResp) })

publicKeyHint := certifierPubKey[:shared.CertPubkeyHintSize]
mux.HandleFunc("POST /v1/submit", func(w http.ResponseWriter, r *http.Request) {
rawReq, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Failed to read request body", http.StatusInternalServerError)
return
}

req := &rpcapi.SubmitRequest{}
if err := protojson.Unmarshal(rawReq, req); err != nil {
http.Error(w, "Invalid request body", http.StatusBadRequest)
return
}

if !bytes.Equal(publicKeyHint, req.CertificatePubkeyHint) {
http.Error(w, shared.ErrCertExpired.Error(), http.StatusUnauthorized)
return
}

w.Write(submitResp)
})

ts := httptest.NewServer(mux)
defer ts.Close()

server := types.PoetServer{
Address: ts.URL,
Pubkey: types.NewBase64Enc([]byte("pubkey")),
}
cfg := PoetConfig{RequestTimeout: time.Millisecond * 100}
client, err := NewHTTPPoetClient(server, cfg, withCustomHttpClient(ts.Client()))
require.NoError(t, err)

cert := certifier.PoetCert{Data: []byte("abc")}
t.Run("public key hint is valid", func(t *testing.T) {
_, err = client.Submit(context.Background(), time.Time{}, nil, nil, types.RandomEdSignature(), sig.NodeID(),
PoetAuth{
PoetCert: &cert,
CertPubKey: publicKeyHint,
})
require.NoError(t, err)
})

t.Run("no public key hint", func(t *testing.T) {
_, err = client.Submit(context.Background(), time.Time{}, nil, nil, types.RandomEdSignature(), sig.NodeID(),
PoetAuth{
PoetCert: &cert,
})
require.NoError(t, err)
})

t.Run("public key hint is invalid", func(t *testing.T) {
_, err = client.Submit(context.Background(), time.Time{}, nil, nil, types.RandomEdSignature(), sig.NodeID(),
PoetAuth{
PoetCert: &cert,
CertPubKey: []byte{1, 2, 3, 4, 5},
})
require.ErrorContains(t, err, shared.ErrCertExpired.Error())
})
}

func TestPoetClient_RecertifiesOnAuthFailure(t *testing.T) {
sig, err := signing.NewEdSigner()
require.NoError(t, err)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ require (
github.com/spacemeshos/fixed v0.1.1
github.com/spacemeshos/go-scale v1.2.0
github.com/spacemeshos/merkle-tree v0.2.3
github.com/spacemeshos/poet v0.10.4
github.com/spacemeshos/poet v0.10.6-0.20240902015624-1655db74a0f2
github.com/spacemeshos/post v0.12.8
github.com/spf13/afero v1.11.0
github.com/spf13/cobra v1.8.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -613,8 +613,8 @@ github.com/spacemeshos/go-scale v1.2.0 h1:ZlA2L1ILym2gmyJUwUdLTiyP1ZIG0U4xE9nFVF
github.com/spacemeshos/go-scale v1.2.0/go.mod h1:HV6e3/X5h9u2aFpYKJxt7PY/fBuLBegEKWgeZJ+/5jE=
github.com/spacemeshos/merkle-tree v0.2.3 h1:zGEgOR9nxAzJr0EWjD39QFngwFEOxfxMloEJZtAysas=
github.com/spacemeshos/merkle-tree v0.2.3/go.mod h1:VomOcQ5pCBXz7goiWMP5hReyqOfDXGSKbrH2GB9Htww=
github.com/spacemeshos/poet v0.10.4 h1:MHGG1dhMVwy5DdlsmwdRLDQTTqlPA21lSQB2PVd8MSk=
github.com/spacemeshos/poet v0.10.4/go.mod h1:hz21GMyHb9h29CqNhVeKxCD5dxZdQK27nAqLpT46gjE=
github.com/spacemeshos/poet v0.10.6-0.20240902015624-1655db74a0f2 h1:fCBMHIl+1HF6nvq5mkOnC18o0PpZkDN5yjhVNW1uDs4=
github.com/spacemeshos/poet v0.10.6-0.20240902015624-1655db74a0f2/go.mod h1:6GuMTg0aMZ0hwlFCfs5NkRi0ACIq3BkRwV8jjkVmH9A=
github.com/spacemeshos/post v0.12.8 h1:xcxVPWTvt2zJYJUvdpmX7CwR1CQnMnmd4VndThGbSdY=
github.com/spacemeshos/post v0.12.8/go.mod h1:WzfVgaa1wxgrsytC4EVKkG8rwoUxjyoyQL0ZSxs56Y0=
github.com/spacemeshos/sha256-simd v0.1.0 h1:G7Mfu5RYdQiuE+wu4ZyJ7I0TI74uqLhFnKblEnSpjYI=
Expand Down
1 change: 1 addition & 0 deletions systest/tests/poets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ func TestRegisteringInPoetWithPowAndCert(t *testing.T) {
powRegs, err := fetchCounterMetric(tctx, metricsEndpoint, "poet_registration_with_pow_total", valid)
require.NoError(t, err)
require.GreaterOrEqual(t, powRegs, float64(cl.Smeshers()*epoch))

powRegsInvalid, err := fetchCounterMetric(tctx, metricsEndpoint, "poet_registration_with_pow_total", invalid)
require.ErrorIs(t, err, errMetricNotFound, "metric for invalid PoW registrations value: %v", powRegsInvalid)

Expand Down