aliases: sign and verify
This commit is contained in:
parent
c9eb1aef9d
commit
04104c0f9e
|
@ -0,0 +1,66 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Package aliases implements the validation and signing features of https://ssb-ngi-pointer.github.io/rooms2/#alias
|
||||
package aliases
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
|
||||
refs "go.mindeco.de/ssb-refs"
|
||||
)
|
||||
|
||||
// Registration ties an alias to the ID of the user and the RoomID it should be registerd on
|
||||
type Registration struct {
|
||||
Alias string
|
||||
UserID refs.FeedRef
|
||||
RoomID refs.FeedRef
|
||||
}
|
||||
|
||||
// Sign takes the public key (belonging to UserID) and returns the signed confirmation
|
||||
func (r Registration) Sign(privKey ed25519.PrivateKey) Confirmation {
|
||||
var conf Confirmation
|
||||
conf.Registration = r
|
||||
msg := r.createRegistrationMessage()
|
||||
conf.Signature = ed25519.Sign(privKey, msg)
|
||||
return conf
|
||||
}
|
||||
|
||||
// createRegistrationMessage returns the string of bytes that should be signed
|
||||
func (r Registration) createRegistrationMessage() []byte {
|
||||
var message bytes.Buffer
|
||||
message.WriteString("=room-alias-registration:")
|
||||
message.WriteString(r.RoomID.Ref())
|
||||
message.WriteString(":")
|
||||
message.WriteString(r.UserID.Ref())
|
||||
message.WriteString(":")
|
||||
message.WriteString(r.Alias)
|
||||
return message.Bytes()
|
||||
}
|
||||
|
||||
// Confirmation combines a registration with the corresponding signature
|
||||
type Confirmation struct {
|
||||
Registration
|
||||
|
||||
Signature []byte
|
||||
}
|
||||
|
||||
// Verify checks that the confirmation is for the expected room and from the expected feed
|
||||
func (c Confirmation) Verify(room, feed refs.FeedRef) bool {
|
||||
// not for that room
|
||||
if !c.RoomID.Equal(&room) {
|
||||
return false
|
||||
}
|
||||
|
||||
// not for that feed
|
||||
if !c.UserID.Equal(&feed) {
|
||||
return false
|
||||
}
|
||||
|
||||
// re-construct the registration
|
||||
message := c.createRegistrationMessage()
|
||||
|
||||
// check the signature matches
|
||||
return ed25519.Verify(c.UserID.PubKey(), message, c.Signature)
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package aliases
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/ssb-ngi-pointer/go-ssb-room/internal/maybemod/keys"
|
||||
"github.com/stretchr/testify/require"
|
||||
refs "go.mindeco.de/ssb-refs"
|
||||
)
|
||||
|
||||
func TestConfirmation(t *testing.T) {
|
||||
r := require.New(t)
|
||||
|
||||
// this is our room, it's not a valid feed but thats fine for this test
|
||||
roomID := refs.FeedRef{
|
||||
ID: bytes.Repeat([]byte("test"), 8),
|
||||
Algo: "test",
|
||||
}
|
||||
|
||||
// to make the test deterministic, decided by fair dice roll.
|
||||
seed := bytes.Repeat([]byte("yeah"), 8)
|
||||
// our user, who will sign the registration
|
||||
userKeyPair, err := keys.NewKeyPair(bytes.NewReader(seed))
|
||||
r.NoError(err)
|
||||
|
||||
// create and fill out the registration for an alias (in this case the name of the test)
|
||||
var valid Registration
|
||||
valid.RoomID = roomID
|
||||
valid.UserID = userKeyPair.Feed
|
||||
valid.Alias = t.Name()
|
||||
|
||||
// internal function to create the registration string
|
||||
msg := valid.createRegistrationMessage()
|
||||
want := "=room-alias-registration:@dGVzdHRlc3R0ZXN0dGVzdHRlc3R0ZXN0dGVzdHRlc3Q=.test:@Rt2aJrtOqWXhBZ5/vlfzeWQ9Bj/z6iT8CMhlr2WWlG4=.ed25519:TestConfirmation"
|
||||
r.Equal(want, string(msg))
|
||||
|
||||
// create the signed confirmation
|
||||
confirmation := valid.Sign(userKeyPair.Pair.Secret)
|
||||
|
||||
yes := confirmation.Verify(roomID, userKeyPair.Feed)
|
||||
r.True(yes, "should be valid for this room and feed")
|
||||
|
||||
// make up another id for the invalid test(s)
|
||||
otherID := refs.FeedRef{
|
||||
ID: bytes.Repeat([]byte("nope"), 8),
|
||||
Algo: "test",
|
||||
}
|
||||
|
||||
yes = confirmation.Verify(otherID, userKeyPair.Feed)
|
||||
r.False(yes, "should not be valid for another room")
|
||||
|
||||
yes = confirmation.Verify(roomID, otherID)
|
||||
r.False(yes, "should not be valid for this room but another feed")
|
||||
|
||||
// puncture the signature to emulate an invalid one
|
||||
confirmation.Signature[0] = confirmation.Signature[0] ^ 1
|
||||
|
||||
yes = confirmation.Verify(roomID, userKeyPair.Feed)
|
||||
r.False(yes, "should not be valid anymore")
|
||||
|
||||
}
|
Loading…
Reference in New Issue