1
0
Fork 0
mirror of https://github.com/anyproto/any-sync.git synced 2025-06-08 05:57:03 +09:00
any-sync/coordinator/coordinatorproto/receipt.go
2024-08-02 11:14:12 +02:00

104 lines
2.7 KiB
Go

package coordinatorproto
import (
"bytes"
"errors"
"github.com/anyproto/any-sync/util/crypto"
"github.com/anyproto/any-sync/util/strkey"
"github.com/anyproto/protobuf/proto"
"time"
)
var (
errSignatureIncorrect = errors.New("receipt signature is incorrect")
errNetworkIsIncorrect = errors.New("network is incorrect")
errSpaceIdIncorrect = errors.New("receipt space id is incorrect")
errPeerIdIncorrect = errors.New("receipt peer id is incorrect")
errAccountIncorrect = errors.New("receipt account is incorrect")
errReceiptExpired = errors.New("receipt is expired")
)
func PrepareSpaceReceipt(spaceId, peerId string, validPeriod time.Duration, accountPubKey crypto.PubKey, networkKey crypto.PrivKey) (signedReceipt *SpaceReceiptWithSignature, err error) {
marshalledAccount, err := accountPubKey.Marshall()
if err != nil {
return
}
receipt := &SpaceReceipt{
SpaceId: spaceId,
PeerId: peerId,
AccountIdentity: marshalledAccount,
NetworkId: networkKey.GetPublic().Network(),
ValidUntil: uint64(time.Now().Add(validPeriod).Unix()),
}
receiptData, err := receipt.Marshal()
if err != nil {
return
}
sign, err := networkKey.Sign(receiptData)
if err != nil {
return
}
return &SpaceReceiptWithSignature{
SpaceReceiptPayload: receiptData,
Signature: sign,
}, nil
}
func CheckReceipt(peerId, spaceId string, accountIdentity []byte, networkId string, receipt *SpaceReceiptWithSignature) (err error) {
payload := &SpaceReceipt{}
err = proto.Unmarshal(receipt.GetSpaceReceiptPayload(), payload)
if err != nil {
return
}
if payload.SpaceId != spaceId {
return errSpaceIdIncorrect
}
if payload.PeerId != peerId {
return errPeerIdIncorrect
}
protoRaw, err := crypto.UnmarshalEd25519PublicKeyProto(payload.AccountIdentity)
if err != nil {
return
}
accountRaw, err := crypto.UnmarshalEd25519PublicKeyProto(accountIdentity)
if err != nil {
return
}
if !bytes.Equal(protoRaw.Storage(), accountRaw.Storage()) {
return errAccountIncorrect
}
err = checkNetwork(
networkId,
payload.NetworkId,
receipt.GetSpaceReceiptPayload(),
receipt.GetSignature())
if err != nil {
return
}
if payload.GetValidUntil() <= uint64(time.Now().Unix()) {
return errReceiptExpired
}
return
}
func checkNetwork(networkId, payloadNetworkId string, payload, signature []byte) (err error) {
if networkId != payloadNetworkId {
return errNetworkIsIncorrect
}
networkIdentity, err := strkey.Decode(strkey.NetworkAddressVersionByte, networkId)
if err != nil {
return
}
networkKey, err := crypto.UnmarshalEd25519PublicKey(networkIdentity)
if err != nil {
return
}
res, err := networkKey.Verify(payload, signature)
if err != nil {
return
}
if !res {
return errSignatureIncorrect
}
return
}