Addressed issue #1 - Byte order was the problem

The counter needs to be represented in bigendian format.
Unfortunately with commit #00045cb I made the unfortunate choice to swap the endiannes from big-endian to little-endian.
This broke the functionality for certain counters.

- [x] Added Go vendoring
- [x] Bumped version of golang in travis yml file
- [x] Removed conversion files and instead used import of convert sec51 external library
This commit is contained in:
silenteh 2016-04-24 22:24:31 +02:00
parent eada29e8a3
commit 72a472700b
91 changed files with 134 additions and 3182 deletions

View File

@ -1,7 +1,7 @@
language: go language: go
go: go:
- 1.5.3 - 1.6.2
install: install:
- go get "github.com/sec51/qrcode" - go get "github.com/sec51/qrcode"

27
Godeps/Godeps.json generated
View File

@ -1,16 +1,15 @@
{ {
"ImportPath": "github.com/sec51/twofactor", "ImportPath": "github.com/sec51/twofactor",
"GoVersion": "go1.5.3", "GoVersion": "go1.6",
"GodepVersion": "v62",
"Deps": [ "Deps": [
{ {
"ImportPath": "code.google.com/p/rsc/gf256", "ImportPath": "github.com/sec51/convert",
"Comment": "null-258", "Rev": "8ed1f399b5e0a9a9620c74cfd5aec3682d8328ab"
"Rev": "'2d8aa6027fab93979a3b4ecdbeb1ba430b489318'"
}, },
{ {
"ImportPath": "code.google.com/p/rsc/qr/coding", "ImportPath": "github.com/sec51/convert/bigendian",
"Comment": "null-258", "Rev": "8ed1f399b5e0a9a9620c74cfd5aec3682d8328ab"
"Rev": "'2d8aa6027fab93979a3b4ecdbeb1ba430b489318'"
}, },
{ {
"ImportPath": "github.com/sec51/convert/smallendian", "ImportPath": "github.com/sec51/convert/smallendian",
@ -18,11 +17,19 @@
}, },
{ {
"ImportPath": "github.com/sec51/cryptoengine", "ImportPath": "github.com/sec51/cryptoengine",
"Rev": "e498a1921e25d2b08a85cadc66e3e0c3e0763129" "Rev": "36f5a7d2e2059ebd9e631d8a5d09c250f73975d3"
}, },
{ {
"ImportPath": "github.com/sec51/rsc/qr", "ImportPath": "github.com/sec51/gf256",
"Rev": "ccfe198e06521e3835029dbdd1ee3ecd799aa049" "Rev": "2454accbeb9e6b0e2e53b01e1d641c7157251ed4"
},
{
"ImportPath": "github.com/sec51/qrcode",
"Rev": "b7779abbcaf1ec4de65f586a85fe24db31d45e7c"
},
{
"ImportPath": "github.com/sec51/qrcode/coding",
"Rev": "b7779abbcaf1ec4de65f586a85fe24db31d45e7c"
}, },
{ {
"ImportPath": "golang.org/x/crypto/curve25519", "ImportPath": "golang.org/x/crypto/curve25519",

2
Godeps/_workspace/.gitignore generated vendored
View File

@ -1,2 +0,0 @@
/pkg
/bin

View File

@ -1,815 +0,0 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package coding implements low-level QR coding details.
package coding
import (
"fmt"
"strconv"
"strings"
"code.google.com/p/rsc/gf256"
)
// Field is the field for QR error correction.
var Field = gf256.NewField(0x11d, 2)
// A Version represents a QR version.
// The version specifies the size of the QR code:
// a QR code with version v has 4v+17 pixels on a side.
// Versions number from 1 to 40: the larger the version,
// the more information the code can store.
type Version int
const MinVersion = 1
const MaxVersion = 40
func (v Version) String() string {
return strconv.Itoa(int(v))
}
func (v Version) sizeClass() int {
if v <= 9 {
return 0
}
if v <= 26 {
return 1
}
return 2
}
// DataBytes returns the number of data bytes that can be
// stored in a QR code with the given version and level.
func (v Version) DataBytes(l Level) int {
vt := &vtab[v]
lev := &vt.level[l]
return vt.bytes - lev.nblock*lev.check
}
// Encoding implements a QR data encoding scheme.
// The implementations--Numeric, Alphanumeric, and String--specify
// the character set and the mapping from UTF-8 to code bits.
// The more restrictive the mode, the fewer code bits are needed.
type Encoding interface {
Check() error
Bits(v Version) int
Encode(b *Bits, v Version)
}
type Bits struct {
b []byte
nbit int
}
func (b *Bits) Reset() {
b.b = b.b[:0]
b.nbit = 0
}
func (b *Bits) Bits() int {
return b.nbit
}
func (b *Bits) Bytes() []byte {
if b.nbit%8 != 0 {
panic("fractional byte")
}
return b.b
}
func (b *Bits) Append(p []byte) {
if b.nbit%8 != 0 {
panic("fractional byte")
}
b.b = append(b.b, p...)
b.nbit += 8 * len(p)
}
func (b *Bits) Write(v uint, nbit int) {
for nbit > 0 {
n := nbit
if n > 8 {
n = 8
}
if b.nbit%8 == 0 {
b.b = append(b.b, 0)
} else {
m := -b.nbit & 7
if n > m {
n = m
}
}
b.nbit += n
sh := uint(nbit - n)
b.b[len(b.b)-1] |= uint8(v >> sh << uint(-b.nbit&7))
v -= v >> sh << sh
nbit -= n
}
}
// Num is the encoding for numeric data.
// The only valid characters are the decimal digits 0 through 9.
type Num string
func (s Num) String() string {
return fmt.Sprintf("Num(%#q)", string(s))
}
func (s Num) Check() error {
for _, c := range s {
if c < '0' || '9' < c {
return fmt.Errorf("non-numeric string %#q", string(s))
}
}
return nil
}
var numLen = [3]int{10, 12, 14}
func (s Num) Bits(v Version) int {
return 4 + numLen[v.sizeClass()] + (10*len(s)+2)/3
}
func (s Num) Encode(b *Bits, v Version) {
b.Write(1, 4)
b.Write(uint(len(s)), numLen[v.sizeClass()])
var i int
for i = 0; i+3 <= len(s); i += 3 {
w := uint(s[i]-'0')*100 + uint(s[i+1]-'0')*10 + uint(s[i+2]-'0')
b.Write(w, 10)
}
switch len(s) - i {
case 1:
w := uint(s[i] - '0')
b.Write(w, 4)
case 2:
w := uint(s[i]-'0')*10 + uint(s[i+1]-'0')
b.Write(w, 7)
}
}
// Alpha is the encoding for alphanumeric data.
// The valid characters are 0-9A-Z$%*+-./: and space.
type Alpha string
const alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"
func (s Alpha) String() string {
return fmt.Sprintf("Alpha(%#q)", string(s))
}
func (s Alpha) Check() error {
for _, c := range s {
if strings.IndexRune(alphabet, c) < 0 {
return fmt.Errorf("non-alphanumeric string %#q", string(s))
}
}
return nil
}
var alphaLen = [3]int{9, 11, 13}
func (s Alpha) Bits(v Version) int {
return 4 + alphaLen[v.sizeClass()] + (11*len(s)+1)/2
}
func (s Alpha) Encode(b *Bits, v Version) {
b.Write(2, 4)
b.Write(uint(len(s)), alphaLen[v.sizeClass()])
var i int
for i = 0; i+2 <= len(s); i += 2 {
w := uint(strings.IndexRune(alphabet, rune(s[i])))*45 +
uint(strings.IndexRune(alphabet, rune(s[i+1])))
b.Write(w, 11)
}
if i < len(s) {
w := uint(strings.IndexRune(alphabet, rune(s[i])))
b.Write(w, 6)
}
}
// String is the encoding for 8-bit data. All bytes are valid.
type String string
func (s String) String() string {
return fmt.Sprintf("String(%#q)", string(s))
}
func (s String) Check() error {
return nil
}
var stringLen = [3]int{8, 16, 16}
func (s String) Bits(v Version) int {
return 4 + stringLen[v.sizeClass()] + 8*len(s)
}
func (s String) Encode(b *Bits, v Version) {
b.Write(4, 4)
b.Write(uint(len(s)), stringLen[v.sizeClass()])
for i := 0; i < len(s); i++ {
b.Write(uint(s[i]), 8)
}
}
// A Pixel describes a single pixel in a QR code.
type Pixel uint32
const (
Black Pixel = 1 << iota
Invert
)
func (p Pixel) Offset() uint {
return uint(p >> 6)
}
func OffsetPixel(o uint) Pixel {
return Pixel(o << 6)
}
func (r PixelRole) Pixel() Pixel {
return Pixel(r << 2)
}
func (p Pixel) Role() PixelRole {
return PixelRole(p>>2) & 15
}
func (p Pixel) String() string {
s := p.Role().String()
if p&Black != 0 {
s += "+black"
}
if p&Invert != 0 {
s += "+invert"
}
s += "+" + strconv.FormatUint(uint64(p.Offset()), 10)
return s
}
// A PixelRole describes the role of a QR pixel.
type PixelRole uint32
const (
_ PixelRole = iota
Position // position squares (large)
Alignment // alignment squares (small)
Timing // timing strip between position squares
Format // format metadata
PVersion // version pattern
Unused // unused pixel
Data // data bit
Check // error correction check bit
Extra
)
var roles = []string{
"",
"position",
"alignment",
"timing",
"format",
"pversion",
"unused",
"data",
"check",
"extra",
}
func (r PixelRole) String() string {
if Position <= r && r <= Check {
return roles[r]
}
return strconv.Itoa(int(r))
}
// A Level represents a QR error correction level.
// From least to most tolerant of errors, they are L, M, Q, H.
type Level int
const (
L Level = iota
M
Q
H
)
func (l Level) String() string {
if L <= l && l <= H {
return "LMQH"[l : l+1]
}
return strconv.Itoa(int(l))
}
// A Code is a square pixel grid.
type Code struct {
Bitmap []byte // 1 is black, 0 is white
Size int // number of pixels on a side
Stride int // number of bytes per row
}
func (c *Code) Black(x, y int) bool {
return 0 <= x && x < c.Size && 0 <= y && y < c.Size &&
c.Bitmap[y*c.Stride+x/8]&(1<<uint(7-x&7)) != 0
}
// A Mask describes a mask that is applied to the QR
// code to avoid QR artifacts being interpreted as
// alignment and timing patterns (such as the squares
// in the corners). Valid masks are integers from 0 to 7.
type Mask int
// http://www.swetake.com/qr/qr5_en.html
var mfunc = []func(int, int) bool{
func(i, j int) bool { return (i+j)%2 == 0 },
func(i, j int) bool { return i%2 == 0 },
func(i, j int) bool { return j%3 == 0 },
func(i, j int) bool { return (i+j)%3 == 0 },
func(i, j int) bool { return (i/2+j/3)%2 == 0 },
func(i, j int) bool { return i*j%2+i*j%3 == 0 },
func(i, j int) bool { return (i*j%2+i*j%3)%2 == 0 },
func(i, j int) bool { return (i*j%3+(i+j)%2)%2 == 0 },
}
func (m Mask) Invert(y, x int) bool {
if m < 0 {
return false
}
return mfunc[m](y, x)
}
// A Plan describes how to construct a QR code
// with a specific version, level, and mask.
type Plan struct {
Version Version
Level Level
Mask Mask
DataBytes int // number of data bytes
CheckBytes int // number of error correcting (checksum) bytes
Blocks int // number of data blocks
Pixel [][]Pixel // pixel map
}
// NewPlan returns a Plan for a QR code with the given
// version, level, and mask.
func NewPlan(version Version, level Level, mask Mask) (*Plan, error) {
p, err := vplan(version)
if err != nil {
return nil, err
}
if err := fplan(level, mask, p); err != nil {
return nil, err
}
if err := lplan(version, level, p); err != nil {
return nil, err
}
if err := mplan(mask, p); err != nil {
return nil, err
}
return p, nil
}
func (b *Bits) Pad(n int) {
if n < 0 {
panic("qr: invalid pad size")
}
if n <= 4 {
b.Write(0, n)
} else {
b.Write(0, 4)
n -= 4
n -= -b.Bits() & 7
b.Write(0, -b.Bits()&7)
pad := n / 8
for i := 0; i < pad; i += 2 {
b.Write(0xec, 8)
if i+1 >= pad {
break
}
b.Write(0x11, 8)
}
}
}
func (b *Bits) AddCheckBytes(v Version, l Level) {
nd := v.DataBytes(l)
if b.nbit < nd*8 {
b.Pad(nd*8 - b.nbit)
}
if b.nbit != nd*8 {
panic("qr: too much data")
}
dat := b.Bytes()
vt := &vtab[v]
lev := &vt.level[l]
db := nd / lev.nblock
extra := nd % lev.nblock
chk := make([]byte, lev.check)
rs := gf256.NewRSEncoder(Field, lev.check)
for i := 0; i < lev.nblock; i++ {
if i == lev.nblock-extra {
db++
}
rs.ECC(dat[:db], chk)
b.Append(chk)
dat = dat[db:]
}
if len(b.Bytes()) != vt.bytes {
panic("qr: internal error")
}
}
func (p *Plan) Encode(text ...Encoding) (*Code, error) {
var b Bits
for _, t := range text {
if err := t.Check(); err != nil {
return nil, err
}
t.Encode(&b, p.Version)
}
if b.Bits() > p.DataBytes*8 {
return nil, fmt.Errorf("cannot encode %d bits into %d-bit code", b.Bits(), p.DataBytes*8)
}
b.AddCheckBytes(p.Version, p.Level)
bytes := b.Bytes()
// Now we have the checksum bytes and the data bytes.
// Construct the actual code.
c := &Code{Size: len(p.Pixel), Stride: (len(p.Pixel) + 7) &^ 7}
c.Bitmap = make([]byte, c.Stride*c.Size)
crow := c.Bitmap
for _, row := range p.Pixel {
for x, pix := range row {
switch pix.Role() {
case Data, Check:
o := pix.Offset()
if bytes[o/8]&(1<<uint(7-o&7)) != 0 {
pix ^= Black
}
}
if pix&Black != 0 {
crow[x/8] |= 1 << uint(7-x&7)
}
}
crow = crow[c.Stride:]
}
return c, nil
}
// A version describes metadata associated with a version.
type version struct {
apos int
astride int
bytes int
pattern int
level [4]level
}
type level struct {
nblock int
check int
}
var vtab = []version{
{},
{100, 100, 26, 0x0, [4]level{{1, 7}, {1, 10}, {1, 13}, {1, 17}}}, // 1
{16, 100, 44, 0x0, [4]level{{1, 10}, {1, 16}, {1, 22}, {1, 28}}}, // 2
{20, 100, 70, 0x0, [4]level{{1, 15}, {1, 26}, {2, 18}, {2, 22}}}, // 3
{24, 100, 100, 0x0, [4]level{{1, 20}, {2, 18}, {2, 26}, {4, 16}}}, // 4
{28, 100, 134, 0x0, [4]level{{1, 26}, {2, 24}, {4, 18}, {4, 22}}}, // 5
{32, 100, 172, 0x0, [4]level{{2, 18}, {4, 16}, {4, 24}, {4, 28}}}, // 6
{20, 16, 196, 0x7c94, [4]level{{2, 20}, {4, 18}, {6, 18}, {5, 26}}}, // 7
{22, 18, 242, 0x85bc, [4]level{{2, 24}, {4, 22}, {6, 22}, {6, 26}}}, // 8
{24, 20, 292, 0x9a99, [4]level{{2, 30}, {5, 22}, {8, 20}, {8, 24}}}, // 9
{26, 22, 346, 0xa4d3, [4]level{{4, 18}, {5, 26}, {8, 24}, {8, 28}}}, // 10
{28, 24, 404, 0xbbf6, [4]level{{4, 20}, {5, 30}, {8, 28}, {11, 24}}}, // 11
{30, 26, 466, 0xc762, [4]level{{4, 24}, {8, 22}, {10, 26}, {11, 28}}}, // 12
{32, 28, 532, 0xd847, [4]level{{4, 26}, {9, 22}, {12, 24}, {16, 22}}}, // 13
{24, 20, 581, 0xe60d, [4]level{{4, 30}, {9, 24}, {16, 20}, {16, 24}}}, // 14
{24, 22, 655, 0xf928, [4]level{{6, 22}, {10, 24}, {12, 30}, {18, 24}}}, // 15
{24, 24, 733, 0x10b78, [4]level{{6, 24}, {10, 28}, {17, 24}, {16, 30}}}, // 16
{28, 24, 815, 0x1145d, [4]level{{6, 28}, {11, 28}, {16, 28}, {19, 28}}}, // 17
{28, 26, 901, 0x12a17, [4]level{{6, 30}, {13, 26}, {18, 28}, {21, 28}}}, // 18
{28, 28, 991, 0x13532, [4]level{{7, 28}, {14, 26}, {21, 26}, {25, 26}}}, // 19
{32, 28, 1085, 0x149a6, [4]level{{8, 28}, {16, 26}, {20, 30}, {25, 28}}}, // 20
{26, 22, 1156, 0x15683, [4]level{{8, 28}, {17, 26}, {23, 28}, {25, 30}}}, // 21
{24, 24, 1258, 0x168c9, [4]level{{9, 28}, {17, 28}, {23, 30}, {34, 24}}}, // 22
{28, 24, 1364, 0x177ec, [4]level{{9, 30}, {18, 28}, {25, 30}, {30, 30}}}, // 23
{26, 26, 1474, 0x18ec4, [4]level{{10, 30}, {20, 28}, {27, 30}, {32, 30}}}, // 24
{30, 26, 1588, 0x191e1, [4]level{{12, 26}, {21, 28}, {29, 30}, {35, 30}}}, // 25
{28, 28, 1706, 0x1afab, [4]level{{12, 28}, {23, 28}, {34, 28}, {37, 30}}}, // 26
{32, 28, 1828, 0x1b08e, [4]level{{12, 30}, {25, 28}, {34, 30}, {40, 30}}}, // 27
{24, 24, 1921, 0x1cc1a, [4]level{{13, 30}, {26, 28}, {35, 30}, {42, 30}}}, // 28
{28, 24, 2051, 0x1d33f, [4]level{{14, 30}, {28, 28}, {38, 30}, {45, 30}}}, // 29
{24, 26, 2185, 0x1ed75, [4]level{{15, 30}, {29, 28}, {40, 30}, {48, 30}}}, // 30
{28, 26, 2323, 0x1f250, [4]level{{16, 30}, {31, 28}, {43, 30}, {51, 30}}}, // 31
{32, 26, 2465, 0x209d5, [4]level{{17, 30}, {33, 28}, {45, 30}, {54, 30}}}, // 32
{28, 28, 2611, 0x216f0, [4]level{{18, 30}, {35, 28}, {48, 30}, {57, 30}}}, // 33
{32, 28, 2761, 0x228ba, [4]level{{19, 30}, {37, 28}, {51, 30}, {60, 30}}}, // 34
{28, 24, 2876, 0x2379f, [4]level{{19, 30}, {38, 28}, {53, 30}, {63, 30}}}, // 35
{22, 26, 3034, 0x24b0b, [4]level{{20, 30}, {40, 28}, {56, 30}, {66, 30}}}, // 36
{26, 26, 3196, 0x2542e, [4]level{{21, 30}, {43, 28}, {59, 30}, {70, 30}}}, // 37
{30, 26, 3362, 0x26a64, [4]level{{22, 30}, {45, 28}, {62, 30}, {74, 30}}}, // 38
{24, 28, 3532, 0x27541, [4]level{{24, 30}, {47, 28}, {65, 30}, {77, 30}}}, // 39
{28, 28, 3706, 0x28c69, [4]level{{25, 30}, {49, 28}, {68, 30}, {81, 30}}}, // 40
}
func grid(siz int) [][]Pixel {
m := make([][]Pixel, siz)
pix := make([]Pixel, siz*siz)
for i := range m {
m[i], pix = pix[:siz], pix[siz:]
}
return m
}
// vplan creates a Plan for the given version.
func vplan(v Version) (*Plan, error) {
p := &Plan{Version: v}
if v < 1 || v > 40 {
return nil, fmt.Errorf("invalid QR version %d", int(v))
}
siz := 17 + int(v)*4
m := grid(siz)
p.Pixel = m
// Timing markers (overwritten by boxes).
const ti = 6 // timing is in row/column 6 (counting from 0)
for i := range m {
p := Timing.Pixel()
if i&1 == 0 {
p |= Black
}
m[i][ti] = p
m[ti][i] = p
}
// Position boxes.
posBox(m, 0, 0)
posBox(m, siz-7, 0)
posBox(m, 0, siz-7)
// Alignment boxes.
info := &vtab[v]
for x := 4; x+5 < siz; {
for y := 4; y+5 < siz; {
// don't overwrite timing markers
if (x < 7 && y < 7) || (x < 7 && y+5 >= siz-7) || (x+5 >= siz-7 && y < 7) {
} else {
alignBox(m, x, y)
}
if y == 4 {
y = info.apos
} else {
y += info.astride
}
}
if x == 4 {
x = info.apos
} else {
x += info.astride
}
}
// Version pattern.
pat := vtab[v].pattern
if pat != 0 {
v := pat
for x := 0; x < 6; x++ {
for y := 0; y < 3; y++ {
p := PVersion.Pixel()
if v&1 != 0 {
p |= Black
}
m[siz-11+y][x] = p
m[x][siz-11+y] = p
v >>= 1
}
}
}
// One lonely black pixel
m[siz-8][8] = Unused.Pixel() | Black
return p, nil
}
// fplan adds the format pixels
func fplan(l Level, m Mask, p *Plan) error {
// Format pixels.
fb := uint32(l^1) << 13 // level: L=01, M=00, Q=11, H=10
fb |= uint32(m) << 10 // mask
const formatPoly = 0x537
rem := fb
for i := 14; i >= 10; i-- {
if rem&(1<<uint(i)) != 0 {
rem ^= formatPoly << uint(i-10)
}
}
fb |= rem
invert := uint32(0x5412)
siz := len(p.Pixel)
for i := uint(0); i < 15; i++ {
pix := Format.Pixel() + OffsetPixel(i)
if (fb>>i)&1 == 1 {
pix |= Black
}
if (invert>>i)&1 == 1 {
pix ^= Invert | Black
}
// top left
switch {
case i < 6:
p.Pixel[i][8] = pix
case i < 8:
p.Pixel[i+1][8] = pix
case i < 9:
p.Pixel[8][7] = pix
default:
p.Pixel[8][14-i] = pix
}
// bottom right
switch {
case i < 8:
p.Pixel[8][siz-1-int(i)] = pix
default:
p.Pixel[siz-1-int(14-i)][8] = pix
}
}
return nil
}
// lplan edits a version-only Plan to add information
// about the error correction levels.
func lplan(v Version, l Level, p *Plan) error {
p.Level = l
nblock := vtab[v].level[l].nblock
ne := vtab[v].level[l].check
nde := (vtab[v].bytes - ne*nblock) / nblock
extra := (vtab[v].bytes - ne*nblock) % nblock
dataBits := (nde*nblock + extra) * 8
checkBits := ne * nblock * 8
p.DataBytes = vtab[v].bytes - ne*nblock
p.CheckBytes = ne * nblock
p.Blocks = nblock
// Make data + checksum pixels.
data := make([]Pixel, dataBits)
for i := range data {
data[i] = Data.Pixel() | OffsetPixel(uint(i))
}
check := make([]Pixel, checkBits)
for i := range check {
check[i] = Check.Pixel() | OffsetPixel(uint(i+dataBits))
}
// Split into blocks.
dataList := make([][]Pixel, nblock)
checkList := make([][]Pixel, nblock)
for i := 0; i < nblock; i++ {
// The last few blocks have an extra data byte (8 pixels).
nd := nde
if i >= nblock-extra {
nd++
}
dataList[i], data = data[0:nd*8], data[nd*8:]
checkList[i], check = check[0:ne*8], check[ne*8:]
}
if len(data) != 0 || len(check) != 0 {
panic("data/check math")
}
// Build up bit sequence, taking first byte of each block,
// then second byte, and so on. Then checksums.
bits := make([]Pixel, dataBits+checkBits)
dst := bits
for i := 0; i < nde+1; i++ {
for _, b := range dataList {
if i*8 < len(b) {
copy(dst, b[i*8:(i+1)*8])
dst = dst[8:]
}
}
}
for i := 0; i < ne; i++ {
for _, b := range checkList {
if i*8 < len(b) {
copy(dst, b[i*8:(i+1)*8])
dst = dst[8:]
}
}
}
if len(dst) != 0 {
panic("dst math")
}
// Sweep up pair of columns,
// then down, assigning to right then left pixel.
// Repeat.
// See Figure 2 of http://www.pclviewer.com/rs2/qrtopology.htm
siz := len(p.Pixel)
rem := make([]Pixel, 7)
for i := range rem {
rem[i] = Extra.Pixel()
}
src := append(bits, rem...)
for x := siz; x > 0; {
for y := siz - 1; y >= 0; y-- {
if p.Pixel[y][x-1].Role() == 0 {
p.Pixel[y][x-1], src = src[0], src[1:]
}
if p.Pixel[y][x-2].Role() == 0 {
p.Pixel[y][x-2], src = src[0], src[1:]
}
}
x -= 2
if x == 7 { // vertical timing strip
x--
}
for y := 0; y < siz; y++ {
if p.Pixel[y][x-1].Role() == 0 {
p.Pixel[y][x-1], src = src[0], src[1:]
}
if p.Pixel[y][x-2].Role() == 0 {
p.Pixel[y][x-2], src = src[0], src[1:]
}
}
x -= 2
}
return nil
}
// mplan edits a version+level-only Plan to add the mask.
func mplan(m Mask, p *Plan) error {
p.Mask = m
for y, row := range p.Pixel {
for x, pix := range row {
if r := pix.Role(); (r == Data || r == Check || r == Extra) && p.Mask.Invert(y, x) {
row[x] ^= Black | Invert
}
}
}
return nil
}
// posBox draws a position (large) box at upper left x, y.
func posBox(m [][]Pixel, x, y int) {
pos := Position.Pixel()
// box
for dy := 0; dy < 7; dy++ {
for dx := 0; dx < 7; dx++ {
p := pos
if dx == 0 || dx == 6 || dy == 0 || dy == 6 || 2 <= dx && dx <= 4 && 2 <= dy && dy <= 4 {
p |= Black
}
m[y+dy][x+dx] = p
}
}
// white border
for dy := -1; dy < 8; dy++ {
if 0 <= y+dy && y+dy < len(m) {
if x > 0 {
m[y+dy][x-1] = pos
}
if x+7 < len(m) {
m[y+dy][x+7] = pos
}
}
}
for dx := -1; dx < 8; dx++ {
if 0 <= x+dx && x+dx < len(m) {
if y > 0 {
m[y-1][x+dx] = pos
}
if y+7 < len(m) {
m[y+7][x+dx] = pos
}
}
}
}
// alignBox draw an alignment (small) box at upper left x, y.
func alignBox(m [][]Pixel, x, y int) {
// box
align := Alignment.Pixel()
for dy := 0; dy < 5; dy++ {
for dx := 0; dx < 5; dx++ {
p := align
if dx == 0 || dx == 4 || dy == 0 || dy == 4 || dx == 2 && dy == 2 {
p |= Black
}
m[y+dy][x+dx] = p
}
}
}

View File

@ -1,34 +0,0 @@
{
"ImportPath": "github.com/sec51/cryptoengine",
"GoVersion": "go1.5.1",
"Deps": [
{
"ImportPath": "github.com/sec51/convert/smallendian",
"Rev": "8ed1f399b5e0a9a9620c74cfd5aec3682d8328ab"
},
{
"ImportPath": "golang.org/x/crypto/curve25519",
"Rev": "beef0f4390813b96e8e68fd78570396d0f4751fc"
},
{
"ImportPath": "golang.org/x/crypto/hkdf",
"Rev": "beef0f4390813b96e8e68fd78570396d0f4751fc"
},
{
"ImportPath": "golang.org/x/crypto/nacl/box",
"Rev": "beef0f4390813b96e8e68fd78570396d0f4751fc"
},
{
"ImportPath": "golang.org/x/crypto/nacl/secretbox",
"Rev": "beef0f4390813b96e8e68fd78570396d0f4751fc"
},
{
"ImportPath": "golang.org/x/crypto/poly1305",
"Rev": "beef0f4390813b96e8e68fd78570396d0f4751fc"
},
{
"ImportPath": "golang.org/x/crypto/salsa20/salsa",
"Rev": "beef0f4390813b96e8e68fd78570396d0f4751fc"
}
]
}

View File

@ -1,5 +0,0 @@
This directory tree is generated automatically by godep.
Please do not edit.
See https://github.com/tools/godep for more information.

View File

@ -1 +0,0 @@
trailing backslash at end of expressi

View File

@ -1,21 +0,0 @@
// this file is used for fuzz testing only
package main
import (
"fmt"
_ "github.com/sec51/cryptoengine"
)
func main() {
fmt.Println("This function is for fuzzing only.")
}
// func Fuzz(data []byte) int {
// _, err := cryptoengine.MessageFromBytes(data)
// if err == nil { // means it was parsed successfully
// return 1
// }
// fmt.Printf("Error parsing message: %s with data %s\n", err, data)
// return 0
// }

View File

@ -1,27 +0,0 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,149 +0,0 @@
// +build ignore
package main
import "fmt"
// tables from qrencode-3.1.1/qrspec.c
var capacity = [41]struct {
width int
words int
remainder int
ec [4]int
}{
{0, 0, 0, [4]int{0, 0, 0, 0}},
{21, 26, 0, [4]int{7, 10, 13, 17}}, // 1
{25, 44, 7, [4]int{10, 16, 22, 28}},
{29, 70, 7, [4]int{15, 26, 36, 44}},
{33, 100, 7, [4]int{20, 36, 52, 64}},
{37, 134, 7, [4]int{26, 48, 72, 88}}, // 5
{41, 172, 7, [4]int{36, 64, 96, 112}},
{45, 196, 0, [4]int{40, 72, 108, 130}},
{49, 242, 0, [4]int{48, 88, 132, 156}},
{53, 292, 0, [4]int{60, 110, 160, 192}},
{57, 346, 0, [4]int{72, 130, 192, 224}}, //10
{61, 404, 0, [4]int{80, 150, 224, 264}},
{65, 466, 0, [4]int{96, 176, 260, 308}},
{69, 532, 0, [4]int{104, 198, 288, 352}},
{73, 581, 3, [4]int{120, 216, 320, 384}},
{77, 655, 3, [4]int{132, 240, 360, 432}}, //15
{81, 733, 3, [4]int{144, 280, 408, 480}},
{85, 815, 3, [4]int{168, 308, 448, 532}},
{89, 901, 3, [4]int{180, 338, 504, 588}},
{93, 991, 3, [4]int{196, 364, 546, 650}},
{97, 1085, 3, [4]int{224, 416, 600, 700}}, //20
{101, 1156, 4, [4]int{224, 442, 644, 750}},
{105, 1258, 4, [4]int{252, 476, 690, 816}},
{109, 1364, 4, [4]int{270, 504, 750, 900}},
{113, 1474, 4, [4]int{300, 560, 810, 960}},
{117, 1588, 4, [4]int{312, 588, 870, 1050}}, //25
{121, 1706, 4, [4]int{336, 644, 952, 1110}},
{125, 1828, 4, [4]int{360, 700, 1020, 1200}},
{129, 1921, 3, [4]int{390, 728, 1050, 1260}},
{133, 2051, 3, [4]int{420, 784, 1140, 1350}},
{137, 2185, 3, [4]int{450, 812, 1200, 1440}}, //30
{141, 2323, 3, [4]int{480, 868, 1290, 1530}},
{145, 2465, 3, [4]int{510, 924, 1350, 1620}},
{149, 2611, 3, [4]int{540, 980, 1440, 1710}},
{153, 2761, 3, [4]int{570, 1036, 1530, 1800}},
{157, 2876, 0, [4]int{570, 1064, 1590, 1890}}, //35
{161, 3034, 0, [4]int{600, 1120, 1680, 1980}},
{165, 3196, 0, [4]int{630, 1204, 1770, 2100}},
{169, 3362, 0, [4]int{660, 1260, 1860, 2220}},
{173, 3532, 0, [4]int{720, 1316, 1950, 2310}},
{177, 3706, 0, [4]int{750, 1372, 2040, 2430}}, //40
}
var eccTable = [41][4][2]int{
{{0, 0}, {0, 0}, {0, 0}, {0, 0}},
{{1, 0}, {1, 0}, {1, 0}, {1, 0}}, // 1
{{1, 0}, {1, 0}, {1, 0}, {1, 0}},
{{1, 0}, {1, 0}, {2, 0}, {2, 0}},
{{1, 0}, {2, 0}, {2, 0}, {4, 0}},
{{1, 0}, {2, 0}, {2, 2}, {2, 2}}, // 5
{{2, 0}, {4, 0}, {4, 0}, {4, 0}},
{{2, 0}, {4, 0}, {2, 4}, {4, 1}},
{{2, 0}, {2, 2}, {4, 2}, {4, 2}},
{{2, 0}, {3, 2}, {4, 4}, {4, 4}},
{{2, 2}, {4, 1}, {6, 2}, {6, 2}}, //10
{{4, 0}, {1, 4}, {4, 4}, {3, 8}},
{{2, 2}, {6, 2}, {4, 6}, {7, 4}},
{{4, 0}, {8, 1}, {8, 4}, {12, 4}},
{{3, 1}, {4, 5}, {11, 5}, {11, 5}},
{{5, 1}, {5, 5}, {5, 7}, {11, 7}}, //15
{{5, 1}, {7, 3}, {15, 2}, {3, 13}},
{{1, 5}, {10, 1}, {1, 15}, {2, 17}},
{{5, 1}, {9, 4}, {17, 1}, {2, 19}},
{{3, 4}, {3, 11}, {17, 4}, {9, 16}},
{{3, 5}, {3, 13}, {15, 5}, {15, 10}}, //20
{{4, 4}, {17, 0}, {17, 6}, {19, 6}},
{{2, 7}, {17, 0}, {7, 16}, {34, 0}},
{{4, 5}, {4, 14}, {11, 14}, {16, 14}},
{{6, 4}, {6, 14}, {11, 16}, {30, 2}},
{{8, 4}, {8, 13}, {7, 22}, {22, 13}}, //25
{{10, 2}, {19, 4}, {28, 6}, {33, 4}},
{{8, 4}, {22, 3}, {8, 26}, {12, 28}},
{{3, 10}, {3, 23}, {4, 31}, {11, 31}},
{{7, 7}, {21, 7}, {1, 37}, {19, 26}},
{{5, 10}, {19, 10}, {15, 25}, {23, 25}}, //30
{{13, 3}, {2, 29}, {42, 1}, {23, 28}},
{{17, 0}, {10, 23}, {10, 35}, {19, 35}},
{{17, 1}, {14, 21}, {29, 19}, {11, 46}},
{{13, 6}, {14, 23}, {44, 7}, {59, 1}},
{{12, 7}, {12, 26}, {39, 14}, {22, 41}}, //35
{{6, 14}, {6, 34}, {46, 10}, {2, 64}},
{{17, 4}, {29, 14}, {49, 10}, {24, 46}},
{{4, 18}, {13, 32}, {48, 14}, {42, 32}},
{{20, 4}, {40, 7}, {43, 22}, {10, 67}},
{{19, 6}, {18, 31}, {34, 34}, {20, 61}}, //40
}
var align = [41][2]int{
{0, 0},
{0, 0}, {18, 0}, {22, 0}, {26, 0}, {30, 0}, // 1- 5
{34, 0}, {22, 38}, {24, 42}, {26, 46}, {28, 50}, // 6-10
{30, 54}, {32, 58}, {34, 62}, {26, 46}, {26, 48}, //11-15
{26, 50}, {30, 54}, {30, 56}, {30, 58}, {34, 62}, //16-20
{28, 50}, {26, 50}, {30, 54}, {28, 54}, {32, 58}, //21-25
{30, 58}, {34, 62}, {26, 50}, {30, 54}, {26, 52}, //26-30
{30, 56}, {34, 60}, {30, 58}, {34, 62}, {30, 54}, //31-35
{24, 50}, {28, 54}, {32, 58}, {26, 54}, {30, 58}, //35-40
}
var versionPattern = [41]int{
0,
0, 0, 0, 0, 0, 0,
0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
0x27541, 0x28c69,
}
func main() {
fmt.Printf("\t{},\n")
for i := 1; i <= 40; i++ {
apos := align[i][0] - 2
if apos < 0 {
apos = 100
}
astride := align[i][1] - align[i][0]
if astride < 1 {
astride = 100
}
fmt.Printf("\t{%v, %v, %v, %#x, [4]level{{%v, %v}, {%v, %v}, {%v, %v}, {%v, %v}}}, // %v\n",
apos, astride, capacity[i].words,
versionPattern[i],
eccTable[i][0][0]+eccTable[i][0][1],
float64(capacity[i].ec[0])/float64(eccTable[i][0][0]+eccTable[i][0][1]),
eccTable[i][1][0]+eccTable[i][1][1],
float64(capacity[i].ec[1])/float64(eccTable[i][1][0]+eccTable[i][1][1]),
eccTable[i][2][0]+eccTable[i][2][1],
float64(capacity[i].ec[2])/float64(eccTable[i][2][0]+eccTable[i][2][1]),
eccTable[i][3][0]+eccTable[i][3][1],
float64(capacity[i].ec[3])/float64(eccTable[i][3][0]+eccTable[i][3][1]),
i,
)
}
}

View File

@ -1,149 +0,0 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package libqrencode wraps the C libqrencode library.
// The qr package (in this package's parent directory)
// does not use any C wrapping. This code is here only
// for use during that package's tests.
package libqrencode
/*
#cgo LDFLAGS: -lqrencode
#include <qrencode.h>
*/
import "C"
import (
"fmt"
"image"
"image/color"
"unsafe"
)
type Version int
type Mode int
const (
Numeric Mode = C.QR_MODE_NUM
Alphanumeric Mode = C.QR_MODE_AN
EightBit Mode = C.QR_MODE_8
)
type Level int
const (
L Level = C.QR_ECLEVEL_L
M Level = C.QR_ECLEVEL_M
Q Level = C.QR_ECLEVEL_Q
H Level = C.QR_ECLEVEL_H
)
type Pixel int
const (
Black Pixel = 1 << iota
DataECC
Format
PVersion
Timing
Alignment
Finder
NonData
)
type Code struct {
Version int
Width int
Pixel [][]Pixel
Scale int
}
func (*Code) ColorModel() color.Model {
return color.RGBAModel
}
func (c *Code) Bounds() image.Rectangle {
d := (c.Width + 8) * c.Scale
return image.Rect(0, 0, d, d)
}
var (
white color.Color = color.RGBA{0xFF, 0xFF, 0xFF, 0xFF}
black color.Color = color.RGBA{0x00, 0x00, 0x00, 0xFF}
blue color.Color = color.RGBA{0x00, 0x00, 0x80, 0xFF}
red color.Color = color.RGBA{0xFF, 0x40, 0x40, 0xFF}
yellow color.Color = color.RGBA{0xFF, 0xFF, 0x00, 0xFF}
gray color.Color = color.RGBA{0x80, 0x80, 0x80, 0xFF}
green color.Color = color.RGBA{0x22, 0x8B, 0x22, 0xFF}
)
func (c *Code) At(x, y int) color.Color {
x = x/c.Scale - 4
y = y/c.Scale - 4
if 0 <= x && x < c.Width && 0 <= y && y < c.Width {
switch p := c.Pixel[y][x]; {
case p&Black == 0:
// nothing
case p&DataECC != 0:
return black
case p&Format != 0:
return blue
case p&PVersion != 0:
return red
case p&Timing != 0:
return yellow
case p&Alignment != 0:
return gray
case p&Finder != 0:
return green
}
}
return white
}
type Chunk struct {
Mode Mode
Text string
}
func Encode(version Version, level Level, mode Mode, text string) (*Code, error) {
return EncodeChunk(version, level, Chunk{mode, text})
}
func EncodeChunk(version Version, level Level, chunk ...Chunk) (*Code, error) {
qi, err := C.QRinput_new2(C.int(version), C.QRecLevel(level))
if qi == nil {
return nil, fmt.Errorf("QRinput_new2: %v", err)
}
defer C.QRinput_free(qi)
for _, ch := range chunk {
data := []byte(ch.Text)
n, err := C.QRinput_append(qi, C.QRencodeMode(ch.Mode), C.int(len(data)), (*C.uchar)(&data[0]))
if n < 0 {
return nil, fmt.Errorf("QRinput_append %q: %v", data, err)
}
}
qc, err := C.QRcode_encodeInput(qi)
if qc == nil {
return nil, fmt.Errorf("QRinput_encodeInput: %v", err)
}
c := &Code{
Version: int(qc.version),
Width: int(qc.width),
Scale: 16,
}
pix := make([]Pixel, c.Width*c.Width)
cdat := (*[1000 * 1000]byte)(unsafe.Pointer(qc.data))[:len(pix)]
for i := range pix {
pix[i] = Pixel(cdat[i])
}
c.Pixel = make([][]Pixel, c.Width)
for i := range c.Pixel {
c.Pixel[i] = pix[i*c.Width : (i+1)*c.Width]
}
return c, nil
}

View File

@ -1,505 +0,0 @@
package web
import (
"bytes"
"fmt"
"image"
"image/color"
"image/draw"
"image/png"
"net/http"
"strconv"
"strings"
"code.google.com/p/freetype-go/freetype"
"code.google.com/p/rsc/appfs/fs"
"code.google.com/p/rsc/qr"
"code.google.com/p/rsc/qr/coding"
)
func makeImage(req *http.Request, caption, font string, pt, size, border, scale int, f func(x, y int) uint32) *image.RGBA {
d := (size + 2*border) * scale
csize := 0
if caption != "" {
if pt == 0 {
pt = 11
}
csize = pt * 2
}
c := image.NewRGBA(image.Rect(0, 0, d, d+csize))
// white
u := &image.Uniform{C: color.White}
draw.Draw(c, c.Bounds(), u, image.ZP, draw.Src)
for y := 0; y < size; y++ {
for x := 0; x < size; x++ {
r := image.Rect((x+border)*scale, (y+border)*scale, (x+border+1)*scale, (y+border+1)*scale)
rgba := f(x, y)
u.C = color.RGBA{byte(rgba >> 24), byte(rgba >> 16), byte(rgba >> 8), byte(rgba)}
draw.Draw(c, r, u, image.ZP, draw.Src)
}
}
if csize != 0 {
if font == "" {
font = "data/luxisr.ttf"
}
ctxt := fs.NewContext(req)
dat, _, err := ctxt.Read(font)
if err != nil {
panic(err)
}
tfont, err := freetype.ParseFont(dat)
if err != nil {
panic(err)
}
ft := freetype.NewContext()
ft.SetDst(c)
ft.SetDPI(100)
ft.SetFont(tfont)
ft.SetFontSize(float64(pt))
ft.SetSrc(image.NewUniform(color.Black))
ft.SetClip(image.Rect(0, 0, 0, 0))
wid, err := ft.DrawString(caption, freetype.Pt(0, 0))
if err != nil {
panic(err)
}
p := freetype.Pt(d, d+3*pt/2)
p.X -= wid.X
p.X /= 2
ft.SetClip(c.Bounds())
ft.DrawString(caption, p)
}
return c
}
func makeFrame(req *http.Request, font string, pt, vers, l, scale, dots int) image.Image {
lev := coding.Level(l)
p, err := coding.NewPlan(coding.Version(vers), lev, 0)
if err != nil {
panic(err)
}
nd := p.DataBytes / p.Blocks
nc := p.CheckBytes / p.Blocks
extra := p.DataBytes - nd*p.Blocks
cap := fmt.Sprintf("QR v%d, %s", vers, lev)
if dots > 0 {
cap = fmt.Sprintf("QR v%d order, from bottom right", vers)
}
m := makeImage(req, cap, font, pt, len(p.Pixel), 0, scale, func(x, y int) uint32 {
pix := p.Pixel[y][x]
switch pix.Role() {
case coding.Data:
if dots > 0 {
return 0xffffffff
}
off := int(pix.Offset() / 8)
nd := nd
var i int
for i = 0; i < p.Blocks; i++ {
if i == extra {
nd++
}
if off < nd {
break
}
off -= nd
}
return blockColors[i%len(blockColors)]
case coding.Check:
if dots > 0 {
return 0xffffffff
}
i := (int(pix.Offset()/8) - p.DataBytes) / nc
return dark(blockColors[i%len(blockColors)])
}
if pix&coding.Black != 0 {
return 0x000000ff
}
return 0xffffffff
})
if dots > 0 {
b := m.Bounds()
for y := 0; y <= len(p.Pixel); y++ {
for x := 0; x < b.Dx(); x++ {
m.SetRGBA(x, y*scale-(y/len(p.Pixel)), color.RGBA{127, 127, 127, 255})
}
}
for x := 0; x <= len(p.Pixel); x++ {
for y := 0; y < b.Dx(); y++ {
m.SetRGBA(x*scale-(x/len(p.Pixel)), y, color.RGBA{127, 127, 127, 255})
}
}
order := make([]image.Point, (p.DataBytes+p.CheckBytes)*8+1)
for y, row := range p.Pixel {
for x, pix := range row {
if r := pix.Role(); r != coding.Data && r != coding.Check {
continue
}
// draw.Draw(m, m.Bounds().Add(image.Pt(x*scale, y*scale)), dot, image.ZP, draw.Over)
order[pix.Offset()] = image.Point{x*scale + scale/2, y*scale + scale/2}
}
}
for mode := 0; mode < 2; mode++ {
for i, p := range order {
q := order[i+1]
if q.X == 0 {
break
}
line(m, p, q, mode)
}
}
}
return m
}
func line(m *image.RGBA, p, q image.Point, mode int) {
x := 0
y := 0
dx := q.X - p.X
dy := q.Y - p.Y
xsign := +1
ysign := +1
if dx < 0 {
xsign = -1
dx = -dx
}
if dy < 0 {
ysign = -1
dy = -dy
}
pt := func() {
switch mode {
case 0:
for dx := -2; dx <= 2; dx++ {
for dy := -2; dy <= 2; dy++ {
if dy*dx <= -4 || dy*dx >= 4 {
continue
}
m.SetRGBA(p.X+x*xsign+dx, p.Y+y*ysign+dy, color.RGBA{255, 192, 192, 255})
}
}
case 1:
m.SetRGBA(p.X+x*xsign, p.Y+y*ysign, color.RGBA{128, 0, 0, 255})
}
}
if dx > dy {
for x < dx || y < dy {
pt()
x++
if float64(x)*float64(dy)/float64(dx)-float64(y) > 0.5 {
y++
}
}
} else {
for x < dx || y < dy {
pt()
y++
if float64(y)*float64(dx)/float64(dy)-float64(x) > 0.5 {
x++
}
}
}
pt()
}
func pngEncode(c image.Image) []byte {
var b bytes.Buffer
png.Encode(&b, c)
return b.Bytes()
}
// Frame handles a request for a single QR frame.
func Frame(w http.ResponseWriter, req *http.Request) {
arg := func(s string) int { x, _ := strconv.Atoi(req.FormValue(s)); return x }
v := arg("v")
scale := arg("scale")
if scale == 0 {
scale = 8
}
w.Header().Set("Cache-Control", "public, max-age=3600")
w.Write(pngEncode(makeFrame(req, req.FormValue("font"), arg("pt"), v, arg("l"), scale, arg("dots"))))
}
// Frames handles a request for multiple QR frames.
func Frames(w http.ResponseWriter, req *http.Request) {
vs := strings.Split(req.FormValue("v"), ",")
arg := func(s string) int { x, _ := strconv.Atoi(req.FormValue(s)); return x }
scale := arg("scale")
if scale == 0 {
scale = 8
}
font := req.FormValue("font")
pt := arg("pt")
dots := arg("dots")
var images []image.Image
l := arg("l")
for _, v := range vs {
l := l
if i := strings.Index(v, "."); i >= 0 {
l, _ = strconv.Atoi(v[i+1:])
v = v[:i]
}
vv, _ := strconv.Atoi(v)
images = append(images, makeFrame(req, font, pt, vv, l, scale, dots))
}
b := images[len(images)-1].Bounds()
dx := arg("dx")
if dx == 0 {
dx = b.Dx()
}
x, y := 0, 0
xmax := 0
sep := arg("sep")
if sep == 0 {
sep = 10
}
var points []image.Point
for i, m := range images {
if x > 0 {
x += sep
}
if x > 0 && x+m.Bounds().Dx() > dx {
y += sep + images[i-1].Bounds().Dy()
x = 0
}
points = append(points, image.Point{x, y})
x += m.Bounds().Dx()
if x > xmax {
xmax = x
}
}
c := image.NewRGBA(image.Rect(0, 0, xmax, y+b.Dy()))
for i, m := range images {
draw.Draw(c, c.Bounds().Add(points[i]), m, image.ZP, draw.Src)
}
w.Header().Set("Cache-Control", "public, max-age=3600")
w.Write(pngEncode(c))
}
// Mask handles a request for a single QR mask.
func Mask(w http.ResponseWriter, req *http.Request) {
arg := func(s string) int { x, _ := strconv.Atoi(req.FormValue(s)); return x }
v := arg("v")
m := arg("m")
scale := arg("scale")
if scale == 0 {
scale = 8
}
w.Header().Set("Cache-Control", "public, max-age=3600")
w.Write(pngEncode(makeMask(req, req.FormValue("font"), arg("pt"), v, m, scale)))
}
// Masks handles a request for multiple QR masks.
func Masks(w http.ResponseWriter, req *http.Request) {
arg := func(s string) int { x, _ := strconv.Atoi(req.FormValue(s)); return x }
v := arg("v")
scale := arg("scale")
if scale == 0 {
scale = 8
}
font := req.FormValue("font")
pt := arg("pt")
var mm []image.Image
for m := 0; m < 8; m++ {
mm = append(mm, makeMask(req, font, pt, v, m, scale))
}
dx := mm[0].Bounds().Dx()
dy := mm[0].Bounds().Dy()
sep := arg("sep")
if sep == 0 {
sep = 10
}
c := image.NewRGBA(image.Rect(0, 0, (dx+sep)*4-sep, (dy+sep)*2-sep))
for m := 0; m < 8; m++ {
x := (m % 4) * (dx + sep)
y := (m / 4) * (dy + sep)
draw.Draw(c, c.Bounds().Add(image.Pt(x, y)), mm[m], image.ZP, draw.Src)
}
w.Header().Set("Cache-Control", "public, max-age=3600")
w.Write(pngEncode(c))
}
var maskName = []string{
"(x+y) % 2",
"y % 2",
"x % 3",
"(x+y) % 3",
"(y/2 + x/3) % 2",
"xy%2 + xy%3",
"(xy%2 + xy%3) % 2",
"(xy%3 + (x+y)%2) % 2",
}
func makeMask(req *http.Request, font string, pt int, vers, mask, scale int) image.Image {
p, err := coding.NewPlan(coding.Version(vers), coding.L, coding.Mask(mask))
if err != nil {
panic(err)
}
m := makeImage(req, maskName[mask], font, pt, len(p.Pixel), 0, scale, func(x, y int) uint32 {
pix := p.Pixel[y][x]
switch pix.Role() {
case coding.Data, coding.Check:
if pix&coding.Invert != 0 {
return 0x000000ff
}
}
return 0xffffffff
})
return m
}
var blockColors = []uint32{
0x7777ffff,
0xffff77ff,
0xff7777ff,
0x77ffffff,
0x1e90ffff,
0xffffe0ff,
0x8b6969ff,
0x77ff77ff,
0x9b30ffff,
0x00bfffff,
0x90e890ff,
0xfff68fff,
0xffec8bff,
0xffa07aff,
0xffa54fff,
0xeee8aaff,
0x98fb98ff,
0xbfbfbfff,
0x54ff9fff,
0xffaeb9ff,
0xb23aeeff,
0xbbffffff,
0x7fffd4ff,
0xff7a7aff,
0x00007fff,
}
func dark(x uint32) uint32 {
r, g, b, a := byte(x>>24), byte(x>>16), byte(x>>8), byte(x)
r = r/2 + r/4
g = g/2 + g/4
b = b/2 + b/4
return uint32(r)<<24 | uint32(g)<<16 | uint32(b)<<8 | uint32(a)
}
func clamp(x int) byte {
if x < 0 {
return 0
}
if x > 255 {
return 255
}
return byte(x)
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
// Arrow handles a request for an arrow pointing in a given direction.
func Arrow(w http.ResponseWriter, req *http.Request) {
arg := func(s string) int { x, _ := strconv.Atoi(req.FormValue(s)); return x }
dir := arg("dir")
size := arg("size")
if size == 0 {
size = 50
}
del := size / 10
m := image.NewRGBA(image.Rect(0, 0, size, size))
if dir == 4 {
draw.Draw(m, m.Bounds(), image.Black, image.ZP, draw.Src)
draw.Draw(m, image.Rect(5, 5, size-5, size-5), image.White, image.ZP, draw.Src)
}
pt := func(x, y int, c color.RGBA) {
switch dir {
case 0:
m.SetRGBA(x, y, c)
case 1:
m.SetRGBA(y, size-1-x, c)
case 2:
m.SetRGBA(size-1-x, size-1-y, c)
case 3:
m.SetRGBA(size-1-y, x, c)
}
}
for y := 0; y < size/2; y++ {
for x := 0; x < del && x < y; x++ {
pt(x, y, color.RGBA{0, 0, 0, 255})
}
for x := del; x < y-del; x++ {
pt(x, y, color.RGBA{128, 128, 255, 255})
}
for x := max(y-del, 0); x <= y; x++ {
pt(x, y, color.RGBA{0, 0, 0, 255})
}
}
for y := size / 2; y < size; y++ {
for x := 0; x < del && x < size-1-y; x++ {
pt(x, y, color.RGBA{0, 0, 0, 255})
}
for x := del; x < size-1-y-del; x++ {
pt(x, y, color.RGBA{128, 128, 192, 255})
}
for x := max(size-1-y-del, 0); x <= size-1-y; x++ {
pt(x, y, color.RGBA{0, 0, 0, 255})
}
}
w.Header().Set("Cache-Control", "public, max-age=3600")
w.Write(pngEncode(m))
}
// Encode encodes a string using the given version, level, and mask.
func Encode(w http.ResponseWriter, req *http.Request) {
val := func(s string) int {
v, _ := strconv.Atoi(req.FormValue(s))
return v
}
l := coding.Level(val("l"))
v := coding.Version(val("v"))
enc := coding.String(req.FormValue("t"))
m := coding.Mask(val("m"))
p, err := coding.NewPlan(v, l, m)
if err != nil {
panic(err)
}
cc, err := p.Encode(enc)
if err != nil {
panic(err)
}
c := &qr.Code{Bitmap: cc.Bitmap, Size: cc.Size, Stride: cc.Stride, Scale: 8}
w.Header().Set("Content-Type", "image/png")
w.Header().Set("Cache-Control", "public, max-age=3600")
w.Write(c.PNG())
}

File diff suppressed because it is too large Load Diff

View File

@ -1,152 +0,0 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package resize
import (
"image"
"image/color"
)
// average convert the sums to averages and returns the result.
func average(sum []uint64, w, h int, n uint64) *image.RGBA {
ret := image.NewRGBA(image.Rect(0, 0, w, h))
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
index := 4 * (y*w + x)
pix := ret.Pix[y*ret.Stride+x*4:]
pix[0] = uint8(sum[index+0] / n)
pix[1] = uint8(sum[index+1] / n)
pix[2] = uint8(sum[index+2] / n)
pix[3] = uint8(sum[index+3] / n)
}
}
return ret
}
// ResizeRGBA returns a scaled copy of the RGBA image slice r of m.
// The returned image has width w and height h.
func ResizeRGBA(m *image.RGBA, r image.Rectangle, w, h int) *image.RGBA {
ww, hh := uint64(w), uint64(h)
dx, dy := uint64(r.Dx()), uint64(r.Dy())
// See comment in Resize.
n, sum := dx*dy, make([]uint64, 4*w*h)
for y := r.Min.Y; y < r.Max.Y; y++ {
pix := m.Pix[(y-r.Min.Y)*m.Stride:]
for x := r.Min.X; x < r.Max.X; x++ {
// Get the source pixel.
p := pix[(x-r.Min.X)*4:]
r64 := uint64(p[0])
g64 := uint64(p[1])
b64 := uint64(p[2])
a64 := uint64(p[3])
// Spread the source pixel over 1 or more destination rows.
py := uint64(y) * hh
for remy := hh; remy > 0; {
qy := dy - (py % dy)
if qy > remy {
qy = remy
}
// Spread the source pixel over 1 or more destination columns.
px := uint64(x) * ww
index := 4 * ((py/dy)*ww + (px / dx))
for remx := ww; remx > 0; {
qx := dx - (px % dx)
if qx > remx {
qx = remx
}
qxy := qx * qy
sum[index+0] += r64 * qxy
sum[index+1] += g64 * qxy
sum[index+2] += b64 * qxy
sum[index+3] += a64 * qxy
index += 4
px += qx
remx -= qx
}
py += qy
remy -= qy
}
}
}
return average(sum, w, h, n)
}
// ResizeNRGBA returns a scaled copy of the RGBA image slice r of m.
// The returned image has width w and height h.
func ResizeNRGBA(m *image.NRGBA, r image.Rectangle, w, h int) *image.RGBA {
ww, hh := uint64(w), uint64(h)
dx, dy := uint64(r.Dx()), uint64(r.Dy())
// See comment in Resize.
n, sum := dx*dy, make([]uint64, 4*w*h)
for y := r.Min.Y; y < r.Max.Y; y++ {
pix := m.Pix[(y-r.Min.Y)*m.Stride:]
for x := r.Min.X; x < r.Max.X; x++ {
// Get the source pixel.
p := pix[(x-r.Min.X)*4:]
r64 := uint64(p[0])
g64 := uint64(p[1])
b64 := uint64(p[2])
a64 := uint64(p[3])
r64 = (r64 * a64) / 255
g64 = (g64 * a64) / 255
b64 = (b64 * a64) / 255
// Spread the source pixel over 1 or more destination rows.
py := uint64(y) * hh
for remy := hh; remy > 0; {
qy := dy - (py % dy)
if qy > remy {
qy = remy
}
// Spread the source pixel over 1 or more destination columns.
px := uint64(x) * ww
index := 4 * ((py/dy)*ww + (px / dx))
for remx := ww; remx > 0; {
qx := dx - (px % dx)
if qx > remx {
qx = remx
}
qxy := qx * qy
sum[index+0] += r64 * qxy
sum[index+1] += g64 * qxy
sum[index+2] += b64 * qxy
sum[index+3] += a64 * qxy
index += 4
px += qx
remx -= qx
}
py += qy
remy -= qy
}
}
}
return average(sum, w, h, n)
}
// Resample returns a resampled copy of the image slice r of m.
// The returned image has width w and height h.
func Resample(m image.Image, r image.Rectangle, w, h int) *image.RGBA {
if w < 0 || h < 0 {
return nil
}
if w == 0 || h == 0 || r.Dx() <= 0 || r.Dy() <= 0 {
return image.NewRGBA(image.Rect(0, 0, w, h))
}
curw, curh := r.Dx(), r.Dy()
img := image.NewRGBA(image.Rect(0, 0, w, h))
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
// Get a source pixel.
subx := x * curw / w
suby := y * curh / h
r32, g32, b32, a32 := m.At(subx, suby).RGBA()
r := uint8(r32 >> 8)
g := uint8(g32 >> 8)
b := uint8(b32 >> 8)
a := uint8(a32 >> 8)
img.SetRGBA(x, y, color.RGBA{r, g, b, a})
}
}
return img
}

View File

@ -1,27 +0,0 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -32,9 +32,10 @@ This package implements the RFC 6238 OATH-TOTP algorithm;
### Storing Keys ### Storing Keys
> **The key crerated is using go crypto random function and it's a cryptographic secret key.** > **The key is created using Golang crypto random function. It's a secret key and therefore**
> It needs to be protected against unauthorized access and they cannot be leaked. > it needs to be protected against unauthorized access. The key cannot be leaked, otherwise the security is complitely compromised.
> In addition when the QR cide is shared with the client, the connection should be secured. > The key is presented to the user in a form of QR Code. Once scanned the key should be revealed again.
> In addition when the QR cide is shared with the client for scanning, the connection used must be secured.
The `totp` struct can be easily serialized using the `ToBytes()` function. The `totp` struct can be easily serialized using the `ToBytes()` function.
The bytes can then be stored on a persistent layer. The bytes are encrypted using `cryptoengine` library (NaCl) The bytes can then be stored on a persistent layer. The bytes are encrypted using `cryptoengine` library (NaCl)

View File

@ -1,101 +0,0 @@
package twofactor
import (
"encoding/binary"
"testing"
)
func TestRound(t *testing.T) {
// TODO: test negative numbers, although not used in our case
input := float64(3.7)
expected := uint64(4)
result := round(input)
if result != expected {
t.Fatalf("Expected %d - got %d\n", expected, result)
}
input = float64(3.5)
expected = uint64(4)
result = round(input)
if result != expected {
t.Fatalf("Expected %d - got %d\n", expected, result)
}
input = float64(3.499999999)
expected = uint64(3)
result = round(input)
if result != expected {
t.Fatalf("Expected %d - got %d\n", expected, result)
}
input = float64(3.0)
expected = uint64(3)
result = round(input)
if result != expected {
t.Fatalf("Expected %d - got %d\n", expected, result)
}
input = float64(3.9999)
expected = uint64(4)
result = round(input)
if result != expected {
t.Fatalf("Expected %d - got %d\n", expected, result)
}
}
func TestBigEndianUint64(t *testing.T) {
// convert ot bytes
input := uint64(2984983220)
inputBytes := bigEndianUint64(input)
// convert from bytes back
result := uint64FromBigEndian(inputBytes)
if result != input {
t.Fatal("Big endian conversion failed")
}
goResult := binary.BigEndian.Uint64(inputBytes[:])
if goResult != input {
t.Fatal("It's not a big endian representation")
}
input = uint64(18446744073709551615)
inputBytes = bigEndianUint64(input)
// convert from bytes back
result = uint64FromBigEndian(inputBytes)
if result != input {
t.Fatal("Big endian conversion failed")
}
goResult = binary.BigEndian.Uint64(inputBytes[:])
if goResult != input {
t.Fatal("It's not a big endian representation")
}
}
func TestBigEndianInt(t *testing.T) {
// convert ot bytes
input := int(2984983220)
inputBytes := bigEndianInt(input)
// convert from bytes back
result := intFromBigEndian(inputBytes)
if result != input {
t.Fatal("Big endian conversion failed")
}
goResult := binary.BigEndian.Uint32(inputBytes[:])
if int(goResult) != input {
t.Fatal("It's not a big endian representation")
}
}

74
totp.go
View File

@ -12,11 +12,13 @@ import (
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt" "fmt"
"github.com/sec51/convert/smallendian" "github.com/sec51/convert"
"github.com/sec51/convert/bigendian"
"github.com/sec51/cryptoengine" "github.com/sec51/cryptoengine"
qr "github.com/sec51/qrcode" qr "github.com/sec51/qrcode"
"hash" "hash"
"io" "io"
"math"
"net/url" "net/url"
"strconv" "strconv"
"time" "time"
@ -64,7 +66,7 @@ func (otp *Totp) label() string {
// Counter returns the TOTP's 8-byte counter as unsigned 64-bit integer. // Counter returns the TOTP's 8-byte counter as unsigned 64-bit integer.
func (otp *Totp) getIntCounter() uint64 { func (otp *Totp) getIntCounter() uint64 {
return smallendian.FromUint64(otp.counter) return bigendian.FromUint64(otp.counter)
} }
// This function creates a new TOTP object // This function creates a new TOTP object
@ -149,6 +151,7 @@ func (otp *Totp) Validate(userCode string) error {
token0Hash := sha256.Sum256([]byte(calculateTOTP(otp, -1))) token0Hash := sha256.Sum256([]byte(calculateTOTP(otp, -1)))
token1Hash := sha256.Sum256([]byte(calculateTOTP(otp, 0))) token1Hash := sha256.Sum256([]byte(calculateTOTP(otp, 0)))
token2Hash := sha256.Sum256([]byte(calculateTOTP(otp, 1))) token2Hash := sha256.Sum256([]byte(calculateTOTP(otp, 1)))
tokens[0] = hex.EncodeToString(token0Hash[:]) // 30 seconds ago token tokens[0] = hex.EncodeToString(token0Hash[:]) // 30 seconds ago token
tokens[1] = hex.EncodeToString(token1Hash[:]) // current token tokens[1] = hex.EncodeToString(token1Hash[:]) // current token
tokens[2] = hex.EncodeToString(token2Hash[:]) // next 30 seconds token tokens[2] = hex.EncodeToString(token2Hash[:]) // next 30 seconds token
@ -196,13 +199,13 @@ func (otp *Totp) incrementCounter(index int) {
// Unix returns t as a Unix time, the number of seconds elapsed since January 1, 1970 UTC. // Unix returns t as a Unix time, the number of seconds elapsed since January 1, 1970 UTC.
counterOffset := time.Duration(index*otp.stepSize) * time.Second counterOffset := time.Duration(index*otp.stepSize) * time.Second
now := time.Now().UTC().Add(counterOffset).Unix() now := time.Now().UTC().Add(counterOffset).Unix()
otp.counter = smallendian.ToUint64(increment(now, otp.stepSize)) otp.counter = bigendian.ToUint64(increment(now, otp.stepSize))
} }
// Function which calculates the value of T (see rfc6238) // Function which calculates the value of T (see rfc6238)
func increment(ts int64, stepSize int) uint64 { func increment(ts int64, stepSize int) uint64 {
T := float64(ts / int64(stepSize)) // TODO: improve this conversions T := float64(ts / int64(stepSize)) // TODO: improve this conversions
n := round(T) // round T n := convert.Round(T) // round T
return n // convert n to little endian byte array return n // convert n to little endian byte array
} }
@ -236,7 +239,7 @@ func calculateTOTP(otp *Totp, index int) string {
} }
// set the counter to the current step based ont he current time // set the counter to the current step based ont the current time
// this is necessary to generate the proper OTP // this is necessary to generate the proper OTP
otp.incrementCounter(index) otp.incrementCounter(index)
@ -259,20 +262,11 @@ func calculateToken(counter []byte, digits int, h hash.Hash) string {
h.Write(counter) h.Write(counter)
hashResult := h.Sum(nil) hashResult := h.Sum(nil)
result := truncateHash(hashResult, h.Size()) result := truncateHash(hashResult, h.Size())
var mod uint64
if digits == 8 {
mod = uint64(result % 100000000)
}
if digits == 7 { mod := int32(result % int64(math.Pow10(digits)))
mod = uint64(result % 10000000)
}
if digits == 6 {
mod = uint64(result % 1000000)
}
fmtStr := fmt.Sprintf("%%0%dd", digits) fmtStr := fmt.Sprintf("%%0%dd", digits)
return fmt.Sprintf(fmtStr, mod) return fmt.Sprintf(fmtStr, mod)
} }
@ -351,18 +345,18 @@ func (otp *Totp) ToBytes() ([]byte, error) {
// caluclate the length of the key and create its byte representation // caluclate the length of the key and create its byte representation
keySize := len(otp.key) keySize := len(otp.key)
keySizeBytes := smallendian.ToInt(keySize) //bigEndianInt(keySize) keySizeBytes := bigendian.ToInt(keySize) //bigEndianInt(keySize)
// caluclate the length of the issuer and create its byte representation // caluclate the length of the issuer and create its byte representation
issuerSize := len(otp.issuer) issuerSize := len(otp.issuer)
issuerSizeBytes := smallendian.ToInt(issuerSize) issuerSizeBytes := bigendian.ToInt(issuerSize)
// caluclate the length of the account and create its byte representation // caluclate the length of the account and create its byte representation
accountSize := len(otp.account) accountSize := len(otp.account)
accountSizeBytes := smallendian.ToInt(accountSize) accountSizeBytes := bigendian.ToInt(accountSize)
totalSize := 4 + 4 + keySize + 8 + 4 + 4 + issuerSize + 4 + accountSize + 4 + 4 + 4 + 8 + 4 totalSize := 4 + 4 + keySize + 8 + 4 + 4 + issuerSize + 4 + accountSize + 4 + 4 + 4 + 8 + 4
totalSizeBytes := smallendian.ToInt(totalSize) totalSizeBytes := bigendian.ToInt(totalSize)
// at this point we are ready to write the data to the byte buffer // at this point we are ready to write the data to the byte buffer
// total size // total size
@ -379,13 +373,13 @@ func (otp *Totp) ToBytes() ([]byte, error) {
} }
// counter // counter
counterBytes := smallendian.ToUint64(otp.getIntCounter()) counterBytes := bigendian.ToUint64(otp.getIntCounter())
if _, err := buffer.Write(counterBytes[:]); err != nil { if _, err := buffer.Write(counterBytes[:]); err != nil {
return nil, err return nil, err
} }
// digits // digits
digitBytes := smallendian.ToInt(otp.digits) digitBytes := bigendian.ToInt(otp.digits)
if _, err := buffer.Write(digitBytes[:]); err != nil { if _, err := buffer.Write(digitBytes[:]); err != nil {
return nil, err return nil, err
} }
@ -407,25 +401,25 @@ func (otp *Totp) ToBytes() ([]byte, error) {
} }
// steps // steps
stepsBytes := smallendian.ToInt(otp.stepSize) stepsBytes := bigendian.ToInt(otp.stepSize)
if _, err := buffer.Write(stepsBytes[:]); err != nil { if _, err := buffer.Write(stepsBytes[:]); err != nil {
return nil, err return nil, err
} }
// offset // offset
offsetBytes := smallendian.ToInt(otp.clientOffset) offsetBytes := bigendian.ToInt(otp.clientOffset)
if _, err := buffer.Write(offsetBytes[:]); err != nil { if _, err := buffer.Write(offsetBytes[:]); err != nil {
return nil, err return nil, err
} }
// total_failures // total_failures
totalFailuresBytes := smallendian.ToInt(otp.totalVerificationFailures) totalFailuresBytes := bigendian.ToInt(otp.totalVerificationFailures)
if _, err := buffer.Write(totalFailuresBytes[:]); err != nil { if _, err := buffer.Write(totalFailuresBytes[:]); err != nil {
return nil, err return nil, err
} }
// last verification time // last verification time
verificationTimeBytes := smallendian.ToUint64(uint64(otp.lastVerificationTime.Unix())) verificationTimeBytes := bigendian.ToUint64(uint64(otp.lastVerificationTime.Unix()))
if _, err := buffer.Write(verificationTimeBytes[:]); err != nil { if _, err := buffer.Write(verificationTimeBytes[:]); err != nil {
return nil, err return nil, err
} }
@ -433,19 +427,19 @@ func (otp *Totp) ToBytes() ([]byte, error) {
// has_function_type // has_function_type
switch otp.hashFunction { switch otp.hashFunction {
case crypto.SHA256: case crypto.SHA256:
sha256Bytes := smallendian.ToInt(1) sha256Bytes := bigendian.ToInt(1)
if _, err := buffer.Write(sha256Bytes[:]); err != nil { if _, err := buffer.Write(sha256Bytes[:]); err != nil {
return nil, err return nil, err
} }
break break
case crypto.SHA512: case crypto.SHA512:
sha512Bytes := smallendian.ToInt(2) sha512Bytes := bigendian.ToInt(2)
if _, err := buffer.Write(sha512Bytes[:]); err != nil { if _, err := buffer.Write(sha512Bytes[:]); err != nil {
return nil, err return nil, err
} }
break break
default: default:
sha1Bytes := smallendian.ToInt(0) sha1Bytes := bigendian.ToInt(0)
if _, err := buffer.Write(sha1Bytes[:]); err != nil { if _, err := buffer.Write(sha1Bytes[:]); err != nil {
return nil, err return nil, err
} }
@ -503,7 +497,7 @@ func TOTPFromBytes(encryptedMessage []byte, issuer string) (*Totp, error) {
return otp, err return otp, err
} }
totalSize := smallendian.FromInt([4]byte{lenght[0], lenght[1], lenght[2], lenght[3]}) totalSize := bigendian.FromInt([4]byte{lenght[0], lenght[1], lenght[2], lenght[3]})
buffer := make([]byte, totalSize-4) buffer := make([]byte, totalSize-4)
_, err = reader.Read(buffer) _, err = reader.Read(buffer)
if err != nil && err != io.EOF { if err != nil && err != io.EOF {
@ -515,7 +509,7 @@ func TOTPFromBytes(encryptedMessage []byte, issuer string) (*Totp, error) {
// read key size // read key size
endOffset := startOffset + 4 endOffset := startOffset + 4
keyBytes := buffer[startOffset:endOffset] keyBytes := buffer[startOffset:endOffset]
keySize := smallendian.FromInt([4]byte{keyBytes[0], keyBytes[1], keyBytes[2], keyBytes[3]}) keySize := bigendian.FromInt([4]byte{keyBytes[0], keyBytes[1], keyBytes[2], keyBytes[3]})
// read the key // read the key
startOffset = endOffset startOffset = endOffset
@ -532,13 +526,13 @@ func TOTPFromBytes(encryptedMessage []byte, issuer string) (*Totp, error) {
startOffset = endOffset startOffset = endOffset
endOffset = startOffset + 4 endOffset = startOffset + 4
b = buffer[startOffset:endOffset] b = buffer[startOffset:endOffset]
otp.digits = smallendian.FromInt([4]byte{b[0], b[1], b[2], b[3]}) // otp.digits = bigendian.FromInt([4]byte{b[0], b[1], b[2], b[3]}) //
// read the issuer size // read the issuer size
startOffset = endOffset startOffset = endOffset
endOffset = startOffset + 4 endOffset = startOffset + 4
b = buffer[startOffset:endOffset] b = buffer[startOffset:endOffset]
issuerSize := smallendian.FromInt([4]byte{b[0], b[1], b[2], b[3]}) issuerSize := bigendian.FromInt([4]byte{b[0], b[1], b[2], b[3]})
// read the issuer string // read the issuer string
startOffset = endOffset startOffset = endOffset
@ -549,7 +543,7 @@ func TOTPFromBytes(encryptedMessage []byte, issuer string) (*Totp, error) {
startOffset = endOffset startOffset = endOffset
endOffset = startOffset + 4 endOffset = startOffset + 4
b = buffer[startOffset:endOffset] b = buffer[startOffset:endOffset]
accountSize := smallendian.FromInt([4]byte{b[0], b[1], b[2], b[3]}) accountSize := bigendian.FromInt([4]byte{b[0], b[1], b[2], b[3]})
// read the account string // read the account string
startOffset = endOffset startOffset = endOffset
@ -560,32 +554,32 @@ func TOTPFromBytes(encryptedMessage []byte, issuer string) (*Totp, error) {
startOffset = endOffset startOffset = endOffset
endOffset = startOffset + 4 endOffset = startOffset + 4
b = buffer[startOffset:endOffset] b = buffer[startOffset:endOffset]
otp.stepSize = smallendian.FromInt([4]byte{b[0], b[1], b[2], b[3]}) otp.stepSize = bigendian.FromInt([4]byte{b[0], b[1], b[2], b[3]})
// read the offset // read the offset
startOffset = endOffset startOffset = endOffset
endOffset = startOffset + 4 endOffset = startOffset + 4
b = buffer[startOffset:endOffset] b = buffer[startOffset:endOffset]
otp.clientOffset = smallendian.FromInt([4]byte{b[0], b[1], b[2], b[3]}) otp.clientOffset = bigendian.FromInt([4]byte{b[0], b[1], b[2], b[3]})
// read the total failuers // read the total failuers
startOffset = endOffset startOffset = endOffset
endOffset = startOffset + 4 endOffset = startOffset + 4
b = buffer[startOffset:endOffset] b = buffer[startOffset:endOffset]
otp.totalVerificationFailures = smallendian.FromInt([4]byte{b[0], b[1], b[2], b[3]}) otp.totalVerificationFailures = bigendian.FromInt([4]byte{b[0], b[1], b[2], b[3]})
// read the offset // read the offset
startOffset = endOffset startOffset = endOffset
endOffset = startOffset + 8 endOffset = startOffset + 8
b = buffer[startOffset:endOffset] b = buffer[startOffset:endOffset]
ts := smallendian.FromUint64([8]byte{b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]}) ts := bigendian.FromUint64([8]byte{b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]})
otp.lastVerificationTime = time.Unix(int64(ts), 0) otp.lastVerificationTime = time.Unix(int64(ts), 0)
// read the hash type // read the hash type
startOffset = endOffset startOffset = endOffset
endOffset = startOffset + 4 endOffset = startOffset + 4
b = buffer[startOffset:endOffset] b = buffer[startOffset:endOffset]
hashType := smallendian.FromInt([4]byte{b[0], b[1], b[2], b[3]}) hashType := bigendian.FromInt([4]byte{b[0], b[1], b[2], b[3]})
switch hashType { switch hashType {
case 1: case 1:
@ -603,7 +597,7 @@ func TOTPFromBytes(encryptedMessage []byte, issuer string) (*Totp, error) {
// this method checks the proper initialization of the Totp object // this method checks the proper initialization of the Totp object
func totpHasBeenInitialized(otp *Totp) error { func totpHasBeenInitialized(otp *Totp) error {
if otp.key == nil || len(otp.key) == 0 { if otp == nil || otp.key == nil || len(otp.key) == 0 {
return initializationFailedError return initializationFailedError
} }
return nil return nil

View File

@ -9,6 +9,7 @@ import (
"crypto/sha512" "crypto/sha512"
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"github.com/sec51/convert/bigendian"
"net/url" "net/url"
"testing" "testing"
"time" "time"
@ -81,7 +82,7 @@ func TestTOTP(t *testing.T) {
otp.key = keySha1 otp.key = keySha1
for index, ts := range timeCounters { for index, ts := range timeCounters {
counter := increment(ts, 30) counter := increment(ts, 30)
otp.counter = bigEndianUint64(counter) otp.counter = bigendian.ToUint64(counter)
hash := hmac.New(sha1.New, otp.key) hash := hmac.New(sha1.New, otp.key)
token := calculateToken(otp.counter[:], otp.digits, hash) token := calculateToken(otp.counter[:], otp.digits, hash)
expected := sha1TestData[index] expected := sha1TestData[index]
@ -94,7 +95,7 @@ func TestTOTP(t *testing.T) {
otp.key = keySha256 otp.key = keySha256
for index, ts := range timeCounters { for index, ts := range timeCounters {
counter := increment(ts, 30) counter := increment(ts, 30)
otp.counter = bigEndianUint64(counter) otp.counter = bigendian.ToUint64(counter)
hash := hmac.New(sha256.New, otp.key) hash := hmac.New(sha256.New, otp.key)
token := calculateToken(otp.counter[:], otp.digits, hash) token := calculateToken(otp.counter[:], otp.digits, hash)
expected := sha256TestData[index] expected := sha256TestData[index]
@ -107,7 +108,7 @@ func TestTOTP(t *testing.T) {
otp.key = keySha512 otp.key = keySha512
for index, ts := range timeCounters { for index, ts := range timeCounters {
counter := increment(ts, 30) counter := increment(ts, 30)
otp.counter = bigEndianUint64(counter) otp.counter = bigendian.ToUint64(counter)
hash := hmac.New(sha512.New, otp.key) hash := hmac.New(sha512.New, otp.key)
token := calculateToken(otp.counter[:], otp.digits, hash) token := calculateToken(otp.counter[:], otp.digits, hash)
expected := sha512TestData[index] expected := sha512TestData[index]
@ -171,6 +172,11 @@ func TestVerificationFailures(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
// maje sure the fields are the same after parsing the token from bytes
if otp.label() != restoredOtp.label() {
t.Error("Label mismatch between in memory OTP and byte parsed OTP")
}
// test the validBackoffTime function // test the validBackoffTime function
if validBackoffTime(restoredOtp.lastVerificationTime) { if validBackoffTime(restoredOtp.lastVerificationTime) {
t.Error("validBackoffTime should return false") t.Error("validBackoffTime should return false")

7
vendor/github.com/sec51/convert/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,7 @@
language: go
go:
- 1.4
script:
- go test -v ./...

9
vendor/github.com/sec51/convert/README.md generated vendored Normal file
View File

@ -0,0 +1,9 @@
### Build status
[![Build Status](https://travis-ci.org/sec51/convert.svg?branch=master)](https://travis-ci.org/sec51/convert)
[![GoDoc](https://godoc.org/github.com/golang/gddo?status.svg)](https://godoc.org/github.com/sec51/convert/)
### Golang conversion library
This library converts, at the moment ints to big endian bytes
It is used in both `twofactor` and `cryptoengine` libraries

View File

@ -1,19 +1,7 @@
package twofactor package bigendian
import (
"math"
)
// Helper function which rounds the float to the nearest integet
func round(n float64) uint64 {
if n < 0 {
return uint64(math.Ceil(n - 0.5))
}
return uint64(math.Floor(n + 0.5))
}
// helper function which converts a uint64 to a []byte in Big Endian // helper function which converts a uint64 to a []byte in Big Endian
func bigEndianUint64(n uint64) [8]byte { func ToUint64(n uint64) [8]byte {
data := [8]byte{} data := [8]byte{}
data[0] = byte((n >> 56) & 0xFF) data[0] = byte((n >> 56) & 0xFF)
data[1] = byte((n >> 48) & 0xFF) data[1] = byte((n >> 48) & 0xFF)
@ -27,7 +15,7 @@ func bigEndianUint64(n uint64) [8]byte {
} }
// helper function which converts a big endian []byte to a uint64 // helper function which converts a big endian []byte to a uint64
func uint64FromBigEndian(data [8]byte) uint64 { func FromUint64(data [8]byte) uint64 {
i := (uint64(data[7]) << 0) | (uint64(data[6]) << 8) | i := (uint64(data[7]) << 0) | (uint64(data[6]) << 8) |
(uint64(data[5]) << 16) | (uint64(data[4]) << 24) | (uint64(data[5]) << 16) | (uint64(data[4]) << 24) |
(uint64(data[3]) << 32) | (uint64(data[2]) << 40) | (uint64(data[3]) << 32) | (uint64(data[2]) << 40) |
@ -35,7 +23,8 @@ func uint64FromBigEndian(data [8]byte) uint64 {
return uint64(i) return uint64(i)
} }
func bigEndianInt(n int) [4]byte { // helper function which converts a int to a []byte in Big Endian
func ToInt(n int) [4]byte {
data := [4]byte{} data := [4]byte{}
data[0] = byte((n >> 24) & 0xFF) data[0] = byte((n >> 24) & 0xFF)
data[1] = byte((n >> 16) & 0xFF) data[1] = byte((n >> 16) & 0xFF)
@ -44,7 +33,8 @@ func bigEndianInt(n int) [4]byte {
return data return data
} }
func intFromBigEndian(data [4]byte) int { // helper function which converts a big endian []byte to a int
func FromInt(data [4]byte) int {
i := (int(data[3]) << 0) | (int(data[2]) << 8) | i := (int(data[3]) << 0) | (int(data[2]) << 8) |
(int(data[1]) << 16) | (int(data[0]) << 24) (int(data[1]) << 16) | (int(data[0]) << 24)
return int(i) return int(i)

2
vendor/github.com/sec51/convert/bigendian/doc.go generated vendored Normal file
View File

@ -0,0 +1,2 @@
// Package used to convert intergers to byte arrays in big endian
package bigendian

13
vendor/github.com/sec51/convert/common.go generated vendored Normal file
View File

@ -0,0 +1,13 @@
package convert
import (
"math"
)
// Helper function which rounds the float to the nearest integet
func Round(n float64) uint64 {
if n < 0 {
return uint64(math.Ceil(n - 0.5))
}
return uint64(math.Floor(n + 0.5))
}

2
vendor/github.com/sec51/convert/doc.go generated vendored Normal file
View File

@ -0,0 +1,2 @@
// Package used to round float to the nearest integet
package convert

View File

@ -8,6 +8,7 @@ sudo: required
install: install:
- go get "golang.org/x/crypto/nacl/box" - go get "golang.org/x/crypto/nacl/box"
- go get "golang.org/x/crypto/nacl/secretbox" - go get "golang.org/x/crypto/nacl/secretbox"
- go get "golang.org/x/crypto/hkdf"
- go get "github.com/sec51/convert" - go get "github.com/sec51/convert"
script: script:

7
vendor/github.com/sec51/gf256/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,7 @@
language: go
go:
- 1.5.3
script:
- go test -v ./...

3
vendor/github.com/sec51/gf256/README.md generated vendored Normal file
View File

@ -0,0 +1,3 @@
[![Build Status](https://travis-ci.org/sec51/gf256.svg?branch=master)](https://travis-ci.org/sec51/gf256)
# gf256

1
vendor/github.com/sec51/qrcode/.gitignore generated vendored Normal file
View File

@ -0,0 +1 @@
x.png

10
vendor/github.com/sec51/qrcode/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,10 @@
language: go
go:
- 1.5.3
install:
- go get "github.com/sec51/gf256"
script:
- go test -v

5
vendor/github.com/sec51/qrcode/README.md generated vendored Normal file
View File

@ -0,0 +1,5 @@
[![Build Status](https://travis-ci.org/sec51/qrcode.svg?branch=master)](https://travis-ci.org/sec51/qrcode)
### Fork of rsc qr codebase
This is a fork due to the dismissal of google code.

View File

@ -10,7 +10,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"code.google.com/p/rsc/gf256" "github.com/sec51/gf256"
) )
// Field is the field for QR error correction. // Field is the field for QR error correction.

View File

@ -12,7 +12,7 @@ import (
"image" "image"
"image/color" "image/color"
"code.google.com/p/rsc/qr/coding" "github.com/sec51/qrcode/coding"
) )
// A Level denotes a QR error correction level. // A Level denotes a QR error correction level.