marshaller

package module
v0.0.0-...-ee4e849 Latest Latest
Warning

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

Go to latest
Published: May 1, 2026 License: MIT Imports: 6 Imported by: 0

README

marshaller

GoDoc

Serializes go-passwd/hasher hashers to / from a single string in a Django-style format.

Installation

go get github.com/go-passwd/marshaller

Usage

import (
    "github.com/go-passwd/hasher"
    "github.com/go-passwd/marshaller"
)

h, _ := hasher.New(hasher.TypeSHA256)
h.SetPassword("secret")

s, _ := marshaller.DjangoMarshaller.Marshal(h)
// s == "sha256$2048$<salt>$<hex-digest>"

restored, _ := marshaller.DjangoMarshaller.Unmarshal(s)
restored.Check("secret") // true

Format

Output adapts to whether iter and salt carry information:

Iter Salt Format
> 1 non-empty code$iter$salt$digest
> 1 empty code$iter$digest
<= 1 non-empty code$salt$digest
<= 1 empty code$digest

The default separator is $. The default DjangoMarshaller encodes the digest as hex; Base64Marshaller encodes it as standard base64 (matching how Django's PBKDF2 stores hashes).

Predefined marshallers

  • DjangoMarshaller — HexMarshaller{Separator: "$"}
  • HexMarshaller{Separator: ":"} — same format with a different separator
  • Base64Marshaller{Separator: "$"} — base64 instead of hex

Caveats

  • The 3-segment form distinguishes iter from salt by trying to parse the middle segment as an integer. A purely numeric salt would be misread as iter. randomstring.Generate produces alphanumeric salts, so this only matters for hand-crafted salts.
  • The format is Django-style, not Django-compatible: real Django MD5PasswordHasher and SHA1PasswordHasher use a 3-field algo$salt$hex shape with a single un-iterated digest.

Implementing your own hasher

To make a custom hasher.Hasher marshallable, implement marshaller.Marshalable:

type Marshalable interface {
    Code() string
    HashIter() int
    HashSalt() string
    HashedPassword() []byte
}

All hashers in go-passwd/hasher already do this.

Documentation

Overview

Package marshaller serializes github.com/go-passwd/hasher hashers to and from a single string in a Django-style format.

The output adapts to whether the hasher carries iteration count and salt: the marshaller emits "code$iter$salt$digest" when both are set, and drops empty segments otherwise. Round-tripping a marshalled string through HexMarshaller.Unmarshal (or any other Marshaller implementation) reconstructs a hasher whose Check method recognises the original password.

DjangoMarshaller is the conventional default: hex digest, "$" separator. Base64Marshaller uses standard base64 instead, matching how Django stores PBKDF2 hashes.

Custom hashers participate by implementing Marshalable.

Index

Examples

Constants

This section is empty.

Variables

View Source
var DjangoMarshaller = HexMarshaller{Separator: "$"}

DjangoMarshaller stores passwords in Django-like format using "$" as the separator and hex-encoded hashes.

Functions

This section is empty.

Types

type Base64Marshaller

type Base64Marshaller struct {
	Separator string
}

Base64Marshaller stores password using standard base64 encoding (with "=" padding). Matches Django's PBKDF2 hash storage format.

func (*Base64Marshaller) Marshal

func (m *Base64Marshaller) Marshal(h hasher.Hasher) (string, error)

Marshal hasher.Hasher to string

func (*Base64Marshaller) Unmarshal

func (m *Base64Marshaller) Unmarshal(s string) (hasher.Hasher, error)

Unmarshal string to Hasher

type HexMarshaller

type HexMarshaller struct {
	Separator string
}

HexMarshaller stores password in HEX

func (*HexMarshaller) Marshal

func (m *HexMarshaller) Marshal(h hasher.Hasher) (string, error)

Marshal hasher.Hasher to string

Example
package main

import (
	"fmt"

	"github.com/go-passwd/hasher"
	"github.com/go-passwd/marshaller"
)

func main() {
	// Use a fixed salt + iter so the output is deterministic for the
	// example. SetPassword on a fresh hasher would otherwise generate
	// a random salt.
	iter := 10
	salt := "salt"
	h := hasher.MD5Hasher{Iter: &iter, Salt: &salt}
	h.SetPassword("password")

	s, err := marshaller.DjangoMarshaller.Marshal(&h)
	if err != nil {
		panic(err)
	}
	fmt.Println(s)
}
Output:
md5$10$salt$1446572e0a1e0d275b6d1ec51d61d5b1

func (*HexMarshaller) Unmarshal

func (m *HexMarshaller) Unmarshal(s string) (hasher.Hasher, error)

Unmarshal string to Hasher

Example
package main

import (
	"fmt"

	"github.com/go-passwd/marshaller"
)

func main() {
	encoded := "md5$10$salt$1446572e0a1e0d275b6d1ec51d61d5b1"

	h, err := marshaller.DjangoMarshaller.Unmarshal(encoded)
	if err != nil {
		panic(err)
	}
	fmt.Println(h.Check("password"))
	fmt.Println(h.Check("wrong"))
}
Output:
true
false

type Marshalable

type Marshalable interface {
	// Code returns the hasher's algorithm code (e.g. "sha256").
	Code() string
	// HashIter returns the iteration count used. 0 means "no
	// iteration count was set".
	HashIter() int
	// HashSalt returns the salt used. "" means "no salt was set".
	HashSalt() string
	// HashedPassword returns the stored digest, or nil when unset.
	HashedPassword() []byte
}

Marshalable defines interface for hasher who can be marshalable

type Marshaller

type Marshaller interface {
	Marshal(hshr hasher.Hasher) (string, error)

	Unmarshal(string) (hasher.Hasher, error)
}

Marshaller defines interface for marshal and unmarshal hasher

Jump to

Keyboard shortcuts

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