mirror of
https://github.com/1f349/twofactor.git
synced 2024-12-22 07:24:12 +00:00
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:
parent
eada29e8a3
commit
72a472700b
@ -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
27
Godeps/Godeps.json
generated
@ -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
2
Godeps/_workspace/.gitignore
generated
vendored
@ -1,2 +0,0 @@
|
|||||||
/pkg
|
|
||||||
/bin
|
|
815
Godeps/_workspace/src/code.google.com/p/rsc/qr/coding/qr.go
generated
vendored
815
Godeps/_workspace/src/code.google.com/p/rsc/qr/coding/qr.go
generated
vendored
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
34
Godeps/_workspace/src/github.com/sec51/cryptoengine/Godeps/Godeps.json
generated
vendored
34
Godeps/_workspace/src/github.com/sec51/cryptoengine/Godeps/Godeps.json
generated
vendored
@ -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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
5
Godeps/_workspace/src/github.com/sec51/cryptoengine/Godeps/Readme
generated
vendored
5
Godeps/_workspace/src/github.com/sec51/cryptoengine/Godeps/Readme
generated
vendored
@ -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.
|
|
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/.DS_Store
generated
vendored
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/.DS_Store
generated
vendored
Binary file not shown.
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/examples/0
generated
vendored
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/examples/0
generated
vendored
Binary file not shown.
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/examples/1
generated
vendored
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/examples/1
generated
vendored
Binary file not shown.
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/examples/2
generated
vendored
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/examples/2
generated
vendored
Binary file not shown.
Binary file not shown.
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/examples/3
generated
vendored
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/examples/3
generated
vendored
Binary file not shown.
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/examples/4
generated
vendored
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/examples/4
generated
vendored
Binary file not shown.
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/examples/5
generated
vendored
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/examples/5
generated
vendored
Binary file not shown.
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/messagefrombytes/corpus/0
generated
vendored
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/messagefrombytes/corpus/0
generated
vendored
Binary file not shown.
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/messagefrombytes/corpus/1
generated
vendored
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/messagefrombytes/corpus/1
generated
vendored
Binary file not shown.
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/messagefrombytes/corpus/2
generated
vendored
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/messagefrombytes/corpus/2
generated
vendored
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@
|
|||||||
trailing backslash at end of expressi
|
|
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/messagefrombytes/corpus/3
generated
vendored
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/messagefrombytes/corpus/3
generated
vendored
Binary file not shown.
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/messagefrombytes/corpus/4
generated
vendored
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/messagefrombytes/corpus/4
generated
vendored
Binary file not shown.
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/messagefrombytes/corpus/5
generated
vendored
BIN
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/messagefrombytes/corpus/5
generated
vendored
Binary file not shown.
21
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/messagefrombytes/main.go
generated
vendored
21
Godeps/_workspace/src/github.com/sec51/cryptoengine/fuzzing/messagefrombytes/main.go
generated
vendored
@ -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
|
|
||||||
// }
|
|
27
Godeps/_workspace/src/github.com/sec51/rsc/LICENSE
generated
vendored
27
Godeps/_workspace/src/github.com/sec51/rsc/LICENSE
generated
vendored
@ -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.
|
|
149
Godeps/_workspace/src/github.com/sec51/rsc/qr/coding/gen.go
generated
vendored
149
Godeps/_workspace/src/github.com/sec51/rsc/qr/coding/gen.go
generated
vendored
@ -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,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
149
Godeps/_workspace/src/github.com/sec51/rsc/qr/libqrencode/qrencode.go
generated
vendored
149
Godeps/_workspace/src/github.com/sec51/rsc/qr/libqrencode/qrencode.go
generated
vendored
@ -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
|
|
||||||
}
|
|
505
Godeps/_workspace/src/github.com/sec51/rsc/qr/web/pic.go
generated
vendored
505
Godeps/_workspace/src/github.com/sec51/rsc/qr/web/pic.go
generated
vendored
@ -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())
|
|
||||||
}
|
|
1118
Godeps/_workspace/src/github.com/sec51/rsc/qr/web/play.go
generated
vendored
1118
Godeps/_workspace/src/github.com/sec51/rsc/qr/web/play.go
generated
vendored
File diff suppressed because it is too large
Load Diff
152
Godeps/_workspace/src/github.com/sec51/rsc/qr/web/resize/resize.go
generated
vendored
152
Godeps/_workspace/src/github.com/sec51/rsc/qr/web/resize/resize.go
generated
vendored
@ -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
|
|
||||||
}
|
|
27
Godeps/_workspace/src/golang.org/x/crypto/LICENSE
generated
vendored
27
Godeps/_workspace/src/golang.org/x/crypto/LICENSE
generated
vendored
@ -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.
|
|
@ -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)
|
||||||
|
@ -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
74
totp.go
@ -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
|
||||||
|
12
totp_test.go
12
totp_test.go
@ -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
7
vendor/github.com/sec51/convert/.travis.yml
generated
vendored
Normal 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
9
vendor/github.com/sec51/convert/README.md
generated
vendored
Normal 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
|
24
conversions.go → vendor/github.com/sec51/convert/bigendian/convert.go
generated
vendored
24
conversions.go → vendor/github.com/sec51/convert/bigendian/convert.go
generated
vendored
@ -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
2
vendor/github.com/sec51/convert/bigendian/doc.go
generated
vendored
Normal 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
13
vendor/github.com/sec51/convert/common.go
generated
vendored
Normal 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
2
vendor/github.com/sec51/convert/doc.go
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Package used to round float to the nearest integet
|
||||||
|
package convert
|
@ -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
7
vendor/github.com/sec51/gf256/.travis.yml
generated
vendored
Normal 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
3
vendor/github.com/sec51/gf256/README.md
generated
vendored
Normal 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
1
vendor/github.com/sec51/qrcode/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
x.png
|
10
vendor/github.com/sec51/qrcode/.travis.yml
generated
vendored
Normal file
10
vendor/github.com/sec51/qrcode/.travis.yml
generated
vendored
Normal 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
5
vendor/github.com/sec51/qrcode/README.md
generated
vendored
Normal 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.
|
@ -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.
|
@ -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.
|
Loading…
Reference in New Issue
Block a user