forked from forgejo/forgejo
Switch to keybase go-crypto (for some elliptic curve key) + test (#1925)
* Switch to keybase go-crypto (for some elliptic curve key) + test
* Use assert.NoError
and add a little more context to failing test description
* Use assert.(No)Error everywhere 🌈
and assert.Error in place of .Nil/.NotNil
This commit is contained in:
parent
5e92b82ac6
commit
274149dd14
56 changed files with 10621 additions and 925 deletions
237
vendor/github.com/keybase/go-crypto/openpgp/armor/armor.go
generated
vendored
Normal file
237
vendor/github.com/keybase/go-crypto/openpgp/armor/armor.go
generated
vendored
Normal file
|
@ -0,0 +1,237 @@
|
|||
// Copyright 2010 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 armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
|
||||
// very similar to PEM except that it has an additional CRC checksum.
|
||||
package armor // import "github.com/keybase/go-crypto/openpgp/armor"
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/keybase/go-crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
// A Block represents an OpenPGP armored structure.
|
||||
//
|
||||
// The encoded form is:
|
||||
// -----BEGIN Type-----
|
||||
// Headers
|
||||
//
|
||||
// base64-encoded Bytes
|
||||
// '=' base64 encoded checksum
|
||||
// -----END Type-----
|
||||
// where Headers is a possibly empty sequence of Key: Value lines.
|
||||
//
|
||||
// Since the armored data can be very large, this package presents a streaming
|
||||
// interface.
|
||||
type Block struct {
|
||||
Type string // The type, taken from the preamble (i.e. "PGP SIGNATURE").
|
||||
Header map[string]string // Optional headers.
|
||||
Body io.Reader // A Reader from which the contents can be read
|
||||
lReader lineReader
|
||||
oReader openpgpReader
|
||||
}
|
||||
|
||||
var ArmorCorrupt error = errors.StructuralError("armor invalid")
|
||||
|
||||
const crc24Init = 0xb704ce
|
||||
const crc24Poly = 0x1864cfb
|
||||
const crc24Mask = 0xffffff
|
||||
|
||||
// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1
|
||||
func crc24(crc uint32, d []byte) uint32 {
|
||||
for _, b := range d {
|
||||
crc ^= uint32(b) << 16
|
||||
for i := 0; i < 8; i++ {
|
||||
crc <<= 1
|
||||
if crc&0x1000000 != 0 {
|
||||
crc ^= crc24Poly
|
||||
}
|
||||
}
|
||||
}
|
||||
return crc
|
||||
}
|
||||
|
||||
var armorStart = []byte("-----BEGIN ")
|
||||
var armorEnd = []byte("-----END ")
|
||||
var armorEndOfLine = []byte("-----")
|
||||
|
||||
// lineReader wraps a line based reader. It watches for the end of an armor
|
||||
// block and records the expected CRC value.
|
||||
type lineReader struct {
|
||||
in *bufio.Reader
|
||||
buf []byte
|
||||
eof bool
|
||||
crc *uint32
|
||||
}
|
||||
|
||||
// ourIsSpace checks if a rune is either space according to unicode
|
||||
// package, or ZeroWidthSpace (which is not a space according to
|
||||
// unicode module). Used to trim lines during header reading.
|
||||
func ourIsSpace(r rune) bool {
|
||||
return r == '\u200b' || unicode.IsSpace(r)
|
||||
}
|
||||
|
||||
func (l *lineReader) Read(p []byte) (n int, err error) {
|
||||
if l.eof {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
if len(l.buf) > 0 {
|
||||
n = copy(p, l.buf)
|
||||
l.buf = l.buf[n:]
|
||||
return
|
||||
}
|
||||
|
||||
line, _, err := l.in.ReadLine()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
line = bytes.TrimFunc(line, ourIsSpace)
|
||||
|
||||
if len(line) == 5 && line[0] == '=' {
|
||||
// This is the checksum line
|
||||
var expectedBytes [3]byte
|
||||
var m int
|
||||
m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:])
|
||||
if m != 3 || err != nil {
|
||||
return
|
||||
}
|
||||
crc := uint32(expectedBytes[0])<<16 |
|
||||
uint32(expectedBytes[1])<<8 |
|
||||
uint32(expectedBytes[2])
|
||||
l.crc = &crc
|
||||
|
||||
for {
|
||||
line, _, err = l.in.ReadLine()
|
||||
if err != nil && err != io.EOF {
|
||||
return
|
||||
}
|
||||
if len(strings.TrimSpace(string(line))) > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !bytes.HasPrefix(line, armorEnd) {
|
||||
return 0, ArmorCorrupt
|
||||
}
|
||||
|
||||
l.eof = true
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
if bytes.HasPrefix(line, armorEnd) {
|
||||
// Unexpected ending, there was no checksum.
|
||||
l.eof = true
|
||||
l.crc = nil
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
n = copy(p, line)
|
||||
bytesToSave := len(line) - n
|
||||
if bytesToSave > 0 {
|
||||
if cap(l.buf) < bytesToSave {
|
||||
l.buf = make([]byte, 0, bytesToSave)
|
||||
}
|
||||
l.buf = l.buf[0:bytesToSave]
|
||||
copy(l.buf, line[n:])
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// openpgpReader passes Read calls to the underlying base64 decoder, but keeps
|
||||
// a running CRC of the resulting data and checks the CRC against the value
|
||||
// found by the lineReader at EOF.
|
||||
type openpgpReader struct {
|
||||
lReader *lineReader
|
||||
b64Reader io.Reader
|
||||
currentCRC uint32
|
||||
}
|
||||
|
||||
func (r *openpgpReader) Read(p []byte) (n int, err error) {
|
||||
n, err = r.b64Reader.Read(p)
|
||||
r.currentCRC = crc24(r.currentCRC, p[:n])
|
||||
|
||||
if err == io.EOF {
|
||||
if r.lReader.crc != nil && *r.lReader.crc != uint32(r.currentCRC&crc24Mask) {
|
||||
return 0, ArmorCorrupt
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Decode reads a PGP armored block from the given Reader. It will ignore
|
||||
// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The
|
||||
// given Reader is not usable after calling this function: an arbitrary amount
|
||||
// of data may have been read past the end of the block.
|
||||
func Decode(in io.Reader) (p *Block, err error) {
|
||||
r := bufio.NewReaderSize(in, 100)
|
||||
var line []byte
|
||||
ignoreNext := false
|
||||
|
||||
TryNextBlock:
|
||||
p = nil
|
||||
|
||||
// Skip leading garbage
|
||||
for {
|
||||
ignoreThis := ignoreNext
|
||||
line, ignoreNext, err = r.ReadLine()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if ignoreNext || ignoreThis {
|
||||
continue
|
||||
}
|
||||
line = bytes.TrimSpace(line)
|
||||
if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
p = new(Block)
|
||||
p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)])
|
||||
p.Header = make(map[string]string)
|
||||
nextIsContinuation := false
|
||||
var lastKey string
|
||||
|
||||
// Read headers
|
||||
for {
|
||||
isContinuation := nextIsContinuation
|
||||
line, nextIsContinuation, err = r.ReadLine()
|
||||
if err != nil {
|
||||
p = nil
|
||||
return
|
||||
}
|
||||
if isContinuation {
|
||||
p.Header[lastKey] += string(line)
|
||||
continue
|
||||
}
|
||||
line = bytes.TrimFunc(line, ourIsSpace)
|
||||
if len(line) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
i := bytes.Index(line, []byte(": "))
|
||||
if i == -1 {
|
||||
goto TryNextBlock
|
||||
}
|
||||
lastKey = string(line[:i])
|
||||
p.Header[lastKey] = string(line[i+2:])
|
||||
}
|
||||
|
||||
p.lReader.in = r
|
||||
p.oReader.currentCRC = crc24Init
|
||||
p.oReader.lReader = &p.lReader
|
||||
p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader)
|
||||
p.Body = &p.oReader
|
||||
|
||||
return
|
||||
}
|
160
vendor/github.com/keybase/go-crypto/openpgp/armor/encode.go
generated
vendored
Normal file
160
vendor/github.com/keybase/go-crypto/openpgp/armor/encode.go
generated
vendored
Normal file
|
@ -0,0 +1,160 @@
|
|||
// Copyright 2010 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 armor
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"io"
|
||||
)
|
||||
|
||||
var armorHeaderSep = []byte(": ")
|
||||
var blockEnd = []byte("\n=")
|
||||
var newline = []byte("\n")
|
||||
var armorEndOfLineOut = []byte("-----\n")
|
||||
|
||||
// writeSlices writes its arguments to the given Writer.
|
||||
func writeSlices(out io.Writer, slices ...[]byte) (err error) {
|
||||
for _, s := range slices {
|
||||
_, err = out.Write(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// lineBreaker breaks data across several lines, all of the same byte length
|
||||
// (except possibly the last). Lines are broken with a single '\n'.
|
||||
type lineBreaker struct {
|
||||
lineLength int
|
||||
line []byte
|
||||
used int
|
||||
out io.Writer
|
||||
haveWritten bool
|
||||
}
|
||||
|
||||
func newLineBreaker(out io.Writer, lineLength int) *lineBreaker {
|
||||
return &lineBreaker{
|
||||
lineLength: lineLength,
|
||||
line: make([]byte, lineLength),
|
||||
used: 0,
|
||||
out: out,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *lineBreaker) Write(b []byte) (n int, err error) {
|
||||
n = len(b)
|
||||
|
||||
if n == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if l.used == 0 && l.haveWritten {
|
||||
_, err = l.out.Write([]byte{'\n'})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if l.used+len(b) < l.lineLength {
|
||||
l.used += copy(l.line[l.used:], b)
|
||||
return
|
||||
}
|
||||
|
||||
l.haveWritten = true
|
||||
_, err = l.out.Write(l.line[0:l.used])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
excess := l.lineLength - l.used
|
||||
l.used = 0
|
||||
|
||||
_, err = l.out.Write(b[0:excess])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = l.Write(b[excess:])
|
||||
return
|
||||
}
|
||||
|
||||
func (l *lineBreaker) Close() (err error) {
|
||||
if l.used > 0 {
|
||||
_, err = l.out.Write(l.line[0:l.used])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// encoding keeps track of a running CRC24 over the data which has been written
|
||||
// to it and outputs a OpenPGP checksum when closed, followed by an armor
|
||||
// trailer.
|
||||
//
|
||||
// It's built into a stack of io.Writers:
|
||||
// encoding -> base64 encoder -> lineBreaker -> out
|
||||
type encoding struct {
|
||||
out io.Writer
|
||||
breaker *lineBreaker
|
||||
b64 io.WriteCloser
|
||||
crc uint32
|
||||
blockType []byte
|
||||
}
|
||||
|
||||
func (e *encoding) Write(data []byte) (n int, err error) {
|
||||
e.crc = crc24(e.crc, data)
|
||||
return e.b64.Write(data)
|
||||
}
|
||||
|
||||
func (e *encoding) Close() (err error) {
|
||||
err = e.b64.Close()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
e.breaker.Close()
|
||||
|
||||
var checksumBytes [3]byte
|
||||
checksumBytes[0] = byte(e.crc >> 16)
|
||||
checksumBytes[1] = byte(e.crc >> 8)
|
||||
checksumBytes[2] = byte(e.crc)
|
||||
|
||||
var b64ChecksumBytes [4]byte
|
||||
base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:])
|
||||
|
||||
return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine, []byte{'\n'})
|
||||
}
|
||||
|
||||
// Encode returns a WriteCloser which will encode the data written to it in
|
||||
// OpenPGP armor.
|
||||
func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) {
|
||||
bType := []byte(blockType)
|
||||
err = writeSlices(out, armorStart, bType, armorEndOfLineOut)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for k, v := range headers {
|
||||
err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
_, err = out.Write(newline)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
e := &encoding{
|
||||
out: out,
|
||||
breaker: newLineBreaker(out, 64),
|
||||
crc: crc24Init,
|
||||
blockType: bType,
|
||||
}
|
||||
e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker)
|
||||
return e, nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue