message

package module
v0.0.0-...-745e037 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 14, 2024 License: MIT Imports: 11 Imported by: 1

README

Message

Package message implements Rails/ActiveSupport style signed messages support in Golang. It is heavily based on the Rails ActiveSupport version, and can read most Rails-generated signed messages.

Getting Started

To use the package, you need to first initialize a message.Message object by calling New, passing in a Hash algorithm's New function, an expiration date (which can be nil) and the message data. The data can be a primitive type (string, float, int) or a map[string]interface{}:

msg := message.New(sha1.New, time.Now().Add(5 * time.Minute), "message data")

To generate a signed message, call signed with a key of at least 128 bits (16 bytes):

signed, err := msg.Signed(secretKey)

Verifying messages is similar to the ActiveSupport implementation.

To decode a message, call message.Verified or message.VerifiedRails with the signed message and your key.

Notes

This will decode Rails messages that do not have embedded objects, as Go does not have a Ruby-compatible marshalling system.

It will also not work for some messages created by the globalid gem, as for some reason, for records with single digit IDs, the gem generates invalid Base64 data that causes Go's base64 library to paniic.

Example:

irb(main):023> ActiveStorage::Blob.find(2).attachable_sgid
  ActiveStorage::Blob Load (0.2ms)  SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
=> "eyJfcmFpbHMiOnsiZGF0YSI6ImdpZDovL3Rlc3Rlci9BY3RpdmVTdG9yYWdlOjpCbG9iLzI_ZXhwaXJlc19pbiIsInB1ciI6ImF0dGFjaGFibGUifX0=--7e516e0935f5b2adc8dd706f8c242b61f062cabb"

And the attempt to decode:

$ base64 -d
eyJfcmFpbHMiOnsiZGF0YSI6ImdpZDovL3Rlc3Rlci9BY3RpdmVTdG9yYWdlOjpCbG9iLzI_ZXhwaXJlc19pbiIsInB1ciI6ImF0dGFjaGFibGUifX0=
# "_rails":{"data":"gid://tester/ActiveStorage::Blob/2base64: invalid input

Every ID over 10 seems to be fine:

irb(main):024> ActiveStorage::Blob.find(10).attachable_sgid
  ActiveStorage::Blob Load (0.1ms)  SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = ? LIMIT ?  [["id", 10], ["LIMIT", 1]]
=> "eyJfcmFpbHMiOnsiZGF0YSI6ImdpZDovL3Rlc3Rlci9BY3RpdmVTdG9yYWdlOjpCbG9iLzEwP2V4cGlyZXNfaW4iLCJwdXIiOiJhdHRhY2hhYmxlIn19--924f42105c004454609e5783233df8c470e5ce67"

And the decode:

$ base64 -d
eyJfcmFpbHMiOnsiZGF0YSI6ImdpZDovL3Rlc3Rlci9BY3RpdmVTdG9yYWdlOjpCbG9iLzEwP2V4cGlyZXNfaW4iLCJwdXIiOiJhdHRhY2hhYmxlIn19
# {"_rails":{"data":"gid://tester/ActiveStorage::Blob/10?expires_in","pur":"attachable"}}

Maybe it was a fluke on my end, maybe something to do with my setup, but the incomplete messages will not decode, and I do not have time to investigate.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidKey         = errors.New("invalid key")
	ErrMalformedMessage   = errors.New("malformed message")
	ErrInvalidSignature   = errors.New("message has an invalid signature")
	ErrMalformedSignature = errors.New("message has a nalformed signature")
	ErrMissingSignature   = errors.New("message is missing signature segment")
	ErrMessageExpired     = errors.New("message is expired")
)

Functions

This section is empty.

Types

type Message

type Message struct {
	Data      interface{}      `json:"data"`
	ExpiresAt string           `json:"exp,omitempty"`
	Hasher    func() hash.Hash `json:"-"`
	Purpose   string           `json:"pur"`
	// contains filtered or unexported fields
}

func New

func New(expiresAt *time.Time, data interface{}) *Message

func Verified

func Verified(signedMessage string, key []byte) (*Message, error)

func (*Message) DataMap

func (m *Message) DataMap() map[string]interface{}

func (*Message) DataString

func (m *Message) DataString() string

func (*Message) Signed

func (m *Message) Signed(key []byte) (string, error)

func (*Message) ToRails

func (m *Message) ToRails() *RailsMessage

type RailsMessage

type RailsMessage struct {
	Message *Message `json:"_rails"`
}

func VerifiedRails

func VerifiedRails(signedMessage string, key []byte) (*RailsMessage, error)

func (*RailsMessage) Signed

func (m *RailsMessage) Signed(key []byte) (string, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL