aboutsummaryrefslogtreecommitdiff
path: root/objects/id.go
diff options
context:
space:
mode:
Diffstat (limited to 'objects/id.go')
-rw-r--r--objects/id.go111
1 files changed, 111 insertions, 0 deletions
diff --git a/objects/id.go b/objects/id.go
new file mode 100644
index 0000000..22eeaa2
--- /dev/null
+++ b/objects/id.go
@@ -0,0 +1,111 @@
+package objects
+
+import (
+ "bytes"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "golang.org/x/crypto/sha3"
+ "hash"
+ "io"
+ "strings"
+)
+
+type ObjectIdAlgo string
+
+const (
+ OIdAlgoSHA3_256 ObjectIdAlgo = "sha3-256"
+ OIdAlgoDefault = OIdAlgoSHA3_256
+)
+
+var allowedAlgos = map[ObjectIdAlgo]struct{}{OIdAlgoSHA3_256: {}}
+
+func (algo ObjectIdAlgo) checkAlgo() bool {
+ _, ok := allowedAlgos[algo]
+ return ok
+}
+
+func (algo ObjectIdAlgo) sumLength() int {
+ if algo != OIdAlgoSHA3_256 {
+ panic("Only sha3-256 is implemented!")
+ }
+
+ return 32
+}
+
+// ObjectId identifies an object using a cryptogrpahic hash
+type ObjectId struct {
+ Algo ObjectIdAlgo
+ Sum []byte
+}
+
+func (oid ObjectId) wellformed() bool {
+ return oid.Algo.checkAlgo() && len(oid.Sum) == oid.Algo.sumLength()
+}
+
+func (oid ObjectId) String() string {
+ return fmt.Sprintf("%s:%s", oid.Algo, hex.EncodeToString(oid.Sum))
+}
+
+func ParseObjectId(s string) (oid ObjectId, err error) {
+ parts := strings.SplitN(s, ":", 2)
+ if len(parts) != 2 {
+ err = errors.New("Invalid ObjectId format")
+ return
+ }
+
+ oid.Algo = ObjectIdAlgo(parts[0])
+
+ oid.Sum, err = hex.DecodeString(parts[1])
+ if err != nil {
+ return
+ }
+
+ if !oid.wellformed() {
+ err = errors.New("Object ID is malformed")
+ }
+
+ return
+}
+
+func (a ObjectId) Equals(b ObjectId) bool {
+ return a.Algo == b.Algo && bytes.Equal(a.Sum, b.Sum)
+}
+
+// ObjectIdGenerator generates an ObjectId from the binary representation of an object
+type ObjectIdGenerator interface {
+ io.Writer // Must not fail
+ GetId() ObjectId
+}
+
+func (algo ObjectIdAlgo) Generator() ObjectIdGenerator {
+ if algo != OIdAlgoSHA3_256 {
+ panic("Only sha3-256 is implemented!")
+ }
+
+ return hashObjectIdGenerator{
+ algo: algo,
+ Hash: sha3.New256(),
+ }
+}
+
+type hashObjectIdGenerator struct {
+ algo ObjectIdAlgo
+ hash.Hash
+}
+
+func (h hashObjectIdGenerator) GetId() ObjectId {
+ return ObjectId{
+ Algo: h.algo,
+ Sum: h.Sum([]byte{}),
+ }
+}
+
+func (oid ObjectId) VerifyObject(o Object) bool {
+ gen := oid.Algo.Generator()
+ if err := o.Serialize(gen); err != nil {
+ panic(err)
+ }
+
+ return gen.GetId().Equals(oid)
+}