shithub: hugo

Download patch

ref: d1553b4b0f83e4a4305d2b4ab9ba6e305637f134
parent: 1d9dde82a0577d93eea8ed0a7ec0b4ae3068eb19
author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
date: Fri Apr 5 07:40:02 EDT 2019

integrity: Add support for sha384

Fixes #5815

--- a/docs/content/en/hugo-pipes/fingerprint.md
+++ b/docs/content/en/hugo-pipes/fingerprint.md
@@ -18,7 +18,7 @@
 
 Fingerprinting and [SRI](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) can be applied to any asset file using `resources.Fingerpint` which takes two arguments, the resource object and a [hash function](https://en.wikipedia.org/wiki/Cryptographic_hash_function). 
 
-The default hash function is `sha256`. Other available functions are `sha512` and `md5`.
+The default hash function is `sha256`. Other available functions are `sha384` (from Hugo `0.55`), `sha512` and `md5`.
 
 Any so processed asset will bear a `.Data.Integrity` property containing an integrity string, which is made up of the name of the hash function, one hyphen and the base64-encoded hash sum.
 
--- a/resources/resource_transformers/integrity/integrity.go
+++ b/resources/resource_transformers/integrity/integrity.go
@@ -19,11 +19,12 @@
 	"crypto/sha512"
 	"encoding/base64"
 	"encoding/hex"
-	"fmt"
 	"hash"
 	"html/template"
 	"io"
 
+	"github.com/pkg/errors"
+
 	"github.com/gohugoio/hugo/resources"
 	"github.com/gohugoio/hugo/resources/resource"
 )
@@ -52,19 +53,10 @@
 // Transform creates a MD5 hash of the Resource content and inserts that hash before
 // the extension in the filename.
 func (t *fingerprintTransformation) Transform(ctx *resources.ResourceTransformationCtx) error {
-	algo := t.algo
 
-	var h hash.Hash
-
-	switch algo {
-	case "md5":
-		h = md5.New()
-	case "sha256":
-		h = sha256.New()
-	case "sha512":
-		h = sha512.New()
-	default:
-		return fmt.Errorf("unsupported crypto algo: %q, use either md5, sha256 or sha512", algo)
+	h, err := newHash(t.algo)
+	if err != nil {
+		return err
 	}
 
 	io.Copy(io.MultiWriter(h, ctx.To), ctx.From)
@@ -73,9 +65,24 @@
 		return err
 	}
 
-	ctx.Data["Integrity"] = integrity(algo, d)
+	ctx.Data["Integrity"] = integrity(t.algo, d)
 	ctx.AddOutPathIdentifier("." + hex.EncodeToString(d[:]))
 	return nil
+}
+
+func newHash(algo string) (hash.Hash, error) {
+	switch algo {
+	case "md5":
+		return md5.New(), nil
+	case "sha256":
+		return sha256.New(), nil
+	case "sha384":
+		return sha512.New384(), nil
+	case "sha512":
+		return sha512.New(), nil
+	default:
+		return nil, errors.Errorf("unsupported crypto algo: %q, use either md5, sha256, sha384 or sha512", algo)
+	}
 }
 
 // Fingerprint applies fingerprinting of the given resource and hash algorithm.
--- /dev/null
+++ b/resources/resource_transformers/integrity/integrity_test.go
@@ -1,0 +1,48 @@
+// Copyright 2019 The Hugo Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package integrity
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestHashFromAlgo(t *testing.T) {
+
+	for _, algo := range []struct {
+		name string
+		bits int
+	}{
+		{"md5", 128},
+		{"sha256", 256},
+		{"sha384", 384},
+		{"sha512", 512},
+		{"shaman", -1},
+	} {
+
+		t.Run(algo.name, func(t *testing.T) {
+			assert := require.New(t)
+			h, err := newHash(algo.name)
+			if algo.bits > 0 {
+				assert.NoError(err)
+				assert.Equal(algo.bits/8, h.Size())
+			} else {
+				assert.Error(err)
+				assert.Contains(err.Error(), "use either md5, sha256, sha384 or sha512")
+			}
+
+		})
+	}
+}
--