Refactor node ID handling, use check digits (fixes #269)

New node ID:s contain four Luhn check digits and are grouped
differently. Code uses NodeID type instead of string, so it's formatted
homogenously everywhere.
This commit is contained in:
Jakob Borg
2014-06-30 01:42:03 +02:00
parent fee8289c0a
commit 8f3effed32
35 changed files with 563 additions and 478 deletions

37
luhn/luhn.go Normal file
View File

@@ -0,0 +1,37 @@
package luhn
import "strings"
type Alphabet string
var (
Base32 Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567="
Base32Trimmed Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
)
func (a Alphabet) Generate(s string) rune {
factor := 1
sum := 0
n := len(a)
for i := range s {
codepoint := strings.IndexByte(string(a), s[i])
addend := factor * codepoint
if factor == 2 {
factor = 1
} else {
factor = 2
}
addend = (addend / n) + (addend % n)
sum += addend
}
remainder := sum % n
checkCodepoint := (n - remainder) % n
return rune(a[checkCodepoint])
}
func (a Alphabet) Validate(s string) bool {
t := s[:len(s)-1]
c := a.Generate(t)
return rune(s[len(s)-1]) == c
}

25
luhn/luhn_test.go Normal file
View File

@@ -0,0 +1,25 @@
package luhn_test
import (
"testing"
"github.com/calmh/syncthing/luhn"
)
func TestGenerate(t *testing.T) {
a := luhn.Alphabet("abcdef")
c := a.Generate("abcdef")
if c != 'e' {
t.Errorf("Incorrect check digit %c != e", c)
}
}
func TestValidate(t *testing.T) {
a := luhn.Alphabet("abcdef")
if !a.Validate("abcdefe") {
t.Errorf("Incorrect validation response for abcdefe")
}
if a.Validate("abcdefd") {
t.Errorf("Incorrect validation response for abcdefd")
}
}