update key format

main
Bill Mill 2 years ago
parent e1069936c5
commit 423a7d3d0f
  1. 46
      client/main.go
  2. 49
      server/main.go

@ -16,36 +16,50 @@ import (
"time"
)
func validKey() (foundPublicKey ed25519.PublicKey, foundPrivateKey ed25519.PrivateKey) {
func validKey() (ed25519.PublicKey, ed25519.PrivateKey) {
// A conforming key's final seven hex characters must be 83e followed by
// four characters that, interpreted as MMYY, express a valid month and
// year in the range 01/00 .. 12/99. Formally, the key must match this
//
// regex: /83e(0[1-9]|1[0-2])(\d\d)$/
//
// Because we have an odd-length hex string, we don't encode the '8' here
// and instead check it specifically in the hot loop... I'm open to ideas
// about how to do this better. I'd like to keep everything in the hot loop
// using the `bytes.compare` function which is assembly on most platforms,
// but we don't have a full byte for the `8`
keyEnd := fmt.Sprintf("3e%s", time.Now().AddDate(2, 0, 0).Format("0106"))
target, err := hex.DecodeString(keyEnd)
if err != nil {
panic(err)
}
expiryYear := time.Now().Year() + 1
keyEnd := fmt.Sprintf("ed%d", expiryYear)
nRoutines := runtime.NumCPU() - 1
var waitGroup sync.WaitGroup
var once sync.Once
fmt.Println(" - looking for a key that ends in", keyEnd)
fmt.Println(" - using", nRoutines, "cores")
fmt.Printf(" - looking for a key that ends in %s using %d routines\n",
keyEnd, nRoutines)
var publicKey ed25519.PublicKey
var privateKey ed25519.PrivateKey
waitGroup.Add(nRoutines)
for i := 0; i < nRoutines; i++ {
go func(num int) {
for foundPublicKey == nil {
for publicKey == nil {
pub, priv, err := ed25519.GenerateKey(nil)
if err != nil {
panic(err)
}
target, err := hex.DecodeString(keyEnd)
if err != nil {
panic(err)
}
if bytes.Compare(pub[29:32], target) == 0 {
// Here's where we check for the `8`; we do it after the
// bytes.Compare to keep the hot loop fast
if bytes.Compare(pub[29:32], target) == 0 && pub[28]&0x0F == 0x08 {
once.Do(func() {
fmt.Printf("%s\n", fmt.Sprintf("%x", pub))
foundPublicKey = pub
foundPrivateKey = priv
fmt.Printf("found %x\n", pub)
publicKey = pub
privateKey = priv
})
}
}
@ -55,7 +69,7 @@ func validKey() (foundPublicKey ed25519.PublicKey, foundPrivateKey ed25519.Priva
waitGroup.Wait()
return
return publicKey, privateKey
}
func fileExists(name string) bool {

@ -288,19 +288,44 @@ func (s *Spring83Server) publishBoard(w http.ResponseWriter, r *http.Request) {
}
}
// If the current four-digit year is YYYY, and the
// previous four-digit year is YYYX, the server must
// only accept PUTs for keys that end with the four
// digits YYYY or YYYX, preceded in turn by the two hex
// digits "ed". This is the years-of-use requirement.
// A conforming key's final seven hex characters must be "83e" followed by
// four characters that, interpreted as MMYY, express a valid month and
// year in the range 01/00 .. 12/99. Formally, the key must match this
// regex:
// /83e(0[1-9]|1[0-2])(\d\d)$/
//
// The server must reject other keys with 400 Bad
// Request.
// If the key does not match that regex, the server must reject the
// request, returning 403 Forbidden.
//
// The key is only valid in the two years preceding its encoded expiration
// date, and expires at the end of the last day of the month specified. For
// example, the key
last4 := string(keyStr[60:64])
if keyStr[58:60] != "ed" ||
(last4 != time.Now().Format("2006") &&
last4 != time.Now().AddDate(1, 0, 0).Format("2006")) {
http.Error(w, "Signature must end with edYYYY", http.StatusBadRequest)
t, err := time.Parse("0106", last4)
if err != nil {
log.Printf("Failed parsing last4 %s", last4)
http.Error(w, "Key must end with 83eMMYY", http.StatusBadRequest)
return
}
// This isn't quite the correct key expiry date; techncially the key
// expires on the last day of the month of its issuance; here we're just
// giving it an extra month. TODO be more accurate
twoYearsInHours := (365 * 2 * 24.0) + 31*24.0
timeDiff := t.Sub(time.Now()).Hours()
if keyStr[57:60] != "83e" {
log.Printf("Expected 83e %s", string(keyStr[57:60]))
http.Error(w, "Key must end with 83eMMYY", http.StatusBadRequest)
return
}
if timeDiff > twoYearsInHours {
log.Printf("Too far in future %f", timeDiff)
http.Error(w, "Key is not yet valid", http.StatusBadRequest)
return
}
if timeDiff < 0 {
log.Printf("Key expired %f", timeDiff)
http.Error(w, "Key is expired", http.StatusBadRequest)
return
}
@ -312,6 +337,8 @@ func (s *Spring83Server) publishBoard(w http.ResponseWriter, r *http.Request) {
return
}
// TODO: here we should find the <time> element and parse its time
expiry := time.Now().AddDate(0, 0, 7).Format(time.RFC3339)
_, err = s.db.Exec(`
INSERT INTO boards (key, board, expiry)

Loading…
Cancel
Save