Index: go/src/infra/tools/cipd/internal/checksum.go |
diff --git a/go/src/infra/tools/cipd/internal/checksum.go b/go/src/infra/tools/cipd/internal/checksum.go |
new file mode 100644 |
index 0000000000000000000000000000000000000000..1dc24a04ecd0b20f4e59f90ab986f497e37c6280 |
--- /dev/null |
+++ b/go/src/infra/tools/cipd/internal/checksum.go |
@@ -0,0 +1,42 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+package internal |
+ |
+import ( |
+ "bytes" |
+ "crypto/sha1" |
+ "errors" |
+ |
+ "github.com/golang/protobuf/proto" |
+ |
+ "infra/tools/cipd/internal/messages" |
+) |
+ |
+// MarshalWithSHA1 serializes proto message to bytes, calculates SHA1 checksum |
+// of it, and returns serialized envelope that contains both. UnmarshalWithSHA1 |
+// can then be used to verify SHA1 and deserialized the original object. |
+func MarshalWithSHA1(pm proto.Message) ([]byte, error) { |
+ blob, err := proto.Marshal(pm) |
+ if err != nil { |
+ return nil, err |
+ } |
+ sum := sha1.Sum(blob) |
+ envelope := messages.BlobWithSHA1{Blob: blob, Sha1: sum[:]} |
+ return proto.Marshal(&envelope) |
+} |
+ |
+// UnmarshalWithSHA1Check is reverse of MarshalWithSHA1. It checks SHA1 checksum |
+// and deserializes the object if it matches the blob. |
+func UnmarshalWithSHA1(buf []byte, pm proto.Message) error { |
+ envelope := messages.BlobWithSHA1{} |
+ if err := proto.Unmarshal(buf, &envelope); err != nil { |
+ return err |
+ } |
+ sum := sha1.Sum(envelope.GetBlob()) |
+ if !bytes.Equal(sum[:], envelope.GetSha1()) { |
+ return errors.New("check sum of tag cache file is invalid") |
+ } |
+ return proto.Unmarshal(envelope.GetBlob(), pm) |
+} |