mirror of https://github.com/namecoin/ncdns
Repo split: remove tlsrestrictchromium
parent
1086a5b4c6
commit
431d2571bf
@ -1,108 +0,0 @@
|
||||
package tlsrestrictchromium
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// DNSHash converts an FQDN to DNS wire format, takes the SHA256 of it, and
|
||||
// then returns the result as a base64-encoded string. This happens to be how
|
||||
// Chromium's HSTS/HPKP database internally stores domain names.
|
||||
func DNSHash(fqdn string) (string, error) {
|
||||
domainNamePacked := make([]byte, 256)
|
||||
offset, err := dns.PackDomainName(fqdn, domainNamePacked, 0, nil, false)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error packing domain name %s: %s", fqdn, err)
|
||||
}
|
||||
|
||||
domainNameHashBytes := sha256.Sum256(domainNamePacked[:offset])
|
||||
domainNameHashB64String := base64.StdEncoding.EncodeToString(domainNameHashBytes[:])
|
||||
|
||||
return domainNameHashB64String, nil
|
||||
}
|
||||
|
||||
// BlockAllCAs returns an HSTS/HPKP rule (serializable to Chromium JSON format)
|
||||
// that blacklists all built-in CA's from signing certs for subdomains of the
|
||||
// given domain name. It doesn't include the domain name. It has only been
|
||||
// tested with TLD's; it is unclear whether the rule will have any undesired
|
||||
// effects if applied to a 2nd-level (or higher level) domain name.
|
||||
func BlockAllCAs() (map[string]interface{}, error) {
|
||||
ruleJSON := `{
|
||||
"dynamic_spki_hashes": [ "" ],
|
||||
"dynamic_spki_hashes_expiry": 99999999999.9999,
|
||||
"expiry": 99999999999.9999,
|
||||
"mode": "force-https",
|
||||
"pkp_include_subdomains": true,
|
||||
"pkp_observed": 1.0000,
|
||||
"report-uri": "",
|
||||
"sts_include_subdomains": false,
|
||||
"sts_observed": 1.0000
|
||||
}`
|
||||
|
||||
var rule map[string]interface{}
|
||||
|
||||
err := json.Unmarshal([]byte(ruleJSON), &rule)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error parsing BlockAllCAs rule: %s", err)
|
||||
}
|
||||
|
||||
sleeve, err := Sleeve256()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error generating sleeve256: %s", err)
|
||||
}
|
||||
rule["dynamic_spki_hashes"].([]interface{})[0] = "sha256/" + sleeve
|
||||
|
||||
return rule, nil
|
||||
}
|
||||
|
||||
// Sleeve256 calculates floor(2**256/pi), and encodes the result as base64. It
|
||||
// is intended to be used as a SHA256 hash where I don't have a preimage up my
|
||||
// sleeve.
|
||||
//
|
||||
// Python2 version originally by Ryan Castellucci. Go port, pi sourcing, and
|
||||
// base64 output by Jeremy Rand.
|
||||
func Sleeve256() (string, error) {
|
||||
var pi big.Float
|
||||
var exp256Float big.Float
|
||||
var fraction big.Float
|
||||
|
||||
var exp256 big.Int
|
||||
var fractionFloored big.Int
|
||||
|
||||
// 1024 bits of precision
|
||||
pi.SetPrec(1024)
|
||||
exp256Float.SetPrec(1024)
|
||||
fraction.SetPrec(1024)
|
||||
|
||||
// 1000 digits of pi from https://www.angio.net/pi/digits/1000.txt (first HTTPS result in Startpage results for "digits of pi")
|
||||
// (retrieved 2017 May 13.)
|
||||
piString := "3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420198"
|
||||
|
||||
_, _, err := pi.Parse(piString, 10)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error parsing pi: %s", err)
|
||||
}
|
||||
|
||||
exp256.Exp(big.NewInt(2), big.NewInt(256), nil)
|
||||
exp256Float.SetInt(&exp256)
|
||||
|
||||
fraction.Quo(&exp256Float, &pi)
|
||||
fraction.Int(&fractionFloored)
|
||||
|
||||
resultHex := fractionFloored.Text(16)
|
||||
|
||||
resultBytes, err := hex.DecodeString(resultHex)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error decoding hex: %s", err)
|
||||
}
|
||||
|
||||
resultB64 := base64.StdEncoding.EncodeToString(resultBytes)
|
||||
|
||||
return resultB64, nil
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
package tlsrestrictchromium_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/namecoin/ncdns/tlsrestrictchromium"
|
||||
)
|
||||
|
||||
func TestDnsHash(t *testing.T) {
|
||||
bitHash, err := tlsrestrictchromium.DNSHash("bit.")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
reference := "nprXwzm7mHINFnNah1Seo5SG0Pz9vW6dTXsYyvEC/PQ="
|
||||
|
||||
if bitHash != reference {
|
||||
t.Error("Wrong DNS hash of 'bit.' calculated: ", bitHash, " should be ", reference)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSleeve256(t *testing.T) {
|
||||
sleeve, err := tlsrestrictchromium.Sleeve256()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// To reproduce this with web-based tools, use https://www.wolframalpha.com/input/?i=hex%28floor%282^256%2Fpi%29%29
|
||||
// and then convert from hex to base64 via https://holtstrom.com/michael/tools/hextopem.php
|
||||
reference := "UXzBtyciCpT+E6vo+ppu4G2xSsyeIcgg/yix1e9d4rA="
|
||||
|
||||
if sleeve != reference {
|
||||
t.Error("Wrong sleeve256 calculated: ", sleeve, " should be ", reference)
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
||||
"github.com/namecoin/ncdns/tlsrestrictchromium"
|
||||
"gopkg.in/hlandau/easyconfig.v1"
|
||||
"gopkg.in/hlandau/easyconfig.v1/cflag"
|
||||
)
|
||||
|
||||
var (
|
||||
flagGroup = cflag.NewGroup(nil, "tlsrestrict")
|
||||
transportSecurityPathFlag = cflag.String(flagGroup, "chromium-ts-path", "", "Path to the TransportSecurity file in Chromium's profile folder. Make sure that no running instance of Chromium is using this profile folder; profile corruption could result otherwise.")
|
||||
domainFlag = cflag.String(flagGroup, "domain", "bit.", "Block built-in CA's from signing for any subdomains of this fully-qualified domain name.")
|
||||
)
|
||||
|
||||
func main() {
|
||||
config := easyconfig.Configurator{
|
||||
ProgramName: "tlsrestrict_chromium",
|
||||
}
|
||||
err := config.Parse(nil)
|
||||
if err != nil {
|
||||
log.Fatalf("Couldn't parse configuration: %s", err)
|
||||
}
|
||||
|
||||
transportSecurityPath := transportSecurityPathFlag.Value()
|
||||
domain := domainFlag.Value()
|
||||
|
||||
if transportSecurityPath == "" {
|
||||
log.Fatalf("Missing required --tlsrestrict.chromium-ts-path parameter")
|
||||
}
|
||||
|
||||
rawIn, err := ioutil.ReadFile(transportSecurityPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Couldn't read file %s: %s", transportSecurityPath, err)
|
||||
}
|
||||
|
||||
var data map[string]interface{}
|
||||
|
||||
err = json.Unmarshal(rawIn, &data)
|
||||
if err != nil {
|
||||
log.Fatalf("Couldn't parse file %s: %s", transportSecurityPath, err)
|
||||
}
|
||||
|
||||
// Chromium's TransportSecurity database uses keys of the form base64(sha256(dnsPack(fqdn)))
|
||||
domainDNSHashB64String, err := tlsrestrictchromium.DNSHash(domain)
|
||||
if err != nil {
|
||||
log.Fatalf("Couldn't hash domain name %s: %s", domain, err)
|
||||
}
|
||||
|
||||
data[domainDNSHashB64String], err = tlsrestrictchromium.BlockAllCAs()
|
||||
if err != nil {
|
||||
log.Fatalf("Couldn't assign BlockAllCAs: %s", err)
|
||||
}
|
||||
|
||||
rawOut, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
log.Fatalf("Couldn't marshal data: %s", err)
|
||||
}
|
||||
|
||||
// 0600 seems to be the default mode in Chromium on Fedora
|
||||
err = ioutil.WriteFile(transportSecurityPath, rawOut, 0600)
|
||||
if err != nil {
|
||||
log.Fatalf("Couldn't write file %s: %s", transportSecurityPath, err)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue