diff --git a/lib/protocol/deviceid.go b/lib/protocol/deviceid.go index df1cbdec..c2a30b28 100644 --- a/lib/protocol/deviceid.go +++ b/lib/protocol/deviceid.go @@ -10,7 +10,6 @@ import ( "fmt" "strings" - "github.com/calmh/luhn" "github.com/syncthing/syncthing/lib/sha256" ) @@ -158,7 +157,7 @@ func luhnify(s string) (string, error) { for i := 0; i < 4; i++ { p := s[i*13 : (i+1)*13] copy(res[i*(13+1):], p) - l, err := luhn.Base32.Generate(p) + l, err := luhnBase32.generate(p) if err != nil { return "", err } @@ -176,7 +175,7 @@ func unluhnify(s string) (string, error) { for i := 0; i < 4; i++ { p := s[i*(13+1) : (i+1)*(13+1)-1] copy(res[i*13:], p) - l, err := luhn.Base32.Generate(p) + l, err := luhnBase32.generate(p) if err != nil { return "", err } diff --git a/lib/protocol/luhn.go b/lib/protocol/luhn.go new file mode 100644 index 00000000..ee5155f0 --- /dev/null +++ b/lib/protocol/luhn.go @@ -0,0 +1,53 @@ +// Copyright (C) 2014 The Protocol Authors. + +package protocol + +import ( + "fmt" + "strings" +) + +// An alphabet is a string of N characters, representing the digits of a given +// base N. +type luhnAlphabet string + +var ( + luhnBase32 luhnAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" +) + +// generate returns a check digit for the string s, which should be composed +// of characters from the Alphabet a. +func (a luhnAlphabet) generate(s string) (rune, error) { + factor := 1 + sum := 0 + n := len(a) + + for i := range s { + codepoint := strings.IndexByte(string(a), s[i]) + if codepoint == -1 { + return 0, fmt.Errorf("Digit %q not valid in alphabet %q", s[i], a) + } + 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]), nil +} + +// luhnValidate returns true if the last character of the string s is correct, for +// a string s composed of characters in the alphabet a. +func (a luhnAlphabet) luhnValidate(s string) bool { + t := s[:len(s)-1] + c, err := a.generate(t) + if err != nil { + return false + } + return rune(s[len(s)-1]) == c +} diff --git a/lib/protocol/luhn_test.go b/lib/protocol/luhn_test.go new file mode 100644 index 00000000..fe7f80c1 --- /dev/null +++ b/lib/protocol/luhn_test.go @@ -0,0 +1,48 @@ +// Copyright (C) 2014 The Protocol Authors. + +package protocol + +import ( + "testing" +) + +func TestGenerate(t *testing.T) { + // Base 6 Luhn + a := luhnAlphabet("abcdef") + c, err := a.generate("abcdef") + if err != nil { + t.Fatal(err) + } + if c != 'e' { + t.Errorf("Incorrect check digit %c != e", c) + } + + // Base 10 Luhn + a = luhnAlphabet("0123456789") + c, err = a.generate("7992739871") + if err != nil { + t.Fatal(err) + } + if c != '3' { + t.Errorf("Incorrect check digit %c != 3", c) + } +} + +func TestInvalidString(t *testing.T) { + a := luhnAlphabet("ABC") + _, err := a.generate("7992739871") + t.Log(err) + if err == nil { + t.Error("Unexpected nil error") + } +} + +func TestValidate(t *testing.T) { + a := luhnAlphabet("abcdef") + if !a.luhnValidate("abcdefe") { + t.Errorf("Incorrect validation response for abcdefe") + } + if a.luhnValidate("abcdefd") { + t.Errorf("Incorrect validation response for abcdefd") + } +} diff --git a/vendor/github.com/calmh/luhn/LICENSE b/vendor/github.com/calmh/luhn/LICENSE deleted file mode 100644 index 0e07d0e1..00000000 --- a/vendor/github.com/calmh/luhn/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (C) 2014 Jakob Borg - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -- The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/calmh/luhn/luhn.go b/vendor/github.com/calmh/luhn/luhn.go deleted file mode 100644 index f09f3f29..00000000 --- a/vendor/github.com/calmh/luhn/luhn.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (C) 2014 Jakob Borg - -// Package luhn generates and validates Luhn mod N check digits. -package luhn - -import ( - "fmt" - "strings" -) - -// An alphabet is a string of N characters, representing the digits of a given -// base N. -type Alphabet string - -var ( - Base32 Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" -) - -// Generate returns a check digit for the string s, which should be composed -// of characters from the Alphabet a. -func (a Alphabet) Generate(s string) (rune, error) { - factor := 1 - sum := 0 - n := len(a) - - for i := range s { - codepoint := strings.IndexByte(string(a), s[i]) - if codepoint == -1 { - return 0, fmt.Errorf("Digit %q not valid in alphabet %q", s[i], a) - } - 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]), nil -} - -// Validate returns true if the last character of the string s is correct, for -// a string s composed of characters in the alphabet a. -func (a Alphabet) Validate(s string) bool { - t := s[:len(s)-1] - c, err := a.Generate(t) - if err != nil { - return false - } - return rune(s[len(s)-1]) == c -} - -// NewAlphabet converts the given string an an Alphabet, verifying that it -// is correct. -func NewAlphabet(s string) (Alphabet, error) { - cm := make(map[byte]bool, len(s)) - for i := range s { - if cm[s[i]] { - return "", fmt.Errorf("Digit %q non-unique in alphabet %q", s[i], s) - } - cm[s[i]] = true - } - return Alphabet(s), nil -} diff --git a/vendor/manifest b/vendor/manifest index 72d9c1c0..801a83cc 100644 --- a/vendor/manifest +++ b/vendor/manifest @@ -49,14 +49,6 @@ "branch": "master", "notests": true }, - { - "importpath": "github.com/calmh/luhn", - "repository": "https://github.com/calmh/luhn", - "vcs": "git", - "revision": "c0f1d77264fb3d1bfc65b70eea6ee264058c57c0", - "branch": "master", - "notests": true - }, { "importpath": "github.com/calmh/xdr", "repository": "https://github.com/calmh/xdr",