Skip to content

Instantly share code, notes, and snippets.

@wybiral
Created May 7, 2019 20:46
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wybiral/a1b1de242b30aa30316d7b0b233f69f2 to your computer and use it in GitHub Desktop.
Save wybiral/a1b1de242b30aa30316d7b0b233f69f2 to your computer and use it in GitHub Desktop.
Experiment to get average time of SRI hash calculation from visiting browsers
package main
import (
"crypto/sha512"
"encoding/base64"
"fmt"
"log"
"math/rand"
"net/http"
"strings"
"sync"
"time"
)
// Number of tests to average
const nTests = 10
// Amount of random junk at end of CSS file
const cssPadding = 100 * 1024
var wg sync.WaitGroup
var resource []byte
var t0, t1 time.Time
func main() {
http.HandleFunc("/", handler)
log.Println("Serving on :8080")
http.ListenAndServe(":8080", nil)
}
func computeHash(b []byte) string {
h := sha512.Sum512(b)
return "SHA512-" + base64.StdEncoding.EncodeToString(h[:])
}
func handler(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
return
}
if strings.HasSuffix(r.URL.Path, ".css") {
css(w, r)
return
}
if strings.HasSuffix(r.URL.Path, ".png") {
img(w, r)
return
}
if r.URL.Path != "/" {
return
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
flusher, ok := w.(http.Flusher)
if !ok {
return
}
for i := 0; i < nTests; i++ {
w.Write([]byte(fmt.Sprintf("<div id=\"e%d\"></div>\n", i)))
}
flusher.Flush()
total := time.Duration(0)
for i := 0; i < nTests; i++ {
wg.Add(1)
s := "<link rel=\"stylesheet\" href=\"/c%d.css\" integrity=\"%s\">\n"
hash, data := createResource(i)
resource = data
w.Write([]byte(fmt.Sprintf(s, i, hash)))
flusher.Flush()
wg.Wait()
total += t1.Sub(t0)
}
log.Println(total / time.Duration(nTests))
}
func css(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/css")
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
w.Header().Set("Pragma", "no-cache")
w.Header().Set("Expires", "0")
w.Write(resource)
t0 = time.Now()
}
func img(w http.ResponseWriter, r *http.Request) {
t1 = time.Now()
wg.Done()
}
func createResource(i int) (string, []byte) {
data := []byte(fmt.Sprintf("#e%d{background:url(\"i%d.png\")}\n", i, i))
garbage := make([]byte, cssPadding)
rand.Read(garbage)
data = append(data, garbage...)
hash := computeHash(data)
return hash, data
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment