Merge branch '18870-installer' refs #18870
[arvados.git] / sdk / go / arvados / blob_signature.go
index 2202016bcc6b8a607c7f7d8241c80166247b87b4..9a031face2e957d91eed93982817fa8e1dc67d7f 100644 (file)
@@ -9,6 +9,7 @@
 package arvados
 
 import (
+       "bytes"
        "crypto/hmac"
        "crypto/sha1"
        "errors"
@@ -33,9 +34,9 @@ var (
 
 // makePermSignature generates a SHA-1 HMAC digest for the given blob,
 // token, expiry, and site secret.
-func makePermSignature(blobHash, apiToken, expiry, blobSignatureTTL string, permissionSecret []byte) string {
+func makePermSignature(blobHash []byte, apiToken, expiry, blobSignatureTTL string, permissionSecret []byte) string {
        hmac := hmac.New(sha1.New, permissionSecret)
-       hmac.Write([]byte(blobHash))
+       hmac.Write(blobHash)
        hmac.Write([]byte("@"))
        hmac.Write([]byte(apiToken))
        hmac.Write([]byte("@"))
@@ -73,7 +74,10 @@ func SignLocator(blobLocator, apiToken string, expiry time.Time, blobSignatureTT
                return blobLocator
        }
        // Strip off all hints: only the hash is used to sign.
-       blobHash := strings.Split(blobLocator, "+")[0]
+       blobHash := []byte(blobLocator)
+       if hints := bytes.IndexRune(blobHash, '+'); hints > 0 {
+               blobHash = blobHash[:hints]
+       }
        timestampHex := fmt.Sprintf("%08x", expiry.Unix())
        blobSignatureTTLHex := strconv.FormatInt(int64(blobSignatureTTL.Seconds()), 16)
        return blobLocator +
@@ -100,7 +104,7 @@ func VerifySignature(signedLocator, apiToken string, blobSignatureTTL time.Durat
        if matches == nil {
                return ErrSignatureMissing
        }
-       blobHash := matches[1]
+       blobHash := []byte(matches[1])
        signatureHex := matches[6]
        expiryHex := matches[7]
        if expiryTime, err := parseHexTimestamp(expiryHex); err != nil {
@@ -123,3 +127,21 @@ func parseHexTimestamp(timestampHex string) (ts time.Time, err error) {
        }
        return ts, err
 }
+
+var errNoSignature = errors.New("locator has no signature")
+
+func signatureExpiryTime(signedLocator string) (time.Time, error) {
+       matches := SignedLocatorRe.FindStringSubmatch(signedLocator)
+       if matches == nil {
+               return time.Time{}, errNoSignature
+       }
+       expiryHex := matches[7]
+       return parseHexTimestamp(expiryHex)
+}
+
+func stripAllHints(locator string) string {
+       if i := strings.IndexRune(locator, '+'); i > 0 {
+               return locator[:i]
+       }
+       return locator
+}