package arvados
import (
+ "bytes"
"crypto/hmac"
"crypto/sha1"
"errors"
// 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("@"))
// SignManifest signs all locators in the given manifest, discarding
// any existing signatures.
-func SignManifest(manifest string, apiToken string, ttl time.Duration, permissionSecret []byte) string {
- expiry := time.Now().Add(ttl)
+func SignManifest(manifest string, apiToken string, expiry time.Time, ttl time.Duration, permissionSecret []byte) string {
return regexp.MustCompile(`\S+`).ReplaceAllStringFunc(manifest, func(tok string) string {
if mBlkRe.MatchString(tok) {
return SignLocator(mPermHintRe.ReplaceAllString(tok, ""), apiToken, expiry, ttl, permissionSecret)
- } else {
- return tok
}
+ return tok
})
}
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 +
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 {
}
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
+}