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" "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 nRoutines := runtime.NumCPU() - 1
var waitGroup sync.WaitGroup var waitGroup sync.WaitGroup
var once sync.Once var once sync.Once
fmt.Println(" - looking for a key that ends in", keyEnd) fmt.Printf(" - looking for a key that ends in %s using %d routines\n",
fmt.Println(" - using", nRoutines, "cores") keyEnd, nRoutines)
var publicKey ed25519.PublicKey
var privateKey ed25519.PrivateKey
waitGroup.Add(nRoutines) waitGroup.Add(nRoutines)
for i := 0; i < nRoutines; i++ { for i := 0; i < nRoutines; i++ {
go func(num int) { go func(num int) {
for foundPublicKey == nil { for publicKey == nil {
pub, priv, err := ed25519.GenerateKey(nil) pub, priv, err := ed25519.GenerateKey(nil)
if err != nil { if err != nil {
panic(err) panic(err)
} }
target, err := hex.DecodeString(keyEnd) // Here's where we check for the `8`; we do it after the
if err != nil { // bytes.Compare to keep the hot loop fast
panic(err) if bytes.Compare(pub[29:32], target) == 0 && pub[28]&0x0F == 0x08 {
}
if bytes.Compare(pub[29:32], target) == 0 {
once.Do(func() { once.Do(func() {
fmt.Printf("%s\n", fmt.Sprintf("%x", pub)) fmt.Printf("found %x\n", pub)
foundPublicKey = pub publicKey = pub
foundPrivateKey = priv privateKey = priv
}) })
} }
} }
@ -55,7 +69,7 @@ func validKey() (foundPublicKey ed25519.PublicKey, foundPrivateKey ed25519.Priva
waitGroup.Wait() waitGroup.Wait()
return return publicKey, privateKey
} }
func fileExists(name string) bool { 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 // A conforming key's final seven hex characters must be "83e" followed by
// previous four-digit year is YYYX, the server must // four characters that, interpreted as MMYY, express a valid month and
// only accept PUTs for keys that end with the four // year in the range 01/00 .. 12/99. Formally, the key must match this
// digits YYYY or YYYX, preceded in turn by the two hex // regex:
// digits "ed". This is the years-of-use requirement. // /83e(0[1-9]|1[0-2])(\d\d)$/
// //
// The server must reject other keys with 400 Bad // If the key does not match that regex, the server must reject the
// Request. // 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]) last4 := string(keyStr[60:64])
if keyStr[58:60] != "ed" || t, err := time.Parse("0106", last4)
(last4 != time.Now().Format("2006") && if err != nil {
last4 != time.Now().AddDate(1, 0, 0).Format("2006")) { log.Printf("Failed parsing last4 %s", last4)
http.Error(w, "Signature must end with edYYYY", http.StatusBadRequest) 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 return
} }
@ -312,6 +337,8 @@ func (s *Spring83Server) publishBoard(w http.ResponseWriter, r *http.Request) {
return return
} }
// TODO: here we should find the <time> element and parse its time
expiry := time.Now().AddDate(0, 0, 7).Format(time.RFC3339) expiry := time.Now().AddDate(0, 0, 7).Format(time.RFC3339)
_, err = s.db.Exec(` _, err = s.db.Exec(`
INSERT INTO boards (key, board, expiry) INSERT INTO boards (key, board, expiry)

Loading…
Cancel
Save