Remove crypto/pkcs12
This commit is contained in:
parent
1e174fde46
commit
5434077d73
4
glide.lock
generated
4
glide.lock
generated
|
@ -53,10 +53,6 @@ imports:
|
||||||
version: f390dcf405f7b83c997eac1b06768bb9f44dec18
|
version: f390dcf405f7b83c997eac1b06768bb9f44dec18
|
||||||
- name: github.com/urfave/cli
|
- name: github.com/urfave/cli
|
||||||
version: 01857ac33766ce0c93856370626f9799281c14f4
|
version: 01857ac33766ce0c93856370626f9799281c14f4
|
||||||
- name: golang.org/x/crypto
|
|
||||||
version: 0c565bf13221fb55497d7ae2bb95694db1fd1bff
|
|
||||||
subpackages:
|
|
||||||
- pkcs12
|
|
||||||
- name: golang.org/x/sys
|
- name: golang.org/x/sys
|
||||||
version: a408501be4d17ee978c04a618e7a1b22af058c0e
|
version: a408501be4d17ee978c04a618e7a1b22af058c0e
|
||||||
subpackages:
|
subpackages:
|
||||||
|
|
|
@ -24,6 +24,3 @@ import:
|
||||||
version: v1.1.3
|
version: v1.1.3
|
||||||
- package: github.com/BurntSushi/toml
|
- package: github.com/BurntSushi/toml
|
||||||
version: v0.2.0
|
version: v0.2.0
|
||||||
- package: golang.org/x/crypto
|
|
||||||
subpackages:
|
|
||||||
- pkcs12
|
|
||||||
|
|
10
vendor/golang.org/x/crypto/.gitattributes
generated
vendored
10
vendor/golang.org/x/crypto/.gitattributes
generated
vendored
|
@ -1,10 +0,0 @@
|
||||||
# Treat all files in this repo as binary, with no git magic updating
|
|
||||||
# line endings. Windows users contributing to Go will need to use a
|
|
||||||
# modern version of git and editors capable of LF line endings.
|
|
||||||
#
|
|
||||||
# We'll prevent accidental CRLF line endings from entering the repo
|
|
||||||
# via the git-review gofmt checks.
|
|
||||||
#
|
|
||||||
# See golang.org/issue/9281
|
|
||||||
|
|
||||||
* -text
|
|
2
vendor/golang.org/x/crypto/.gitignore
generated
vendored
2
vendor/golang.org/x/crypto/.gitignore
generated
vendored
|
@ -1,2 +0,0 @@
|
||||||
# Add no patterns to .hgignore except for files generated by the build.
|
|
||||||
last-change
|
|
3
vendor/golang.org/x/crypto/AUTHORS
generated
vendored
3
vendor/golang.org/x/crypto/AUTHORS
generated
vendored
|
@ -1,3 +0,0 @@
|
||||||
# This source code refers to The Go Authors for copyright purposes.
|
|
||||||
# The master list of authors is in the main Go distribution,
|
|
||||||
# visible at http://tip.golang.org/AUTHORS.
|
|
31
vendor/golang.org/x/crypto/CONTRIBUTING.md
generated
vendored
31
vendor/golang.org/x/crypto/CONTRIBUTING.md
generated
vendored
|
@ -1,31 +0,0 @@
|
||||||
# Contributing to Go
|
|
||||||
|
|
||||||
Go is an open source project.
|
|
||||||
|
|
||||||
It is the work of hundreds of contributors. We appreciate your help!
|
|
||||||
|
|
||||||
|
|
||||||
## Filing issues
|
|
||||||
|
|
||||||
When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions:
|
|
||||||
|
|
||||||
1. What version of Go are you using (`go version`)?
|
|
||||||
2. What operating system and processor architecture are you using?
|
|
||||||
3. What did you do?
|
|
||||||
4. What did you expect to see?
|
|
||||||
5. What did you see instead?
|
|
||||||
|
|
||||||
General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
|
|
||||||
The gophers there will answer or ask you to file an issue if you've tripped over a bug.
|
|
||||||
|
|
||||||
## Contributing code
|
|
||||||
|
|
||||||
Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
|
|
||||||
before sending patches.
|
|
||||||
|
|
||||||
**We do not accept GitHub pull requests**
|
|
||||||
(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review).
|
|
||||||
|
|
||||||
Unless otherwise noted, the Go source files are distributed under
|
|
||||||
the BSD-style license found in the LICENSE file.
|
|
||||||
|
|
3
vendor/golang.org/x/crypto/CONTRIBUTORS
generated
vendored
3
vendor/golang.org/x/crypto/CONTRIBUTORS
generated
vendored
|
@ -1,3 +0,0 @@
|
||||||
# This source code was written by the Go contributors.
|
|
||||||
# The master list of contributors is in the main Go distribution,
|
|
||||||
# visible at http://tip.golang.org/CONTRIBUTORS.
|
|
27
vendor/golang.org/x/crypto/LICENSE
generated
vendored
27
vendor/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.
|
|
22
vendor/golang.org/x/crypto/PATENTS
generated
vendored
22
vendor/golang.org/x/crypto/PATENTS
generated
vendored
|
@ -1,22 +0,0 @@
|
||||||
Additional IP Rights Grant (Patents)
|
|
||||||
|
|
||||||
"This implementation" means the copyrightable works distributed by
|
|
||||||
Google as part of the Go project.
|
|
||||||
|
|
||||||
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
|
||||||
no-charge, royalty-free, irrevocable (except as stated in this section)
|
|
||||||
patent license to make, have made, use, offer to sell, sell, import,
|
|
||||||
transfer and otherwise run, modify and propagate the contents of this
|
|
||||||
implementation of Go, where such license applies only to those patent
|
|
||||||
claims, both currently owned or controlled by Google and acquired in
|
|
||||||
the future, licensable by Google that are necessarily infringed by this
|
|
||||||
implementation of Go. This grant does not include claims that would be
|
|
||||||
infringed only as a consequence of further modification of this
|
|
||||||
implementation. If you or your agent or exclusive licensee institute or
|
|
||||||
order or agree to the institution of patent litigation against any
|
|
||||||
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
|
||||||
that this implementation of Go or any code incorporated within this
|
|
||||||
implementation of Go constitutes direct or contributory patent
|
|
||||||
infringement, or inducement of patent infringement, then any patent
|
|
||||||
rights granted to you under this License for this implementation of Go
|
|
||||||
shall terminate as of the date such litigation is filed.
|
|
3
vendor/golang.org/x/crypto/README
generated
vendored
3
vendor/golang.org/x/crypto/README
generated
vendored
|
@ -1,3 +0,0 @@
|
||||||
This repository holds supplementary Go cryptography libraries.
|
|
||||||
|
|
||||||
To submit changes to this repository, see http://golang.org/doc/contribute.html.
|
|
473
vendor/golang.org/x/crypto/acme/internal/acme/acme.go
generated
vendored
473
vendor/golang.org/x/crypto/acme/internal/acme/acme.go
generated
vendored
|
@ -1,473 +0,0 @@
|
||||||
// Copyright 2015 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 acme provides an ACME client implementation.
|
|
||||||
// See https://ietf-wg-acme.github.io/acme/ for details.
|
|
||||||
//
|
|
||||||
// This package is a work in progress and makes no API stability promises.
|
|
||||||
package acme
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/rsa"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Client is an ACME client.
|
|
||||||
type Client struct {
|
|
||||||
// HTTPClient optionally specifies an HTTP client to use
|
|
||||||
// instead of http.DefaultClient.
|
|
||||||
HTTPClient *http.Client
|
|
||||||
|
|
||||||
// Key is the account key used to register with a CA
|
|
||||||
// and sign requests.
|
|
||||||
Key *rsa.PrivateKey
|
|
||||||
}
|
|
||||||
|
|
||||||
// Discover performs ACME server discovery using the provided discovery endpoint URL.
|
|
||||||
func (c *Client) Discover(url string) (*Directory, error) {
|
|
||||||
res, err := c.httpClient().Get(url)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
if res.StatusCode != http.StatusOK {
|
|
||||||
return nil, responseError(res)
|
|
||||||
}
|
|
||||||
var v struct {
|
|
||||||
Reg string `json:"new-reg"`
|
|
||||||
Authz string `json:"new-authz"`
|
|
||||||
Cert string `json:"new-cert"`
|
|
||||||
Revoke string `json:"revoke-cert"`
|
|
||||||
Meta struct {
|
|
||||||
Terms string `json:"terms-of-service"`
|
|
||||||
Website string `json:"website"`
|
|
||||||
CAA []string `json:"caa-identities"`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if json.NewDecoder(res.Body).Decode(&v); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &Directory{
|
|
||||||
RegURL: v.Reg,
|
|
||||||
AuthzURL: v.Authz,
|
|
||||||
CertURL: v.Cert,
|
|
||||||
RevokeURL: v.Revoke,
|
|
||||||
Terms: v.Meta.Terms,
|
|
||||||
Website: v.Meta.Website,
|
|
||||||
CAA: v.Meta.CAA,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateCert requests a new certificate.
|
|
||||||
// In the case where CA server does not provide the issued certificate in the response,
|
|
||||||
// CreateCert will poll certURL using c.FetchCert, which will result in additional round-trips.
|
|
||||||
// In such scenario the caller can cancel the polling with ctx.
|
|
||||||
//
|
|
||||||
// If the bundle is true, the returned value will also contain CA (the issuer) certificate.
|
|
||||||
// The url argument is an Directory.CertURL value, typically obtained from c.Discover.
|
|
||||||
// The csr is a DER encoded certificate signing request.
|
|
||||||
func (c *Client) CreateCert(ctx context.Context, url string, csr []byte, exp time.Duration, bundle bool) (der [][]byte, certURL string, err error) {
|
|
||||||
req := struct {
|
|
||||||
Resource string `json:"resource"`
|
|
||||||
CSR string `json:"csr"`
|
|
||||||
NotBefore string `json:"notBefore,omitempty"`
|
|
||||||
NotAfter string `json:"notAfter,omitempty"`
|
|
||||||
}{
|
|
||||||
Resource: "new-cert",
|
|
||||||
CSR: base64.RawURLEncoding.EncodeToString(csr),
|
|
||||||
}
|
|
||||||
now := timeNow()
|
|
||||||
req.NotBefore = now.Format(time.RFC3339)
|
|
||||||
if exp > 0 {
|
|
||||||
req.NotAfter = now.Add(exp).Format(time.RFC3339)
|
|
||||||
}
|
|
||||||
|
|
||||||
res, err := c.postJWS(url, req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, "", err
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
if res.StatusCode != http.StatusCreated {
|
|
||||||
return nil, "", responseError(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
curl := res.Header.Get("location") // cert permanent URL
|
|
||||||
if res.ContentLength == 0 {
|
|
||||||
// no cert in the body; poll until we get it
|
|
||||||
cert, err := c.FetchCert(ctx, curl, bundle)
|
|
||||||
return cert, curl, err
|
|
||||||
}
|
|
||||||
// slurp issued cert and ca, if requested
|
|
||||||
cert, err := responseCert(c.httpClient(), res, bundle)
|
|
||||||
return cert, curl, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// FetchCert retrieves already issued certificate from the given url, in DER format.
|
|
||||||
// It retries the request until the certificate is successfully retrieved,
|
|
||||||
// context is cancelled by the caller or an error response is received.
|
|
||||||
//
|
|
||||||
// The returned value will also contain CA (the issuer) certificate if bundle == true.
|
|
||||||
//
|
|
||||||
// http.DefaultClient is used if client argument is nil.
|
|
||||||
func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) {
|
|
||||||
for {
|
|
||||||
res, err := c.httpClient().Get(url)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
if res.StatusCode == http.StatusOK {
|
|
||||||
return responseCert(c.httpClient(), res, bundle)
|
|
||||||
}
|
|
||||||
if res.StatusCode > 299 {
|
|
||||||
return nil, responseError(res)
|
|
||||||
}
|
|
||||||
d, err := retryAfter(res.Header.Get("retry-after"))
|
|
||||||
if err != nil {
|
|
||||||
d = 3 * time.Second
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-time.After(d):
|
|
||||||
// retry
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, ctx.Err()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register creates a new account registration by following the "new-reg" flow.
|
|
||||||
// It returns registered account. The a argument is not modified.
|
|
||||||
//
|
|
||||||
// The url argument is typically an Directory.RegURL obtained from c.Discover.
|
|
||||||
func (c *Client) Register(url string, a *Account) (*Account, error) {
|
|
||||||
return c.doReg(url, "new-reg", a)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetReg retrieves an existing registration.
|
|
||||||
// The url argument is an Account.URI, typically obtained from c.Register.
|
|
||||||
func (c *Client) GetReg(url string) (*Account, error) {
|
|
||||||
a := &Account{URI: url}
|
|
||||||
return c.doReg(url, "reg", a)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateReg updates an existing registration.
|
|
||||||
// It returns an updated account copy. The provided account is not modified.
|
|
||||||
//
|
|
||||||
// The url argument is an Account.URI, usually obtained with c.Register.
|
|
||||||
func (c *Client) UpdateReg(url string, a *Account) (*Account, error) {
|
|
||||||
return c.doReg(url, "reg", a)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Authorize performs the initial step in an authorization flow.
|
|
||||||
// The caller will then need to choose from and perform a set of returned
|
|
||||||
// challenges using c.Accept in order to successfully complete authorization.
|
|
||||||
//
|
|
||||||
// The url argument is an authz URL, usually obtained with c.Register.
|
|
||||||
func (c *Client) Authorize(url, domain string) (*Authorization, error) {
|
|
||||||
type authzID struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Value string `json:"value"`
|
|
||||||
}
|
|
||||||
req := struct {
|
|
||||||
Resource string `json:"resource"`
|
|
||||||
Identifier authzID `json:"identifier"`
|
|
||||||
}{
|
|
||||||
Resource: "new-authz",
|
|
||||||
Identifier: authzID{Type: "dns", Value: domain},
|
|
||||||
}
|
|
||||||
res, err := c.postJWS(url, req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
if res.StatusCode != http.StatusCreated {
|
|
||||||
return nil, responseError(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
var v wireAuthz
|
|
||||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
|
||||||
return nil, fmt.Errorf("Decode: %v", err)
|
|
||||||
}
|
|
||||||
if v.Status != StatusPending {
|
|
||||||
return nil, fmt.Errorf("Unexpected status: %s", v.Status)
|
|
||||||
}
|
|
||||||
return v.authorization(res.Header.Get("Location")), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAuthz retrieves the current status of an authorization flow.
|
|
||||||
//
|
|
||||||
// A client typically polls an authz status using this method.
|
|
||||||
func (c *Client) GetAuthz(url string) (*Authorization, error) {
|
|
||||||
res, err := c.httpClient().Get(url)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
|
|
||||||
return nil, responseError(res)
|
|
||||||
}
|
|
||||||
var v wireAuthz
|
|
||||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
|
||||||
return nil, fmt.Errorf("Decode: %v", err)
|
|
||||||
}
|
|
||||||
return v.authorization(url), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetChallenge retrieves the current status of an challenge.
|
|
||||||
//
|
|
||||||
// A client typically polls a challenge status using this method.
|
|
||||||
func (c *Client) GetChallenge(url string) (*Challenge, error) {
|
|
||||||
res, err := c.httpClient().Get(url)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
|
|
||||||
return nil, responseError(res)
|
|
||||||
}
|
|
||||||
v := wireChallenge{URI: url}
|
|
||||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
|
||||||
return nil, fmt.Errorf("Decode: %v", err)
|
|
||||||
}
|
|
||||||
return v.challenge(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accept informs the server that the client accepts one of its challenges
|
|
||||||
// previously obtained with c.Authorize.
|
|
||||||
//
|
|
||||||
// The server will then perform the validation asynchronously.
|
|
||||||
func (c *Client) Accept(chal *Challenge) (*Challenge, error) {
|
|
||||||
req := struct {
|
|
||||||
Resource string `json:"resource"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
Auth string `json:"keyAuthorization"`
|
|
||||||
}{
|
|
||||||
Resource: "challenge",
|
|
||||||
Type: chal.Type,
|
|
||||||
Auth: keyAuth(&c.Key.PublicKey, chal.Token),
|
|
||||||
}
|
|
||||||
res, err := c.postJWS(chal.URI, req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
// Note: the protocol specifies 200 as the expected response code, but
|
|
||||||
// letsencrypt seems to be returning 202.
|
|
||||||
if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
|
|
||||||
return nil, responseError(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
var v wireChallenge
|
|
||||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
|
||||||
return nil, fmt.Errorf("Decode: %v", err)
|
|
||||||
}
|
|
||||||
return v.challenge(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTP01Handler creates a new handler which responds to a http-01 challenge.
|
|
||||||
// The token argument is a Challenge.Token value.
|
|
||||||
func (c *Client) HTTP01Handler(token string) http.Handler {
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if !strings.HasSuffix(r.URL.Path, token) {
|
|
||||||
w.WriteHeader(http.StatusNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set("content-type", "text/plain")
|
|
||||||
w.Write([]byte(keyAuth(&c.Key.PublicKey, token)))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) httpClient() *http.Client {
|
|
||||||
if c.HTTPClient != nil {
|
|
||||||
return c.HTTPClient
|
|
||||||
}
|
|
||||||
return http.DefaultClient
|
|
||||||
}
|
|
||||||
|
|
||||||
// postJWS signs body and posts it to the provided url.
|
|
||||||
// The body argument must be JSON-serializable.
|
|
||||||
func (c *Client) postJWS(url string, body interface{}) (*http.Response, error) {
|
|
||||||
nonce, err := fetchNonce(c.httpClient(), url)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
b, err := jwsEncodeJSON(body, c.Key, nonce)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
req, err := http.NewRequest("POST", url, bytes.NewReader(b))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return c.httpClient().Do(req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// doReg sends all types of registration requests.
|
|
||||||
// The type of request is identified by typ argument, which is a "resource"
|
|
||||||
// in the ACME spec terms.
|
|
||||||
//
|
|
||||||
// A non-nil acct argument indicates whether the intention is to mutate data
|
|
||||||
// of the Account. Only Contact and Agreement of its fields are used
|
|
||||||
// in such cases.
|
|
||||||
//
|
|
||||||
// The fields of acct will be populate with the server response
|
|
||||||
// and may be overwritten.
|
|
||||||
func (c *Client) doReg(url string, typ string, acct *Account) (*Account, error) {
|
|
||||||
req := struct {
|
|
||||||
Resource string `json:"resource"`
|
|
||||||
Contact []string `json:"contact,omitempty"`
|
|
||||||
Agreement string `json:"agreement,omitempty"`
|
|
||||||
}{
|
|
||||||
Resource: typ,
|
|
||||||
}
|
|
||||||
if acct != nil {
|
|
||||||
req.Contact = acct.Contact
|
|
||||||
req.Agreement = acct.AgreedTerms
|
|
||||||
}
|
|
||||||
res, err := c.postJWS(url, req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
if res.StatusCode < 200 || res.StatusCode > 299 {
|
|
||||||
return nil, responseError(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
var v struct {
|
|
||||||
Contact []string
|
|
||||||
Agreement string
|
|
||||||
Authorizations string
|
|
||||||
Certificates string
|
|
||||||
}
|
|
||||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
|
||||||
return nil, fmt.Errorf("Decode: %v", err)
|
|
||||||
}
|
|
||||||
return &Account{
|
|
||||||
URI: res.Header.Get("Location"),
|
|
||||||
Contact: v.Contact,
|
|
||||||
AgreedTerms: v.Agreement,
|
|
||||||
CurrentTerms: linkHeader(res.Header, "terms-of-service"),
|
|
||||||
Authz: linkHeader(res.Header, "next"),
|
|
||||||
Authorizations: v.Authorizations,
|
|
||||||
Certificates: v.Certificates,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func responseCert(client *http.Client, res *http.Response, bundle bool) ([][]byte, error) {
|
|
||||||
b, err := ioutil.ReadAll(res.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("ReadAll: %v", err)
|
|
||||||
}
|
|
||||||
cert := [][]byte{b}
|
|
||||||
if !bundle {
|
|
||||||
return cert, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// append ca cert
|
|
||||||
up := linkHeader(res.Header, "up")
|
|
||||||
if up == "" {
|
|
||||||
return nil, errors.New("rel=up link not found")
|
|
||||||
}
|
|
||||||
res, err = client.Get(up)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
if res.StatusCode != http.StatusOK {
|
|
||||||
return nil, responseError(res)
|
|
||||||
}
|
|
||||||
b, err = ioutil.ReadAll(res.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return append(cert, b), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// responseError creates an error of Error type from resp.
|
|
||||||
func responseError(resp *http.Response) error {
|
|
||||||
// don't care if ReadAll returns an error:
|
|
||||||
// json.Unmarshal will fail in that case anyway
|
|
||||||
b, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
e := struct {
|
|
||||||
Status int
|
|
||||||
Type string
|
|
||||||
Detail string
|
|
||||||
}{
|
|
||||||
Status: resp.StatusCode,
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(b, &e); err != nil {
|
|
||||||
// this is not a regular error response:
|
|
||||||
// populate detail with anything we received,
|
|
||||||
// e.Status will already contain HTTP response code value
|
|
||||||
e.Detail = string(b)
|
|
||||||
if e.Detail == "" {
|
|
||||||
e.Detail = resp.Status
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &Error{
|
|
||||||
StatusCode: e.Status,
|
|
||||||
ProblemType: e.Type,
|
|
||||||
Detail: e.Detail,
|
|
||||||
Header: resp.Header,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fetchNonce(client *http.Client, url string) (string, error) {
|
|
||||||
resp, err := client.Head(url)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
enc := resp.Header.Get("replay-nonce")
|
|
||||||
if enc == "" {
|
|
||||||
return "", errors.New("nonce not found")
|
|
||||||
}
|
|
||||||
return enc, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func linkHeader(h http.Header, rel string) string {
|
|
||||||
for _, v := range h["Link"] {
|
|
||||||
parts := strings.Split(v, ";")
|
|
||||||
for _, p := range parts {
|
|
||||||
p = strings.TrimSpace(p)
|
|
||||||
if !strings.HasPrefix(p, "rel=") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if v := strings.Trim(p[4:], `"`); v == rel {
|
|
||||||
return strings.Trim(parts[0], "<>")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func retryAfter(v string) (time.Duration, error) {
|
|
||||||
if i, err := strconv.Atoi(v); err == nil {
|
|
||||||
return time.Duration(i) * time.Second, nil
|
|
||||||
}
|
|
||||||
t, err := http.ParseTime(v)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return t.Sub(timeNow()), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// keyAuth generates a key authorization string for a given token.
|
|
||||||
func keyAuth(pub *rsa.PublicKey, token string) string {
|
|
||||||
return fmt.Sprintf("%s.%s", token, JWKThumbprint(pub))
|
|
||||||
}
|
|
||||||
|
|
||||||
// timeNow is useful for testing for fixed current time.
|
|
||||||
var timeNow = time.Now
|
|
759
vendor/golang.org/x/crypto/acme/internal/acme/acme_test.go
generated
vendored
759
vendor/golang.org/x/crypto/acme/internal/acme/acme_test.go
generated
vendored
|
@ -1,759 +0,0 @@
|
||||||
// Copyright 2015 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 acme
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/x509"
|
|
||||||
"crypto/x509/pkix"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"math/big"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Decodes a JWS-encoded request and unmarshals the decoded JSON into a provided
|
|
||||||
// interface.
|
|
||||||
func decodeJWSRequest(t *testing.T, v interface{}, r *http.Request) {
|
|
||||||
// Decode request
|
|
||||||
var req struct{ Payload string }
|
|
||||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
payload, err := base64.RawURLEncoding.DecodeString(req.Payload)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
err = json.Unmarshal(payload, v)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDiscover(t *testing.T) {
|
|
||||||
const (
|
|
||||||
reg = "https://example.com/acme/new-reg"
|
|
||||||
authz = "https://example.com/acme/new-authz"
|
|
||||||
cert = "https://example.com/acme/new-cert"
|
|
||||||
revoke = "https://example.com/acme/revoke-cert"
|
|
||||||
)
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Header().Set("content-type", "application/json")
|
|
||||||
fmt.Fprintf(w, `{
|
|
||||||
"new-reg": %q,
|
|
||||||
"new-authz": %q,
|
|
||||||
"new-cert": %q,
|
|
||||||
"revoke-cert": %q
|
|
||||||
}`, reg, authz, cert, revoke)
|
|
||||||
}))
|
|
||||||
defer ts.Close()
|
|
||||||
ep, err := (&Client{}).Discover(ts.URL)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if ep.RegURL != reg {
|
|
||||||
t.Errorf("RegURL = %q; want %q", ep.RegURL, reg)
|
|
||||||
}
|
|
||||||
if ep.AuthzURL != authz {
|
|
||||||
t.Errorf("authzURL = %q; want %q", ep.AuthzURL, authz)
|
|
||||||
}
|
|
||||||
if ep.CertURL != cert {
|
|
||||||
t.Errorf("certURL = %q; want %q", ep.CertURL, cert)
|
|
||||||
}
|
|
||||||
if ep.RevokeURL != revoke {
|
|
||||||
t.Errorf("revokeURL = %q; want %q", ep.RevokeURL, revoke)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRegister(t *testing.T) {
|
|
||||||
contacts := []string{"mailto:admin@example.com"}
|
|
||||||
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method == "HEAD" {
|
|
||||||
w.Header().Set("replay-nonce", "test-nonce")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r.Method != "POST" {
|
|
||||||
t.Errorf("r.Method = %q; want POST", r.Method)
|
|
||||||
}
|
|
||||||
|
|
||||||
var j struct {
|
|
||||||
Resource string
|
|
||||||
Contact []string
|
|
||||||
Agreement string
|
|
||||||
}
|
|
||||||
decodeJWSRequest(t, &j, r)
|
|
||||||
|
|
||||||
// Test request
|
|
||||||
if j.Resource != "new-reg" {
|
|
||||||
t.Errorf("j.Resource = %q; want new-reg", j.Resource)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(j.Contact, contacts) {
|
|
||||||
t.Errorf("j.Contact = %v; want %v", j.Contact, contacts)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Location", "https://ca.tld/acme/reg/1")
|
|
||||||
w.Header().Set("Link", `<https://ca.tld/acme/new-authz>;rel="next"`)
|
|
||||||
w.Header().Add("Link", `<https://ca.tld/acme/recover-reg>;rel="recover"`)
|
|
||||||
w.Header().Add("Link", `<https://ca.tld/acme/terms>;rel="terms-of-service"`)
|
|
||||||
w.WriteHeader(http.StatusCreated)
|
|
||||||
b, _ := json.Marshal(contacts)
|
|
||||||
fmt.Fprintf(w, `{
|
|
||||||
"key":%q,
|
|
||||||
"contact":%s
|
|
||||||
}`, testKeyThumbprint, b)
|
|
||||||
}))
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
c := Client{Key: testKey}
|
|
||||||
a := &Account{Contact: contacts}
|
|
||||||
var err error
|
|
||||||
if a, err = c.Register(ts.URL, a); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if a.URI != "https://ca.tld/acme/reg/1" {
|
|
||||||
t.Errorf("a.URI = %q; want https://ca.tld/acme/reg/1", a.URI)
|
|
||||||
}
|
|
||||||
if a.Authz != "https://ca.tld/acme/new-authz" {
|
|
||||||
t.Errorf("a.Authz = %q; want https://ca.tld/acme/new-authz", a.Authz)
|
|
||||||
}
|
|
||||||
if a.CurrentTerms != "https://ca.tld/acme/terms" {
|
|
||||||
t.Errorf("a.CurrentTerms = %q; want https://ca.tld/acme/terms", a.CurrentTerms)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(a.Contact, contacts) {
|
|
||||||
t.Errorf("a.Contact = %v; want %v", a.Contact, contacts)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUpdateReg(t *testing.T) {
|
|
||||||
const terms = "https://ca.tld/acme/terms"
|
|
||||||
contacts := []string{"mailto:admin@example.com"}
|
|
||||||
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method == "HEAD" {
|
|
||||||
w.Header().Set("replay-nonce", "test-nonce")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r.Method != "POST" {
|
|
||||||
t.Errorf("r.Method = %q; want POST", r.Method)
|
|
||||||
}
|
|
||||||
|
|
||||||
var j struct {
|
|
||||||
Resource string
|
|
||||||
Contact []string
|
|
||||||
Agreement string
|
|
||||||
}
|
|
||||||
decodeJWSRequest(t, &j, r)
|
|
||||||
|
|
||||||
// Test request
|
|
||||||
if j.Resource != "reg" {
|
|
||||||
t.Errorf("j.Resource = %q; want reg", j.Resource)
|
|
||||||
}
|
|
||||||
if j.Agreement != terms {
|
|
||||||
t.Errorf("j.Agreement = %q; want %q", j.Agreement, terms)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(j.Contact, contacts) {
|
|
||||||
t.Errorf("j.Contact = %v; want %v", j.Contact, contacts)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Link", `<https://ca.tld/acme/new-authz>;rel="next"`)
|
|
||||||
w.Header().Add("Link", `<https://ca.tld/acme/recover-reg>;rel="recover"`)
|
|
||||||
w.Header().Add("Link", fmt.Sprintf(`<%s>;rel="terms-of-service"`, terms))
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
b, _ := json.Marshal(contacts)
|
|
||||||
fmt.Fprintf(w, `{
|
|
||||||
"key":%q,
|
|
||||||
"contact":%s,
|
|
||||||
"agreement":%q
|
|
||||||
}`, testKeyThumbprint, b, terms)
|
|
||||||
}))
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
c := Client{Key: testKey}
|
|
||||||
a := &Account{Contact: contacts, AgreedTerms: terms}
|
|
||||||
var err error
|
|
||||||
if a, err = c.UpdateReg(ts.URL, a); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if a.Authz != "https://ca.tld/acme/new-authz" {
|
|
||||||
t.Errorf("a.Authz = %q; want https://ca.tld/acme/new-authz", a.Authz)
|
|
||||||
}
|
|
||||||
if a.AgreedTerms != terms {
|
|
||||||
t.Errorf("a.AgreedTerms = %q; want %q", a.AgreedTerms, terms)
|
|
||||||
}
|
|
||||||
if a.CurrentTerms != terms {
|
|
||||||
t.Errorf("a.CurrentTerms = %q; want %q", a.CurrentTerms, terms)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetReg(t *testing.T) {
|
|
||||||
const terms = "https://ca.tld/acme/terms"
|
|
||||||
const newTerms = "https://ca.tld/acme/new-terms"
|
|
||||||
contacts := []string{"mailto:admin@example.com"}
|
|
||||||
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method == "HEAD" {
|
|
||||||
w.Header().Set("replay-nonce", "test-nonce")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r.Method != "POST" {
|
|
||||||
t.Errorf("r.Method = %q; want POST", r.Method)
|
|
||||||
}
|
|
||||||
|
|
||||||
var j struct {
|
|
||||||
Resource string
|
|
||||||
Contact []string
|
|
||||||
Agreement string
|
|
||||||
}
|
|
||||||
decodeJWSRequest(t, &j, r)
|
|
||||||
|
|
||||||
// Test request
|
|
||||||
if j.Resource != "reg" {
|
|
||||||
t.Errorf("j.Resource = %q; want reg", j.Resource)
|
|
||||||
}
|
|
||||||
if len(j.Contact) != 0 {
|
|
||||||
t.Errorf("j.Contact = %v", j.Contact)
|
|
||||||
}
|
|
||||||
if j.Agreement != "" {
|
|
||||||
t.Errorf("j.Agreement = %q", j.Agreement)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Link", `<https://ca.tld/acme/new-authz>;rel="next"`)
|
|
||||||
w.Header().Add("Link", `<https://ca.tld/acme/recover-reg>;rel="recover"`)
|
|
||||||
w.Header().Add("Link", fmt.Sprintf(`<%s>;rel="terms-of-service"`, newTerms))
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
b, _ := json.Marshal(contacts)
|
|
||||||
fmt.Fprintf(w, `{
|
|
||||||
"key":%q,
|
|
||||||
"contact":%s,
|
|
||||||
"agreement":%q
|
|
||||||
}`, testKeyThumbprint, b, terms)
|
|
||||||
}))
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
c := Client{Key: testKey}
|
|
||||||
a, err := c.GetReg(ts.URL)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if a.Authz != "https://ca.tld/acme/new-authz" {
|
|
||||||
t.Errorf("a.AuthzURL = %q; want https://ca.tld/acme/new-authz", a.Authz)
|
|
||||||
}
|
|
||||||
if a.AgreedTerms != terms {
|
|
||||||
t.Errorf("a.AgreedTerms = %q; want %q", a.AgreedTerms, terms)
|
|
||||||
}
|
|
||||||
if a.CurrentTerms != newTerms {
|
|
||||||
t.Errorf("a.CurrentTerms = %q; want %q", a.CurrentTerms, newTerms)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAuthorize(t *testing.T) {
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method == "HEAD" {
|
|
||||||
w.Header().Set("replay-nonce", "test-nonce")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r.Method != "POST" {
|
|
||||||
t.Errorf("r.Method = %q; want POST", r.Method)
|
|
||||||
}
|
|
||||||
|
|
||||||
var j struct {
|
|
||||||
Resource string
|
|
||||||
Identifier struct {
|
|
||||||
Type string
|
|
||||||
Value string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
decodeJWSRequest(t, &j, r)
|
|
||||||
|
|
||||||
// Test request
|
|
||||||
if j.Resource != "new-authz" {
|
|
||||||
t.Errorf("j.Resource = %q; want new-authz", j.Resource)
|
|
||||||
}
|
|
||||||
if j.Identifier.Type != "dns" {
|
|
||||||
t.Errorf("j.Identifier.Type = %q; want dns", j.Identifier.Type)
|
|
||||||
}
|
|
||||||
if j.Identifier.Value != "example.com" {
|
|
||||||
t.Errorf("j.Identifier.Value = %q; want example.com", j.Identifier.Value)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Location", "https://ca.tld/acme/auth/1")
|
|
||||||
w.WriteHeader(http.StatusCreated)
|
|
||||||
fmt.Fprintf(w, `{
|
|
||||||
"identifier": {"type":"dns","value":"example.com"},
|
|
||||||
"status":"pending",
|
|
||||||
"challenges":[
|
|
||||||
{
|
|
||||||
"type":"http-01",
|
|
||||||
"status":"pending",
|
|
||||||
"uri":"https://ca.tld/acme/challenge/publickey/id1",
|
|
||||||
"token":"token1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type":"tls-sni-01",
|
|
||||||
"status":"pending",
|
|
||||||
"uri":"https://ca.tld/acme/challenge/publickey/id2",
|
|
||||||
"token":"token2"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"combinations":[[0],[1]]}`)
|
|
||||||
}))
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
cl := Client{Key: testKey}
|
|
||||||
auth, err := cl.Authorize(ts.URL, "example.com")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if auth.URI != "https://ca.tld/acme/auth/1" {
|
|
||||||
t.Errorf("URI = %q; want https://ca.tld/acme/auth/1", auth.URI)
|
|
||||||
}
|
|
||||||
if auth.Status != "pending" {
|
|
||||||
t.Errorf("Status = %q; want pending", auth.Status)
|
|
||||||
}
|
|
||||||
if auth.Identifier.Type != "dns" {
|
|
||||||
t.Errorf("Identifier.Type = %q; want dns", auth.Identifier.Type)
|
|
||||||
}
|
|
||||||
if auth.Identifier.Value != "example.com" {
|
|
||||||
t.Errorf("Identifier.Value = %q; want example.com", auth.Identifier.Value)
|
|
||||||
}
|
|
||||||
|
|
||||||
if n := len(auth.Challenges); n != 2 {
|
|
||||||
t.Fatalf("len(auth.Challenges) = %d; want 2", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
c := auth.Challenges[0]
|
|
||||||
if c.Type != "http-01" {
|
|
||||||
t.Errorf("c.Type = %q; want http-01", c.Type)
|
|
||||||
}
|
|
||||||
if c.URI != "https://ca.tld/acme/challenge/publickey/id1" {
|
|
||||||
t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI)
|
|
||||||
}
|
|
||||||
if c.Token != "token1" {
|
|
||||||
t.Errorf("c.Token = %q; want token1", c.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
c = auth.Challenges[1]
|
|
||||||
if c.Type != "tls-sni-01" {
|
|
||||||
t.Errorf("c.Type = %q; want tls-sni-01", c.Type)
|
|
||||||
}
|
|
||||||
if c.URI != "https://ca.tld/acme/challenge/publickey/id2" {
|
|
||||||
t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id2", c.URI)
|
|
||||||
}
|
|
||||||
if c.Token != "token2" {
|
|
||||||
t.Errorf("c.Token = %q; want token2", c.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
combs := [][]int{{0}, {1}}
|
|
||||||
if !reflect.DeepEqual(auth.Combinations, combs) {
|
|
||||||
t.Errorf("auth.Combinations: %+v\nwant: %+v\n", auth.Combinations, combs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPollAuthz(t *testing.T) {
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "GET" {
|
|
||||||
t.Errorf("r.Method = %q; want GET", r.Method)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
fmt.Fprintf(w, `{
|
|
||||||
"identifier": {"type":"dns","value":"example.com"},
|
|
||||||
"status":"pending",
|
|
||||||
"challenges":[
|
|
||||||
{
|
|
||||||
"type":"http-01",
|
|
||||||
"status":"pending",
|
|
||||||
"uri":"https://ca.tld/acme/challenge/publickey/id1",
|
|
||||||
"token":"token1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type":"tls-sni-01",
|
|
||||||
"status":"pending",
|
|
||||||
"uri":"https://ca.tld/acme/challenge/publickey/id2",
|
|
||||||
"token":"token2"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"combinations":[[0],[1]]}`)
|
|
||||||
}))
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
cl := Client{Key: testKey}
|
|
||||||
auth, err := cl.GetAuthz(ts.URL)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if auth.Status != "pending" {
|
|
||||||
t.Errorf("Status = %q; want pending", auth.Status)
|
|
||||||
}
|
|
||||||
if auth.Identifier.Type != "dns" {
|
|
||||||
t.Errorf("Identifier.Type = %q; want dns", auth.Identifier.Type)
|
|
||||||
}
|
|
||||||
if auth.Identifier.Value != "example.com" {
|
|
||||||
t.Errorf("Identifier.Value = %q; want example.com", auth.Identifier.Value)
|
|
||||||
}
|
|
||||||
|
|
||||||
if n := len(auth.Challenges); n != 2 {
|
|
||||||
t.Fatalf("len(set.Challenges) = %d; want 2", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
c := auth.Challenges[0]
|
|
||||||
if c.Type != "http-01" {
|
|
||||||
t.Errorf("c.Type = %q; want http-01", c.Type)
|
|
||||||
}
|
|
||||||
if c.URI != "https://ca.tld/acme/challenge/publickey/id1" {
|
|
||||||
t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI)
|
|
||||||
}
|
|
||||||
if c.Token != "token1" {
|
|
||||||
t.Errorf("c.Token = %q; want token1", c.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
c = auth.Challenges[1]
|
|
||||||
if c.Type != "tls-sni-01" {
|
|
||||||
t.Errorf("c.Type = %q; want tls-sni-01", c.Type)
|
|
||||||
}
|
|
||||||
if c.URI != "https://ca.tld/acme/challenge/publickey/id2" {
|
|
||||||
t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id2", c.URI)
|
|
||||||
}
|
|
||||||
if c.Token != "token2" {
|
|
||||||
t.Errorf("c.Token = %q; want token2", c.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
combs := [][]int{{0}, {1}}
|
|
||||||
if !reflect.DeepEqual(auth.Combinations, combs) {
|
|
||||||
t.Errorf("auth.Combinations: %+v\nwant: %+v\n", auth.Combinations, combs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPollChallenge(t *testing.T) {
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "GET" {
|
|
||||||
t.Errorf("r.Method = %q; want GET", r.Method)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
fmt.Fprintf(w, `{
|
|
||||||
"type":"http-01",
|
|
||||||
"status":"pending",
|
|
||||||
"uri":"https://ca.tld/acme/challenge/publickey/id1",
|
|
||||||
"token":"token1"}`)
|
|
||||||
}))
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
cl := Client{Key: testKey}
|
|
||||||
chall, err := cl.GetChallenge(ts.URL)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if chall.Status != "pending" {
|
|
||||||
t.Errorf("Status = %q; want pending", chall.Status)
|
|
||||||
}
|
|
||||||
if chall.Type != "http-01" {
|
|
||||||
t.Errorf("c.Type = %q; want http-01", chall.Type)
|
|
||||||
}
|
|
||||||
if chall.URI != "https://ca.tld/acme/challenge/publickey/id1" {
|
|
||||||
t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", chall.URI)
|
|
||||||
}
|
|
||||||
if chall.Token != "token1" {
|
|
||||||
t.Errorf("c.Token = %q; want token1", chall.Type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAcceptChallenge(t *testing.T) {
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method == "HEAD" {
|
|
||||||
w.Header().Set("replay-nonce", "test-nonce")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r.Method != "POST" {
|
|
||||||
t.Errorf("r.Method = %q; want POST", r.Method)
|
|
||||||
}
|
|
||||||
|
|
||||||
var j struct {
|
|
||||||
Resource string
|
|
||||||
Type string
|
|
||||||
Auth string `json:"keyAuthorization"`
|
|
||||||
}
|
|
||||||
decodeJWSRequest(t, &j, r)
|
|
||||||
|
|
||||||
// Test request
|
|
||||||
if j.Resource != "challenge" {
|
|
||||||
t.Errorf(`resource = %q; want "challenge"`, j.Resource)
|
|
||||||
}
|
|
||||||
if j.Type != "http-01" {
|
|
||||||
t.Errorf(`type = %q; want "http-01"`, j.Type)
|
|
||||||
}
|
|
||||||
keyAuth := "token1." + testKeyThumbprint
|
|
||||||
if j.Auth != keyAuth {
|
|
||||||
t.Errorf(`keyAuthorization = %q; want %q`, j.Auth, keyAuth)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Respond to request
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
|
||||||
fmt.Fprintf(w, `{
|
|
||||||
"type":"http-01",
|
|
||||||
"status":"pending",
|
|
||||||
"uri":"https://ca.tld/acme/challenge/publickey/id1",
|
|
||||||
"token":"token1",
|
|
||||||
"keyAuthorization":%q
|
|
||||||
}`, keyAuth)
|
|
||||||
}))
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
cl := Client{Key: testKey}
|
|
||||||
c, err := cl.Accept(&Challenge{
|
|
||||||
URI: ts.URL,
|
|
||||||
Token: "token1",
|
|
||||||
Type: "http-01",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Type != "http-01" {
|
|
||||||
t.Errorf("c.Type = %q; want http-01", c.Type)
|
|
||||||
}
|
|
||||||
if c.URI != "https://ca.tld/acme/challenge/publickey/id1" {
|
|
||||||
t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI)
|
|
||||||
}
|
|
||||||
if c.Token != "token1" {
|
|
||||||
t.Errorf("c.Token = %q; want token1", c.Type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewCert(t *testing.T) {
|
|
||||||
notBefore := time.Now()
|
|
||||||
notAfter := notBefore.AddDate(0, 2, 0)
|
|
||||||
timeNow = func() time.Time { return notBefore }
|
|
||||||
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method == "HEAD" {
|
|
||||||
w.Header().Set("replay-nonce", "test-nonce")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r.Method != "POST" {
|
|
||||||
t.Errorf("r.Method = %q; want POST", r.Method)
|
|
||||||
}
|
|
||||||
|
|
||||||
var j struct {
|
|
||||||
Resource string `json:"resource"`
|
|
||||||
CSR string `json:"csr"`
|
|
||||||
NotBefore string `json:"notBefore,omitempty"`
|
|
||||||
NotAfter string `json:"notAfter,omitempty"`
|
|
||||||
}
|
|
||||||
decodeJWSRequest(t, &j, r)
|
|
||||||
|
|
||||||
// Test request
|
|
||||||
if j.Resource != "new-cert" {
|
|
||||||
t.Errorf(`resource = %q; want "new-cert"`, j.Resource)
|
|
||||||
}
|
|
||||||
if j.NotBefore != notBefore.Format(time.RFC3339) {
|
|
||||||
t.Errorf(`notBefore = %q; wanted %q`, j.NotBefore, notBefore.Format(time.RFC3339))
|
|
||||||
}
|
|
||||||
if j.NotAfter != notAfter.Format(time.RFC3339) {
|
|
||||||
t.Errorf(`notAfter = %q; wanted %q`, j.NotAfter, notAfter.Format(time.RFC3339))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Respond to request
|
|
||||||
template := x509.Certificate{
|
|
||||||
SerialNumber: big.NewInt(int64(1)),
|
|
||||||
Subject: pkix.Name{
|
|
||||||
Organization: []string{"goacme"},
|
|
||||||
},
|
|
||||||
NotBefore: notBefore,
|
|
||||||
NotAfter: notAfter,
|
|
||||||
|
|
||||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
|
||||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
|
||||||
BasicConstraintsValid: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
sampleCert, err := x509.CreateCertificate(rand.Reader, &template, &template, &testKey.PublicKey, testKey)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error creating certificate: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Location", "https://ca.tld/acme/cert/1")
|
|
||||||
w.WriteHeader(http.StatusCreated)
|
|
||||||
w.Write(sampleCert)
|
|
||||||
}))
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
csr := x509.CertificateRequest{
|
|
||||||
Version: 0,
|
|
||||||
Subject: pkix.Name{
|
|
||||||
CommonName: "example.com",
|
|
||||||
Organization: []string{"goacme"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
csrb, err := x509.CreateCertificateRequest(rand.Reader, &csr, testKey)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c := Client{Key: testKey}
|
|
||||||
cert, certURL, err := c.CreateCert(context.Background(), ts.URL, csrb, notAfter.Sub(notBefore), false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if cert == nil {
|
|
||||||
t.Errorf("cert is nil")
|
|
||||||
}
|
|
||||||
if certURL != "https://ca.tld/acme/cert/1" {
|
|
||||||
t.Errorf("certURL = %q; want https://ca.tld/acme/cert/1", certURL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFetchCert(t *testing.T) {
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Write([]byte{1})
|
|
||||||
}))
|
|
||||||
defer ts.Close()
|
|
||||||
res, err := (&Client{}).FetchCert(context.Background(), ts.URL, false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("FetchCert: %v", err)
|
|
||||||
}
|
|
||||||
cert := [][]byte{{1}}
|
|
||||||
if !reflect.DeepEqual(res, cert) {
|
|
||||||
t.Errorf("res = %v; want %v", res, cert)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFetchCertRetry(t *testing.T) {
|
|
||||||
var count int
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if count < 1 {
|
|
||||||
w.Header().Set("retry-after", "0")
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
|
||||||
count++
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Write([]byte{1})
|
|
||||||
}))
|
|
||||||
defer ts.Close()
|
|
||||||
res, err := (&Client{}).FetchCert(context.Background(), ts.URL, false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("FetchCert: %v", err)
|
|
||||||
}
|
|
||||||
cert := [][]byte{{1}}
|
|
||||||
if !reflect.DeepEqual(res, cert) {
|
|
||||||
t.Errorf("res = %v; want %v", res, cert)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFetchCertCancel(t *testing.T) {
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Header().Set("retry-after", "0")
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
|
||||||
}))
|
|
||||||
defer ts.Close()
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
done := make(chan struct{})
|
|
||||||
var err error
|
|
||||||
go func() {
|
|
||||||
_, err = (&Client{}).FetchCert(ctx, ts.URL, false)
|
|
||||||
close(done)
|
|
||||||
}()
|
|
||||||
cancel()
|
|
||||||
<-done
|
|
||||||
if err != context.Canceled {
|
|
||||||
t.Errorf("err = %v; want %v", err, context.Canceled)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFetchNonce(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
code int
|
|
||||||
nonce string
|
|
||||||
}{
|
|
||||||
{http.StatusOK, "nonce1"},
|
|
||||||
{http.StatusBadRequest, "nonce2"},
|
|
||||||
{http.StatusOK, ""},
|
|
||||||
}
|
|
||||||
var i int
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "HEAD" {
|
|
||||||
t.Errorf("%d: r.Method = %q; want HEAD", i, r.Method)
|
|
||||||
}
|
|
||||||
w.Header().Set("replay-nonce", tests[i].nonce)
|
|
||||||
w.WriteHeader(tests[i].code)
|
|
||||||
}))
|
|
||||||
defer ts.Close()
|
|
||||||
for ; i < len(tests); i++ {
|
|
||||||
test := tests[i]
|
|
||||||
n, err := fetchNonce(http.DefaultClient, ts.URL)
|
|
||||||
if n != test.nonce {
|
|
||||||
t.Errorf("%d: n=%q; want %q", i, n, test.nonce)
|
|
||||||
}
|
|
||||||
switch {
|
|
||||||
case err == nil && test.nonce == "":
|
|
||||||
t.Errorf("%d: n=%q, err=%v; want non-nil error", i, n, err)
|
|
||||||
case err != nil && test.nonce != "":
|
|
||||||
t.Errorf("%d: n=%q, err=%v; want %q", i, n, err, test.nonce)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLinkHeader(t *testing.T) {
|
|
||||||
h := http.Header{"Link": {
|
|
||||||
`<https://example.com/acme/new-authz>;rel="next"`,
|
|
||||||
`<https://example.com/acme/recover-reg>; rel=recover`,
|
|
||||||
`<https://example.com/acme/terms>; foo=bar; rel="terms-of-service"`,
|
|
||||||
}}
|
|
||||||
tests := []struct{ in, out string }{
|
|
||||||
{"next", "https://example.com/acme/new-authz"},
|
|
||||||
{"recover", "https://example.com/acme/recover-reg"},
|
|
||||||
{"terms-of-service", "https://example.com/acme/terms"},
|
|
||||||
{"empty", ""},
|
|
||||||
}
|
|
||||||
for i, test := range tests {
|
|
||||||
if v := linkHeader(h, test.in); v != test.out {
|
|
||||||
t.Errorf("%d: parseLinkHeader(%q): %q; want %q", i, test.in, v, test.out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestErrorResponse(t *testing.T) {
|
|
||||||
s := `{
|
|
||||||
"status": 400,
|
|
||||||
"type": "urn:acme:error:xxx",
|
|
||||||
"detail": "text"
|
|
||||||
}`
|
|
||||||
res := &http.Response{
|
|
||||||
StatusCode: 400,
|
|
||||||
Status: "400 Bad Request",
|
|
||||||
Body: ioutil.NopCloser(strings.NewReader(s)),
|
|
||||||
Header: http.Header{"X-Foo": {"bar"}},
|
|
||||||
}
|
|
||||||
err := responseError(res)
|
|
||||||
v, ok := err.(*Error)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("err = %+v (%T); want *Error type", err, err)
|
|
||||||
}
|
|
||||||
if v.StatusCode != 400 {
|
|
||||||
t.Errorf("v.StatusCode = %v; want 400", v.StatusCode)
|
|
||||||
}
|
|
||||||
if v.ProblemType != "urn:acme:error:xxx" {
|
|
||||||
t.Errorf("v.ProblemType = %q; want urn:acme:error:xxx", v.ProblemType)
|
|
||||||
}
|
|
||||||
if v.Detail != "text" {
|
|
||||||
t.Errorf("v.Detail = %q; want text", v.Detail)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(v.Header, res.Header) {
|
|
||||||
t.Errorf("v.Header = %+v; want %+v", v.Header, res.Header)
|
|
||||||
}
|
|
||||||
}
|
|
67
vendor/golang.org/x/crypto/acme/internal/acme/jws.go
generated
vendored
67
vendor/golang.org/x/crypto/acme/internal/acme/jws.go
generated
vendored
|
@ -1,67 +0,0 @@
|
||||||
// Copyright 2015 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 acme
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto"
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/rsa"
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"math/big"
|
|
||||||
)
|
|
||||||
|
|
||||||
// jwsEncodeJSON signs claimset using provided key and a nonce.
|
|
||||||
// The result is serialized in JSON format.
|
|
||||||
// See https://tools.ietf.org/html/rfc7515#section-7.
|
|
||||||
func jwsEncodeJSON(claimset interface{}, key *rsa.PrivateKey, nonce string) ([]byte, error) {
|
|
||||||
jwk := jwkEncode(&key.PublicKey)
|
|
||||||
phead := fmt.Sprintf(`{"alg":"RS256","jwk":%s,"nonce":%q}`, jwk, nonce)
|
|
||||||
phead = base64.RawURLEncoding.EncodeToString([]byte(phead))
|
|
||||||
cs, err := json.Marshal(claimset)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
payload := base64.RawURLEncoding.EncodeToString(cs)
|
|
||||||
h := sha256.New()
|
|
||||||
h.Write([]byte(phead + "." + payload))
|
|
||||||
sig, err := rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, h.Sum(nil))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
enc := struct {
|
|
||||||
Protected string `json:"protected"`
|
|
||||||
Payload string `json:"payload"`
|
|
||||||
Sig string `json:"signature"`
|
|
||||||
}{
|
|
||||||
Protected: phead,
|
|
||||||
Payload: payload,
|
|
||||||
Sig: base64.RawURLEncoding.EncodeToString(sig),
|
|
||||||
}
|
|
||||||
return json.Marshal(&enc)
|
|
||||||
}
|
|
||||||
|
|
||||||
// jwkEncode encodes public part of an RSA key into a JWK.
|
|
||||||
// The result is also suitable for creating a JWK thumbprint.
|
|
||||||
func jwkEncode(pub *rsa.PublicKey) string {
|
|
||||||
n := pub.N
|
|
||||||
e := big.NewInt(int64(pub.E))
|
|
||||||
// fields order is important
|
|
||||||
// see https://tools.ietf.org/html/rfc7638#section-3.3 for details
|
|
||||||
return fmt.Sprintf(`{"e":"%s","kty":"RSA","n":"%s"}`,
|
|
||||||
base64.RawURLEncoding.EncodeToString(e.Bytes()),
|
|
||||||
base64.RawURLEncoding.EncodeToString(n.Bytes()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// JWKThumbprint creates a JWK thumbprint out of pub
|
|
||||||
// as specified in https://tools.ietf.org/html/rfc7638.
|
|
||||||
func JWKThumbprint(pub *rsa.PublicKey) string {
|
|
||||||
jwk := jwkEncode(pub)
|
|
||||||
b := sha256.Sum256([]byte(jwk))
|
|
||||||
return base64.RawURLEncoding.EncodeToString(b[:])
|
|
||||||
}
|
|
139
vendor/golang.org/x/crypto/acme/internal/acme/jws_test.go
generated
vendored
139
vendor/golang.org/x/crypto/acme/internal/acme/jws_test.go
generated
vendored
|
@ -1,139 +0,0 @@
|
||||||
// Copyright 2015 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 acme
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rsa"
|
|
||||||
"crypto/x509"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"encoding/pem"
|
|
||||||
"math/big"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
const testKeyPEM = `
|
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEowIBAAKCAQEA4xgZ3eRPkwoRvy7qeRUbmMDe0V+xH9eWLdu0iheeLlrmD2mq
|
|
||||||
WXfP9IeSKApbn34g8TuAS9g5zhq8ELQ3kmjr+KV86GAMgI6VAcGlq3QrzpTCf/30
|
|
||||||
Ab7+zawrfRaFONa1HwEzPY1KHnGVkxJc85gNkwYI9SY2RHXtvln3zs5wITNrdosq
|
|
||||||
EXeaIkVYBEhbhNu54pp3kxo6TuWLi9e6pXeWetEwmlBwtWZlPoib2j3TxLBksKZf
|
|
||||||
oyFyek380mHgJAumQ/I2fjj98/97mk3ihOY4AgVdCDj1z/GCoZkG5Rq7nbCGyosy
|
|
||||||
KWyDX00Zs+nNqVhoLeIvXC4nnWdJMZ6rogxyQQIDAQABAoIBACIEZTOI1Kao9nmV
|
|
||||||
9IeIsuaR1Y61b9neOF/MLmIVIZu+AAJFCMB4Iw11FV6sFodwpEyeZhx2WkpWVN+H
|
|
||||||
r19eGiLX3zsL0DOdqBJoSIHDWCCMxgnYJ6nvS0nRxX3qVrBp8R2g12Ub+gNPbmFm
|
|
||||||
ecf/eeERIVxfifd9VsyRu34eDEvcmKFuLYbElFcPh62xE3x12UZvV/sN7gXbawpP
|
|
||||||
G+w255vbE5MoaKdnnO83cTFlcHvhn24M/78qP7Te5OAeelr1R89kYxQLpuGe4fbS
|
|
||||||
zc6E3ym5Td6urDetGGrSY1Eu10/8sMusX+KNWkm+RsBRbkyKq72ks/qKpOxOa+c6
|
|
||||||
9gm+Y8ECgYEA/iNUyg1ubRdH11p82l8KHtFC1DPE0V1gSZsX29TpM5jS4qv46K+s
|
|
||||||
8Ym1zmrORM8x+cynfPx1VQZQ34EYeCMIX212ryJ+zDATl4NE0I4muMvSiH9vx6Xc
|
|
||||||
7FmhNnaYzPsBL5Tm9nmtQuP09YEn8poiOJFiDs/4olnD5ogA5O4THGkCgYEA5MIL
|
|
||||||
qWYBUuqbEWLRtMruUtpASclrBqNNsJEsMGbeqBJmoMxdHeSZckbLOrqm7GlMyNRJ
|
|
||||||
Ne/5uWRGSzaMYuGmwsPpERzqEvYFnSrpjW5YtXZ+JtxFXNVfm9Z1gLLgvGpOUCIU
|
|
||||||
RbpoDckDe1vgUuk3y5+DjZihs+rqIJ45XzXTzBkCgYBWuf3segruJZy5rEKhTv+o
|
|
||||||
JqeUvRn0jNYYKFpLBeyTVBrbie6GkbUGNIWbrK05pC+c3K9nosvzuRUOQQL1tJbd
|
|
||||||
4gA3oiD9U4bMFNr+BRTHyZ7OQBcIXdz3t1qhuHVKtnngIAN1p25uPlbRFUNpshnt
|
|
||||||
jgeVoHlsBhApcs5DUc+pyQKBgDzeHPg/+g4z+nrPznjKnktRY1W+0El93kgi+J0Q
|
|
||||||
YiJacxBKEGTJ1MKBb8X6sDurcRDm22wMpGfd9I5Cv2v4GsUsF7HD/cx5xdih+G73
|
|
||||||
c4clNj/k0Ff5Nm1izPUno4C+0IOl7br39IPmfpSuR6wH/h6iHQDqIeybjxyKvT1G
|
|
||||||
N0rRAoGBAKGD+4ZI/E1MoJ5CXB8cDDMHagbE3cq/DtmYzE2v1DFpQYu5I4PCm5c7
|
|
||||||
EQeIP6dZtv8IMgtGIb91QX9pXvP0aznzQKwYIA8nZgoENCPfiMTPiEDT9e/0lObO
|
|
||||||
9XWsXpbSTsRPj0sv1rB+UzBJ0PgjK4q2zOF0sNo7b1+6nlM3BWPx
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
||||||
`
|
|
||||||
|
|
||||||
// This thumbprint is for the testKey defined above.
|
|
||||||
const testKeyThumbprint = "6nicxzh6WETQlrvdchkz-U3e3DOQZ4heJKU63rfqMqQ"
|
|
||||||
|
|
||||||
var testKey *rsa.PrivateKey
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
d, _ := pem.Decode([]byte(testKeyPEM))
|
|
||||||
if d == nil {
|
|
||||||
panic("no block found in testKeyPEM")
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
testKey, err = x509.ParsePKCS1PrivateKey(d.Bytes)
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestJWSEncodeJSON(t *testing.T) {
|
|
||||||
claims := struct{ Msg string }{"Hello JWS"}
|
|
||||||
// JWS signed with testKey and "nonce" as the nonce value
|
|
||||||
// JSON-serialized JWS fields are split for easier testing
|
|
||||||
const (
|
|
||||||
// {"alg":"RS256","jwk":{"e":"AQAB","kty":"RSA","n":"..."},"nonce":"nonce"}
|
|
||||||
protected = "eyJhbGciOiJSUzI1NiIsImp3ayI6eyJlIjoiQVFBQiIsImt0eSI6" +
|
|
||||||
"IlJTQSIsIm4iOiI0eGdaM2VSUGt3b1J2eTdxZVJVYm1NRGUwVi14" +
|
|
||||||
"SDllV0xkdTBpaGVlTGxybUQybXFXWGZQOUllU0tBcGJuMzRnOFR1" +
|
|
||||||
"QVM5ZzV6aHE4RUxRM2ttanItS1Y4NkdBTWdJNlZBY0dscTNRcnpw" +
|
|
||||||
"VENmXzMwQWI3LXphd3JmUmFGT05hMUh3RXpQWTFLSG5HVmt4SmM4" +
|
|
||||||
"NWdOa3dZSTlTWTJSSFh0dmxuM3pzNXdJVE5yZG9zcUVYZWFJa1ZZ" +
|
|
||||||
"QkVoYmhOdTU0cHAza3hvNlR1V0xpOWU2cFhlV2V0RXdtbEJ3dFda" +
|
|
||||||
"bFBvaWIyajNUeExCa3NLWmZveUZ5ZWszODBtSGdKQXVtUV9JMmZq" +
|
|
||||||
"ajk4Xzk3bWszaWhPWTRBZ1ZkQ0RqMXpfR0NvWmtHNVJxN25iQ0d5" +
|
|
||||||
"b3N5S1d5RFgwMFpzLW5OcVZob0xlSXZYQzRubldkSk1aNnJvZ3h5" +
|
|
||||||
"UVEifSwibm9uY2UiOiJub25jZSJ9"
|
|
||||||
// {"Msg":"Hello JWS"}
|
|
||||||
payload = "eyJNc2ciOiJIZWxsbyBKV1MifQ"
|
|
||||||
signature = "eAGUikStX_UxyiFhxSLMyuyBcIB80GeBkFROCpap2sW3EmkU_ggF" +
|
|
||||||
"knaQzxrTfItICSAXsCLIquZ5BbrSWA_4vdEYrwWtdUj7NqFKjHRa" +
|
|
||||||
"zpLHcoR7r1rEHvkoP1xj49lS5fc3Wjjq8JUhffkhGbWZ8ZVkgPdC" +
|
|
||||||
"4tMBWiQDoth-x8jELP_3LYOB_ScUXi2mETBawLgOT2K8rA0Vbbmx" +
|
|
||||||
"hWNlOWuUf-8hL5YX4IOEwsS8JK_TrTq5Zc9My0zHJmaieqDV0UlP" +
|
|
||||||
"k0onFjPFkGm7MrPSgd0MqRG-4vSAg2O4hDo7rKv4n8POjjXlNQvM" +
|
|
||||||
"9IPLr8qZ7usYBKhEGwX3yq_eicAwBw"
|
|
||||||
)
|
|
||||||
|
|
||||||
b, err := jwsEncodeJSON(claims, testKey, "nonce")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
var jws struct{ Protected, Payload, Signature string }
|
|
||||||
if err := json.Unmarshal(b, &jws); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if jws.Protected != protected {
|
|
||||||
t.Errorf("protected:\n%s\nwant:\n%s", jws.Protected, protected)
|
|
||||||
}
|
|
||||||
if jws.Payload != payload {
|
|
||||||
t.Errorf("payload:\n%s\nwant:\n%s", jws.Payload, payload)
|
|
||||||
}
|
|
||||||
if jws.Signature != signature {
|
|
||||||
t.Errorf("signature:\n%s\nwant:\n%s", jws.Signature, signature)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestJWKThumbprint(t *testing.T) {
|
|
||||||
// Key example from RFC 7638
|
|
||||||
const base64N = "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAt" +
|
|
||||||
"VT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn6" +
|
|
||||||
"4tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FD" +
|
|
||||||
"W2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n9" +
|
|
||||||
"1CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINH" +
|
|
||||||
"aQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw"
|
|
||||||
const base64E = "AQAB"
|
|
||||||
const expected = "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs"
|
|
||||||
|
|
||||||
bytes, err := base64.RawURLEncoding.DecodeString(base64N)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error parsing example key N: %v", err)
|
|
||||||
}
|
|
||||||
n := new(big.Int).SetBytes(bytes)
|
|
||||||
|
|
||||||
bytes, err = base64.RawURLEncoding.DecodeString(base64E)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error parsing example key E: %v", err)
|
|
||||||
}
|
|
||||||
e := new(big.Int).SetBytes(bytes)
|
|
||||||
|
|
||||||
pub := &rsa.PublicKey{N: n, E: int(e.Uint64())}
|
|
||||||
th := JWKThumbprint(pub)
|
|
||||||
if th != expected {
|
|
||||||
t.Errorf("th = %q; want %q", th, expected)
|
|
||||||
}
|
|
||||||
}
|
|
181
vendor/golang.org/x/crypto/acme/internal/acme/types.go
generated
vendored
181
vendor/golang.org/x/crypto/acme/internal/acme/types.go
generated
vendored
|
@ -1,181 +0,0 @@
|
||||||
package acme
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ACME server response statuses used to describe Authorization and Challenge states.
|
|
||||||
const (
|
|
||||||
StatusUnknown = "unknown"
|
|
||||||
StatusPending = "pending"
|
|
||||||
StatusProcessing = "processing"
|
|
||||||
StatusValid = "valid"
|
|
||||||
StatusInvalid = "invalid"
|
|
||||||
StatusRevoked = "revoked"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Account is a user account. It is associated with a private key.
|
|
||||||
type Account struct {
|
|
||||||
// URI is the account unique ID, which is also a URL used to retrieve
|
|
||||||
// account data from the CA.
|
|
||||||
URI string
|
|
||||||
|
|
||||||
// Contact is a slice of contact info used during registration.
|
|
||||||
Contact []string
|
|
||||||
|
|
||||||
// The terms user has agreed to.
|
|
||||||
// Zero value indicates that the user hasn't agreed yet.
|
|
||||||
AgreedTerms string
|
|
||||||
|
|
||||||
// Actual terms of a CA.
|
|
||||||
CurrentTerms string
|
|
||||||
|
|
||||||
// Authz is the authorization URL used to initiate a new authz flow.
|
|
||||||
Authz string
|
|
||||||
|
|
||||||
// Authorizations is a URI from which a list of authorizations
|
|
||||||
// granted to this account can be fetched via a GET request.
|
|
||||||
Authorizations string
|
|
||||||
|
|
||||||
// Certificates is a URI from which a list of certificates
|
|
||||||
// issued for this account can be fetched via a GET request.
|
|
||||||
Certificates string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Directory is ACME server discovery data.
|
|
||||||
type Directory struct {
|
|
||||||
// RegURL is an account endpoint URL, allowing for creating new
|
|
||||||
// and modifying existing accounts.
|
|
||||||
RegURL string
|
|
||||||
|
|
||||||
// AuthzURL is used to initiate Identifier Authorization flow.
|
|
||||||
AuthzURL string
|
|
||||||
|
|
||||||
// CertURL is a new certificate issuance endpoint URL.
|
|
||||||
CertURL string
|
|
||||||
|
|
||||||
// RevokeURL is used to initiate a certificate revocation flow.
|
|
||||||
RevokeURL string
|
|
||||||
|
|
||||||
// Term is a URI identifying the current terms of service.
|
|
||||||
Terms string
|
|
||||||
|
|
||||||
// Website is an HTTP or HTTPS URL locating a website
|
|
||||||
// providing more information about the ACME server.
|
|
||||||
Website string
|
|
||||||
|
|
||||||
// CAA consists of lowercase hostname elements, which the ACME server
|
|
||||||
// recognises as referring to itself for the purposes of CAA record validation
|
|
||||||
// as defined in RFC6844.
|
|
||||||
CAA []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Challenge encodes a returned CA challenge.
|
|
||||||
type Challenge struct {
|
|
||||||
// Type is the challenge type, e.g. "http-01", "tls-sni-02", "dns-01".
|
|
||||||
Type string
|
|
||||||
|
|
||||||
// URI is where a challenge response can be posted to.
|
|
||||||
URI string
|
|
||||||
|
|
||||||
// Token is a random value that uniquely identifies the challenge.
|
|
||||||
Token string
|
|
||||||
|
|
||||||
// Status identifies the status of this challenge.
|
|
||||||
Status string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Authorization encodes an authorization response.
|
|
||||||
type Authorization struct {
|
|
||||||
// URI uniquely identifies a authorization.
|
|
||||||
URI string
|
|
||||||
|
|
||||||
// Status identifies the status of an authorization.
|
|
||||||
Status string
|
|
||||||
|
|
||||||
// Identifier is what the account is authorized to represent.
|
|
||||||
Identifier AuthzID
|
|
||||||
|
|
||||||
// Challenges that the client needs to fulfill in order to prove possession
|
|
||||||
// of the identifier (for pending authorizations).
|
|
||||||
// For final authorizations, the challenges that were used.
|
|
||||||
Challenges []*Challenge
|
|
||||||
|
|
||||||
// A collection of sets of challenges, each of which would be sufficient
|
|
||||||
// to prove possession of the identifier.
|
|
||||||
// Clients must complete a set of challenges that covers at least one set.
|
|
||||||
// Challenges are identified by their indices in the challenges array.
|
|
||||||
// If this field is empty, the client needs to complete all challenges.
|
|
||||||
Combinations [][]int
|
|
||||||
}
|
|
||||||
|
|
||||||
// AuthzID is an identifier that an account is authorized to represent.
|
|
||||||
type AuthzID struct {
|
|
||||||
Type string // The type of identifier, e.g. "dns".
|
|
||||||
Value string // The identifier itself, e.g. "example.org".
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error is an ACME error, defined in Problem Details for HTTP APIs doc
|
|
||||||
// http://tools.ietf.org/html/draft-ietf-appsawg-http-problem.
|
|
||||||
type Error struct {
|
|
||||||
// StatusCode is The HTTP status code generated by the origin server.
|
|
||||||
StatusCode int
|
|
||||||
// ProblemType is a URI reference that identifies the problem type,
|
|
||||||
// typically in a "urn:acme:error:xxx" form.
|
|
||||||
ProblemType string
|
|
||||||
// Detail is a human-readable explanation specific to this occurrence of the problem.
|
|
||||||
Detail string
|
|
||||||
// Header is the original server error response headers.
|
|
||||||
Header http.Header
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Error) Error() string {
|
|
||||||
return fmt.Sprintf("%d %s: %s", e.StatusCode, e.ProblemType, e.Detail)
|
|
||||||
}
|
|
||||||
|
|
||||||
// wireAuthz is ACME JSON representation of Authorization objects.
|
|
||||||
type wireAuthz struct {
|
|
||||||
Status string
|
|
||||||
Challenges []wireChallenge
|
|
||||||
Combinations [][]int
|
|
||||||
Identifier struct {
|
|
||||||
Type string
|
|
||||||
Value string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *wireAuthz) authorization(uri string) *Authorization {
|
|
||||||
a := &Authorization{
|
|
||||||
URI: uri,
|
|
||||||
Status: z.Status,
|
|
||||||
Identifier: AuthzID{Type: z.Identifier.Type, Value: z.Identifier.Value},
|
|
||||||
Combinations: z.Combinations, // shallow copy
|
|
||||||
Challenges: make([]*Challenge, len(z.Challenges)),
|
|
||||||
}
|
|
||||||
for i, v := range z.Challenges {
|
|
||||||
a.Challenges[i] = v.challenge()
|
|
||||||
}
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
// wireChallenge is ACME JSON challenge representation.
|
|
||||||
type wireChallenge struct {
|
|
||||||
URI string `json:"uri"`
|
|
||||||
Type string
|
|
||||||
Token string
|
|
||||||
Status string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *wireChallenge) challenge() *Challenge {
|
|
||||||
v := &Challenge{
|
|
||||||
URI: c.URI,
|
|
||||||
Type: c.Type,
|
|
||||||
Token: c.Token,
|
|
||||||
Status: c.Status,
|
|
||||||
}
|
|
||||||
if v.Status == "" {
|
|
||||||
v.Status = StatusPending
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
35
vendor/golang.org/x/crypto/bcrypt/base64.go
generated
vendored
35
vendor/golang.org/x/crypto/bcrypt/base64.go
generated
vendored
|
@ -1,35 +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 bcrypt
|
|
||||||
|
|
||||||
import "encoding/base64"
|
|
||||||
|
|
||||||
const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
|
||||||
|
|
||||||
var bcEncoding = base64.NewEncoding(alphabet)
|
|
||||||
|
|
||||||
func base64Encode(src []byte) []byte {
|
|
||||||
n := bcEncoding.EncodedLen(len(src))
|
|
||||||
dst := make([]byte, n)
|
|
||||||
bcEncoding.Encode(dst, src)
|
|
||||||
for dst[n-1] == '=' {
|
|
||||||
n--
|
|
||||||
}
|
|
||||||
return dst[:n]
|
|
||||||
}
|
|
||||||
|
|
||||||
func base64Decode(src []byte) ([]byte, error) {
|
|
||||||
numOfEquals := 4 - (len(src) % 4)
|
|
||||||
for i := 0; i < numOfEquals; i++ {
|
|
||||||
src = append(src, '=')
|
|
||||||
}
|
|
||||||
|
|
||||||
dst := make([]byte, bcEncoding.DecodedLen(len(src)))
|
|
||||||
n, err := bcEncoding.Decode(dst, src)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return dst[:n], nil
|
|
||||||
}
|
|
294
vendor/golang.org/x/crypto/bcrypt/bcrypt.go
generated
vendored
294
vendor/golang.org/x/crypto/bcrypt/bcrypt.go
generated
vendored
|
@ -1,294 +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 bcrypt implements Provos and Mazières's bcrypt adaptive hashing
|
|
||||||
// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf
|
|
||||||
package bcrypt // import "golang.org/x/crypto/bcrypt"
|
|
||||||
|
|
||||||
// The code is a port of Provos and Mazières's C implementation.
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/subtle"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"golang.org/x/crypto/blowfish"
|
|
||||||
"io"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword
|
|
||||||
MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword
|
|
||||||
DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword
|
|
||||||
)
|
|
||||||
|
|
||||||
// The error returned from CompareHashAndPassword when a password and hash do
|
|
||||||
// not match.
|
|
||||||
var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password")
|
|
||||||
|
|
||||||
// The error returned from CompareHashAndPassword when a hash is too short to
|
|
||||||
// be a bcrypt hash.
|
|
||||||
var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password")
|
|
||||||
|
|
||||||
// The error returned from CompareHashAndPassword when a hash was created with
|
|
||||||
// a bcrypt algorithm newer than this implementation.
|
|
||||||
type HashVersionTooNewError byte
|
|
||||||
|
|
||||||
func (hv HashVersionTooNewError) Error() string {
|
|
||||||
return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The error returned from CompareHashAndPassword when a hash starts with something other than '$'
|
|
||||||
type InvalidHashPrefixError byte
|
|
||||||
|
|
||||||
func (ih InvalidHashPrefixError) Error() string {
|
|
||||||
return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih))
|
|
||||||
}
|
|
||||||
|
|
||||||
type InvalidCostError int
|
|
||||||
|
|
||||||
func (ic InvalidCostError) Error() string {
|
|
||||||
return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost))
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
majorVersion = '2'
|
|
||||||
minorVersion = 'a'
|
|
||||||
maxSaltSize = 16
|
|
||||||
maxCryptedHashSize = 23
|
|
||||||
encodedSaltSize = 22
|
|
||||||
encodedHashSize = 31
|
|
||||||
minHashSize = 59
|
|
||||||
)
|
|
||||||
|
|
||||||
// magicCipherData is an IV for the 64 Blowfish encryption calls in
|
|
||||||
// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes.
|
|
||||||
var magicCipherData = []byte{
|
|
||||||
0x4f, 0x72, 0x70, 0x68,
|
|
||||||
0x65, 0x61, 0x6e, 0x42,
|
|
||||||
0x65, 0x68, 0x6f, 0x6c,
|
|
||||||
0x64, 0x65, 0x72, 0x53,
|
|
||||||
0x63, 0x72, 0x79, 0x44,
|
|
||||||
0x6f, 0x75, 0x62, 0x74,
|
|
||||||
}
|
|
||||||
|
|
||||||
type hashed struct {
|
|
||||||
hash []byte
|
|
||||||
salt []byte
|
|
||||||
cost int // allowed range is MinCost to MaxCost
|
|
||||||
major byte
|
|
||||||
minor byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenerateFromPassword returns the bcrypt hash of the password at the given
|
|
||||||
// cost. If the cost given is less than MinCost, the cost will be set to
|
|
||||||
// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package,
|
|
||||||
// to compare the returned hashed password with its cleartext version.
|
|
||||||
func GenerateFromPassword(password []byte, cost int) ([]byte, error) {
|
|
||||||
p, err := newFromPassword(password, cost)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return p.Hash(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CompareHashAndPassword compares a bcrypt hashed password with its possible
|
|
||||||
// plaintext equivalent. Returns nil on success, or an error on failure.
|
|
||||||
func CompareHashAndPassword(hashedPassword, password []byte) error {
|
|
||||||
p, err := newFromHash(hashedPassword)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
otherHash, err := bcrypt(password, p.cost, p.salt)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor}
|
|
||||||
if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return ErrMismatchedHashAndPassword
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cost returns the hashing cost used to create the given hashed
|
|
||||||
// password. When, in the future, the hashing cost of a password system needs
|
|
||||||
// to be increased in order to adjust for greater computational power, this
|
|
||||||
// function allows one to establish which passwords need to be updated.
|
|
||||||
func Cost(hashedPassword []byte) (int, error) {
|
|
||||||
p, err := newFromHash(hashedPassword)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return p.cost, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFromPassword(password []byte, cost int) (*hashed, error) {
|
|
||||||
if cost < MinCost {
|
|
||||||
cost = DefaultCost
|
|
||||||
}
|
|
||||||
p := new(hashed)
|
|
||||||
p.major = majorVersion
|
|
||||||
p.minor = minorVersion
|
|
||||||
|
|
||||||
err := checkCost(cost)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
p.cost = cost
|
|
||||||
|
|
||||||
unencodedSalt := make([]byte, maxSaltSize)
|
|
||||||
_, err = io.ReadFull(rand.Reader, unencodedSalt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
p.salt = base64Encode(unencodedSalt)
|
|
||||||
hash, err := bcrypt(password, p.cost, p.salt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
p.hash = hash
|
|
||||||
return p, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFromHash(hashedSecret []byte) (*hashed, error) {
|
|
||||||
if len(hashedSecret) < minHashSize {
|
|
||||||
return nil, ErrHashTooShort
|
|
||||||
}
|
|
||||||
p := new(hashed)
|
|
||||||
n, err := p.decodeVersion(hashedSecret)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
hashedSecret = hashedSecret[n:]
|
|
||||||
n, err = p.decodeCost(hashedSecret)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
hashedSecret = hashedSecret[n:]
|
|
||||||
|
|
||||||
// The "+2" is here because we'll have to append at most 2 '=' to the salt
|
|
||||||
// when base64 decoding it in expensiveBlowfishSetup().
|
|
||||||
p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2)
|
|
||||||
copy(p.salt, hashedSecret[:encodedSaltSize])
|
|
||||||
|
|
||||||
hashedSecret = hashedSecret[encodedSaltSize:]
|
|
||||||
p.hash = make([]byte, len(hashedSecret))
|
|
||||||
copy(p.hash, hashedSecret)
|
|
||||||
|
|
||||||
return p, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) {
|
|
||||||
cipherData := make([]byte, len(magicCipherData))
|
|
||||||
copy(cipherData, magicCipherData)
|
|
||||||
|
|
||||||
c, err := expensiveBlowfishSetup(password, uint32(cost), salt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < 24; i += 8 {
|
|
||||||
for j := 0; j < 64; j++ {
|
|
||||||
c.Encrypt(cipherData[i:i+8], cipherData[i:i+8])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bug compatibility with C bcrypt implementations. We only encode 23 of
|
|
||||||
// the 24 bytes encrypted.
|
|
||||||
hsh := base64Encode(cipherData[:maxCryptedHashSize])
|
|
||||||
return hsh, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) {
|
|
||||||
|
|
||||||
csalt, err := base64Decode(salt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bug compatibility with C bcrypt implementations. They use the trailing
|
|
||||||
// NULL in the key string during expansion.
|
|
||||||
ckey := append(key, 0)
|
|
||||||
|
|
||||||
c, err := blowfish.NewSaltedCipher(ckey, csalt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var i, rounds uint64
|
|
||||||
rounds = 1 << cost
|
|
||||||
for i = 0; i < rounds; i++ {
|
|
||||||
blowfish.ExpandKey(ckey, c)
|
|
||||||
blowfish.ExpandKey(csalt, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *hashed) Hash() []byte {
|
|
||||||
arr := make([]byte, 60)
|
|
||||||
arr[0] = '$'
|
|
||||||
arr[1] = p.major
|
|
||||||
n := 2
|
|
||||||
if p.minor != 0 {
|
|
||||||
arr[2] = p.minor
|
|
||||||
n = 3
|
|
||||||
}
|
|
||||||
arr[n] = '$'
|
|
||||||
n += 1
|
|
||||||
copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost)))
|
|
||||||
n += 2
|
|
||||||
arr[n] = '$'
|
|
||||||
n += 1
|
|
||||||
copy(arr[n:], p.salt)
|
|
||||||
n += encodedSaltSize
|
|
||||||
copy(arr[n:], p.hash)
|
|
||||||
n += encodedHashSize
|
|
||||||
return arr[:n]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *hashed) decodeVersion(sbytes []byte) (int, error) {
|
|
||||||
if sbytes[0] != '$' {
|
|
||||||
return -1, InvalidHashPrefixError(sbytes[0])
|
|
||||||
}
|
|
||||||
if sbytes[1] > majorVersion {
|
|
||||||
return -1, HashVersionTooNewError(sbytes[1])
|
|
||||||
}
|
|
||||||
p.major = sbytes[1]
|
|
||||||
n := 3
|
|
||||||
if sbytes[2] != '$' {
|
|
||||||
p.minor = sbytes[2]
|
|
||||||
n++
|
|
||||||
}
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// sbytes should begin where decodeVersion left off.
|
|
||||||
func (p *hashed) decodeCost(sbytes []byte) (int, error) {
|
|
||||||
cost, err := strconv.Atoi(string(sbytes[0:2]))
|
|
||||||
if err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
err = checkCost(cost)
|
|
||||||
if err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
p.cost = cost
|
|
||||||
return 3, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *hashed) String() string {
|
|
||||||
return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor)
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkCost(cost int) error {
|
|
||||||
if cost < MinCost || cost > MaxCost {
|
|
||||||
return InvalidCostError(cost)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
226
vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go
generated
vendored
226
vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go
generated
vendored
|
@ -1,226 +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 bcrypt
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBcryptingIsEasy(t *testing.T) {
|
|
||||||
pass := []byte("mypassword")
|
|
||||||
hp, err := GenerateFromPassword(pass, 0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("GenerateFromPassword error: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if CompareHashAndPassword(hp, pass) != nil {
|
|
||||||
t.Errorf("%v should hash %s correctly", hp, pass)
|
|
||||||
}
|
|
||||||
|
|
||||||
notPass := "notthepass"
|
|
||||||
err = CompareHashAndPassword(hp, []byte(notPass))
|
|
||||||
if err != ErrMismatchedHashAndPassword {
|
|
||||||
t.Errorf("%v and %s should be mismatched", hp, notPass)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBcryptingIsCorrect(t *testing.T) {
|
|
||||||
pass := []byte("allmine")
|
|
||||||
salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
|
|
||||||
expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
|
|
||||||
|
|
||||||
hash, err := bcrypt(pass, 10, salt)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("bcrypt blew up: %v", err)
|
|
||||||
}
|
|
||||||
if !bytes.HasSuffix(expectedHash, hash) {
|
|
||||||
t.Errorf("%v should be the suffix of %v", hash, expectedHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
h, err := newFromHash(expectedHash)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unable to parse %s: %v", string(expectedHash), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is not the safe way to compare these hashes. We do this only for
|
|
||||||
// testing clarity. Use bcrypt.CompareHashAndPassword()
|
|
||||||
if err == nil && !bytes.Equal(expectedHash, h.Hash()) {
|
|
||||||
t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestVeryShortPasswords(t *testing.T) {
|
|
||||||
key := []byte("k")
|
|
||||||
salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
|
|
||||||
_, err := bcrypt(key, 10, salt)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("One byte key resulted in error: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTooLongPasswordsWork(t *testing.T) {
|
|
||||||
salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
|
|
||||||
// One byte over the usual 56 byte limit that blowfish has
|
|
||||||
tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456")
|
|
||||||
tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C")
|
|
||||||
hash, err := bcrypt(tooLongPass, 10, salt)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("bcrypt blew up on long password: %v", err)
|
|
||||||
}
|
|
||||||
if !bytes.HasSuffix(tooLongExpected, hash) {
|
|
||||||
t.Errorf("%v should be the suffix of %v", hash, tooLongExpected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type InvalidHashTest struct {
|
|
||||||
err error
|
|
||||||
hash []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
var invalidTests = []InvalidHashTest{
|
|
||||||
{ErrHashTooShort, []byte("$2a$10$fooo")},
|
|
||||||
{ErrHashTooShort, []byte("$2a")},
|
|
||||||
{HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
|
|
||||||
{InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
|
|
||||||
{InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInvalidHashErrors(t *testing.T) {
|
|
||||||
check := func(name string, expected, err error) {
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("%s: Should have returned an error", name)
|
|
||||||
}
|
|
||||||
if err != nil && err != expected {
|
|
||||||
t.Errorf("%s gave err %v but should have given %v", name, err, expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, iht := range invalidTests {
|
|
||||||
_, err := newFromHash(iht.hash)
|
|
||||||
check("newFromHash", iht.err, err)
|
|
||||||
err = CompareHashAndPassword(iht.hash, []byte("anything"))
|
|
||||||
check("CompareHashAndPassword", iht.err, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnpaddedBase64Encoding(t *testing.T) {
|
|
||||||
original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30}
|
|
||||||
encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe")
|
|
||||||
|
|
||||||
encoded := base64Encode(original)
|
|
||||||
|
|
||||||
if !bytes.Equal(encodedOriginal, encoded) {
|
|
||||||
t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal)
|
|
||||||
}
|
|
||||||
|
|
||||||
decoded, err := base64Decode(encodedOriginal)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("base64Decode blew up: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(decoded, original) {
|
|
||||||
t.Errorf("Decoded %v should have equaled %v", decoded, original)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCost(t *testing.T) {
|
|
||||||
suffix := "XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C"
|
|
||||||
for _, vers := range []string{"2a", "2"} {
|
|
||||||
for _, cost := range []int{4, 10} {
|
|
||||||
s := fmt.Sprintf("$%s$%02d$%s", vers, cost, suffix)
|
|
||||||
h := []byte(s)
|
|
||||||
actual, err := Cost(h)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Cost, error: %s", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if actual != cost {
|
|
||||||
t.Errorf("Cost, expected: %d, actual: %d", cost, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_, err := Cost([]byte("$a$a$" + suffix))
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("Cost, malformed but no error returned")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCostValidationInHash(t *testing.T) {
|
|
||||||
if testing.Short() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pass := []byte("mypassword")
|
|
||||||
|
|
||||||
for c := 0; c < MinCost; c++ {
|
|
||||||
p, _ := newFromPassword(pass, c)
|
|
||||||
if p.cost != DefaultCost {
|
|
||||||
t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p, _ := newFromPassword(pass, 14)
|
|
||||||
if p.cost != 14 {
|
|
||||||
t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost)
|
|
||||||
}
|
|
||||||
|
|
||||||
hp, _ := newFromHash(p.Hash())
|
|
||||||
if p.cost != hp.cost {
|
|
||||||
t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := newFromPassword(pass, 32)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf("newFromPassword: should return a cost error")
|
|
||||||
}
|
|
||||||
if err != InvalidCostError(32) {
|
|
||||||
t.Errorf("newFromPassword: should return cost error, got %#v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCostReturnsWithLeadingZeroes(t *testing.T) {
|
|
||||||
hp, _ := newFromPassword([]byte("abcdefgh"), 7)
|
|
||||||
cost := hp.Hash()[4:7]
|
|
||||||
expected := []byte("07$")
|
|
||||||
|
|
||||||
if !bytes.Equal(expected, cost) {
|
|
||||||
t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMinorNotRequired(t *testing.T) {
|
|
||||||
noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
|
|
||||||
h, err := newFromHash(noMinorHash)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("No minor hash blew up: %s", err)
|
|
||||||
}
|
|
||||||
if h.minor != 0 {
|
|
||||||
t.Errorf("Should leave minor version at 0, but was %d", h.minor)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(noMinorHash, h.Hash()) {
|
|
||||||
t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkEqual(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
passwd := []byte("somepasswordyoulike")
|
|
||||||
hash, _ := GenerateFromPassword(passwd, 10)
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
CompareHashAndPassword(hash, passwd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkGeneration(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
passwd := []byte("mylongpassword1234")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
GenerateFromPassword(passwd, 10)
|
|
||||||
}
|
|
||||||
}
|
|
159
vendor/golang.org/x/crypto/blowfish/block.go
generated
vendored
159
vendor/golang.org/x/crypto/blowfish/block.go
generated
vendored
|
@ -1,159 +0,0 @@
|
||||||
// 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 blowfish
|
|
||||||
|
|
||||||
// getNextWord returns the next big-endian uint32 value from the byte slice
|
|
||||||
// at the given position in a circular manner, updating the position.
|
|
||||||
func getNextWord(b []byte, pos *int) uint32 {
|
|
||||||
var w uint32
|
|
||||||
j := *pos
|
|
||||||
for i := 0; i < 4; i++ {
|
|
||||||
w = w<<8 | uint32(b[j])
|
|
||||||
j++
|
|
||||||
if j >= len(b) {
|
|
||||||
j = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*pos = j
|
|
||||||
return w
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
|
|
||||||
// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
|
|
||||||
// pi and substitution tables for calls to Encrypt. This is used, primarily,
|
|
||||||
// by the bcrypt package to reuse the Blowfish key schedule during its
|
|
||||||
// set up. It's unlikely that you need to use this directly.
|
|
||||||
func ExpandKey(key []byte, c *Cipher) {
|
|
||||||
j := 0
|
|
||||||
for i := 0; i < 18; i++ {
|
|
||||||
// Using inlined getNextWord for performance.
|
|
||||||
var d uint32
|
|
||||||
for k := 0; k < 4; k++ {
|
|
||||||
d = d<<8 | uint32(key[j])
|
|
||||||
j++
|
|
||||||
if j >= len(key) {
|
|
||||||
j = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.p[i] ^= d
|
|
||||||
}
|
|
||||||
|
|
||||||
var l, r uint32
|
|
||||||
for i := 0; i < 18; i += 2 {
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.p[i], c.p[i+1] = l, r
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < 256; i += 2 {
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.s0[i], c.s0[i+1] = l, r
|
|
||||||
}
|
|
||||||
for i := 0; i < 256; i += 2 {
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.s1[i], c.s1[i+1] = l, r
|
|
||||||
}
|
|
||||||
for i := 0; i < 256; i += 2 {
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.s2[i], c.s2[i+1] = l, r
|
|
||||||
}
|
|
||||||
for i := 0; i < 256; i += 2 {
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.s3[i], c.s3[i+1] = l, r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is similar to ExpandKey, but folds the salt during the key
|
|
||||||
// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
|
|
||||||
// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
|
|
||||||
// and specializing it here is useful.
|
|
||||||
func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
|
|
||||||
j := 0
|
|
||||||
for i := 0; i < 18; i++ {
|
|
||||||
c.p[i] ^= getNextWord(key, &j)
|
|
||||||
}
|
|
||||||
|
|
||||||
j = 0
|
|
||||||
var l, r uint32
|
|
||||||
for i := 0; i < 18; i += 2 {
|
|
||||||
l ^= getNextWord(salt, &j)
|
|
||||||
r ^= getNextWord(salt, &j)
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.p[i], c.p[i+1] = l, r
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < 256; i += 2 {
|
|
||||||
l ^= getNextWord(salt, &j)
|
|
||||||
r ^= getNextWord(salt, &j)
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.s0[i], c.s0[i+1] = l, r
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < 256; i += 2 {
|
|
||||||
l ^= getNextWord(salt, &j)
|
|
||||||
r ^= getNextWord(salt, &j)
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.s1[i], c.s1[i+1] = l, r
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < 256; i += 2 {
|
|
||||||
l ^= getNextWord(salt, &j)
|
|
||||||
r ^= getNextWord(salt, &j)
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.s2[i], c.s2[i+1] = l, r
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < 256; i += 2 {
|
|
||||||
l ^= getNextWord(salt, &j)
|
|
||||||
r ^= getNextWord(salt, &j)
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
c.s3[i], c.s3[i+1] = l, r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
|
|
||||||
xl, xr := l, r
|
|
||||||
xl ^= c.p[0]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16]
|
|
||||||
xr ^= c.p[17]
|
|
||||||
return xr, xl
|
|
||||||
}
|
|
||||||
|
|
||||||
func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
|
|
||||||
xl, xr := l, r
|
|
||||||
xl ^= c.p[17]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3]
|
|
||||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2]
|
|
||||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1]
|
|
||||||
xr ^= c.p[0]
|
|
||||||
return xr, xl
|
|
||||||
}
|
|
274
vendor/golang.org/x/crypto/blowfish/blowfish_test.go
generated
vendored
274
vendor/golang.org/x/crypto/blowfish/blowfish_test.go
generated
vendored
|
@ -1,274 +0,0 @@
|
||||||
// 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 blowfish
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
type CryptTest struct {
|
|
||||||
key []byte
|
|
||||||
in []byte
|
|
||||||
out []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test vector values are from http://www.schneier.com/code/vectors.txt.
|
|
||||||
var encryptTests = []CryptTest{
|
|
||||||
{
|
|
||||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
[]byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
|
|
||||||
{
|
|
||||||
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
|
||||||
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
|
||||||
[]byte{0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A}},
|
|
||||||
{
|
|
||||||
[]byte{0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
[]byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
|
|
||||||
[]byte{0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2}},
|
|
||||||
{
|
|
||||||
[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
|
|
||||||
[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
|
|
||||||
[]byte{0x24, 0x66, 0xDD, 0x87, 0x8B, 0x96, 0x3C, 0x9D}},
|
|
||||||
|
|
||||||
{
|
|
||||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
|
||||||
[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
|
|
||||||
[]byte{0x61, 0xF9, 0xC3, 0x80, 0x22, 0x81, 0xB0, 0x96}},
|
|
||||||
{
|
|
||||||
[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
|
|
||||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
|
||||||
[]byte{0x7D, 0x0C, 0xC6, 0x30, 0xAF, 0xDA, 0x1E, 0xC7}},
|
|
||||||
{
|
|
||||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
[]byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
|
|
||||||
{
|
|
||||||
[]byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
|
|
||||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
|
||||||
[]byte{0x0A, 0xCE, 0xAB, 0x0F, 0xC6, 0xA0, 0xA2, 0x8D}},
|
|
||||||
{
|
|
||||||
[]byte{0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57},
|
|
||||||
[]byte{0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42},
|
|
||||||
[]byte{0x59, 0xC6, 0x82, 0x45, 0xEB, 0x05, 0x28, 0x2B}},
|
|
||||||
{
|
|
||||||
[]byte{0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E},
|
|
||||||
[]byte{0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA},
|
|
||||||
[]byte{0xB1, 0xB8, 0xCC, 0x0B, 0x25, 0x0F, 0x09, 0xA0}},
|
|
||||||
{
|
|
||||||
[]byte{0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86},
|
|
||||||
[]byte{0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72},
|
|
||||||
[]byte{0x17, 0x30, 0xE5, 0x77, 0x8B, 0xEA, 0x1D, 0xA4}},
|
|
||||||
{
|
|
||||||
[]byte{0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E},
|
|
||||||
[]byte{0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A},
|
|
||||||
[]byte{0xA2, 0x5E, 0x78, 0x56, 0xCF, 0x26, 0x51, 0xEB}},
|
|
||||||
{
|
|
||||||
[]byte{0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6},
|
|
||||||
[]byte{0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2},
|
|
||||||
[]byte{0x35, 0x38, 0x82, 0xB1, 0x09, 0xCE, 0x8F, 0x1A}},
|
|
||||||
{
|
|
||||||
[]byte{0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE},
|
|
||||||
[]byte{0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A},
|
|
||||||
[]byte{0x48, 0xF4, 0xD0, 0x88, 0x4C, 0x37, 0x99, 0x18}},
|
|
||||||
{
|
|
||||||
[]byte{0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6},
|
|
||||||
[]byte{0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2},
|
|
||||||
[]byte{0x43, 0x21, 0x93, 0xB7, 0x89, 0x51, 0xFC, 0x98}},
|
|
||||||
{
|
|
||||||
[]byte{0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE},
|
|
||||||
[]byte{0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A},
|
|
||||||
[]byte{0x13, 0xF0, 0x41, 0x54, 0xD6, 0x9D, 0x1A, 0xE5}},
|
|
||||||
{
|
|
||||||
[]byte{0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16},
|
|
||||||
[]byte{0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02},
|
|
||||||
[]byte{0x2E, 0xED, 0xDA, 0x93, 0xFF, 0xD3, 0x9C, 0x79}},
|
|
||||||
{
|
|
||||||
[]byte{0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F},
|
|
||||||
[]byte{0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A},
|
|
||||||
[]byte{0xD8, 0x87, 0xE0, 0x39, 0x3C, 0x2D, 0xA6, 0xE3}},
|
|
||||||
{
|
|
||||||
[]byte{0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46},
|
|
||||||
[]byte{0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32},
|
|
||||||
[]byte{0x5F, 0x99, 0xD0, 0x4F, 0x5B, 0x16, 0x39, 0x69}},
|
|
||||||
{
|
|
||||||
[]byte{0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E},
|
|
||||||
[]byte{0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA},
|
|
||||||
[]byte{0x4A, 0x05, 0x7A, 0x3B, 0x24, 0xD3, 0x97, 0x7B}},
|
|
||||||
{
|
|
||||||
[]byte{0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76},
|
|
||||||
[]byte{0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62},
|
|
||||||
[]byte{0x45, 0x20, 0x31, 0xC1, 0xE4, 0xFA, 0xDA, 0x8E}},
|
|
||||||
{
|
|
||||||
[]byte{0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07},
|
|
||||||
[]byte{0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2},
|
|
||||||
[]byte{0x75, 0x55, 0xAE, 0x39, 0xF5, 0x9B, 0x87, 0xBD}},
|
|
||||||
{
|
|
||||||
[]byte{0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F},
|
|
||||||
[]byte{0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA},
|
|
||||||
[]byte{0x53, 0xC5, 0x5F, 0x9C, 0xB4, 0x9F, 0xC0, 0x19}},
|
|
||||||
{
|
|
||||||
[]byte{0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7},
|
|
||||||
[]byte{0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92},
|
|
||||||
[]byte{0x7A, 0x8E, 0x7B, 0xFA, 0x93, 0x7E, 0x89, 0xA3}},
|
|
||||||
{
|
|
||||||
[]byte{0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF},
|
|
||||||
[]byte{0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A},
|
|
||||||
[]byte{0xCF, 0x9C, 0x5D, 0x7A, 0x49, 0x86, 0xAD, 0xB5}},
|
|
||||||
{
|
|
||||||
[]byte{0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6},
|
|
||||||
[]byte{0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2},
|
|
||||||
[]byte{0xD1, 0xAB, 0xB2, 0x90, 0x65, 0x8B, 0xC7, 0x78}},
|
|
||||||
{
|
|
||||||
[]byte{0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF},
|
|
||||||
[]byte{0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A},
|
|
||||||
[]byte{0x55, 0xCB, 0x37, 0x74, 0xD1, 0x3E, 0xF2, 0x01}},
|
|
||||||
{
|
|
||||||
[]byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
|
|
||||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
|
||||||
[]byte{0xFA, 0x34, 0xEC, 0x48, 0x47, 0xB2, 0x68, 0xB2}},
|
|
||||||
{
|
|
||||||
[]byte{0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E},
|
|
||||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
|
||||||
[]byte{0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE}},
|
|
||||||
{
|
|
||||||
[]byte{0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE},
|
|
||||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
|
||||||
[]byte{0xC3, 0x9E, 0x07, 0x2D, 0x9F, 0xAC, 0x63, 0x1D}},
|
|
||||||
{
|
|
||||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
|
||||||
[]byte{0x01, 0x49, 0x33, 0xE0, 0xCD, 0xAF, 0xF6, 0xE4}},
|
|
||||||
{
|
|
||||||
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
|
||||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
[]byte{0xF2, 0x1E, 0x9A, 0x77, 0xB7, 0x1C, 0x49, 0xBC}},
|
|
||||||
{
|
|
||||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
|
||||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
[]byte{0x24, 0x59, 0x46, 0x88, 0x57, 0x54, 0x36, 0x9A}},
|
|
||||||
{
|
|
||||||
[]byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
|
|
||||||
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
|
||||||
[]byte{0x6B, 0x5C, 0x5A, 0x9C, 0x5D, 0x9E, 0x0A, 0x5A}},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCipherEncrypt(t *testing.T) {
|
|
||||||
for i, tt := range encryptTests {
|
|
||||||
c, err := NewCipher(tt.key)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ct := make([]byte, len(tt.out))
|
|
||||||
c.Encrypt(ct, tt.in)
|
|
||||||
for j, v := range ct {
|
|
||||||
if v != tt.out[j] {
|
|
||||||
t.Errorf("Cipher.Encrypt, test vector #%d: cipher-text[%d] = %#x, expected %#x", i, j, v, tt.out[j])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCipherDecrypt(t *testing.T) {
|
|
||||||
for i, tt := range encryptTests {
|
|
||||||
c, err := NewCipher(tt.key)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
pt := make([]byte, len(tt.in))
|
|
||||||
c.Decrypt(pt, tt.out)
|
|
||||||
for j, v := range pt {
|
|
||||||
if v != tt.in[j] {
|
|
||||||
t.Errorf("Cipher.Decrypt, test vector #%d: plain-text[%d] = %#x, expected %#x", i, j, v, tt.in[j])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSaltedCipherKeyLength(t *testing.T) {
|
|
||||||
if _, err := NewSaltedCipher(nil, []byte{'a'}); err != KeySizeError(0) {
|
|
||||||
t.Errorf("NewSaltedCipher with short key, gave error %#v, expected %#v", err, KeySizeError(0))
|
|
||||||
}
|
|
||||||
|
|
||||||
// A 57-byte key. One over the typical blowfish restriction.
|
|
||||||
key := []byte("012345678901234567890123456789012345678901234567890123456")
|
|
||||||
if _, err := NewSaltedCipher(key, []byte{'a'}); err != nil {
|
|
||||||
t.Errorf("NewSaltedCipher with long key, gave error %#v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test vectors generated with Blowfish from OpenSSH.
|
|
||||||
var saltedVectors = [][8]byte{
|
|
||||||
{0x0c, 0x82, 0x3b, 0x7b, 0x8d, 0x01, 0x4b, 0x7e},
|
|
||||||
{0xd1, 0xe1, 0x93, 0xf0, 0x70, 0xa6, 0xdb, 0x12},
|
|
||||||
{0xfc, 0x5e, 0xba, 0xde, 0xcb, 0xf8, 0x59, 0xad},
|
|
||||||
{0x8a, 0x0c, 0x76, 0xe7, 0xdd, 0x2c, 0xd3, 0xa8},
|
|
||||||
{0x2c, 0xcb, 0x7b, 0xee, 0xac, 0x7b, 0x7f, 0xf8},
|
|
||||||
{0xbb, 0xf6, 0x30, 0x6f, 0xe1, 0x5d, 0x62, 0xbf},
|
|
||||||
{0x97, 0x1e, 0xc1, 0x3d, 0x3d, 0xe0, 0x11, 0xe9},
|
|
||||||
{0x06, 0xd7, 0x4d, 0xb1, 0x80, 0xa3, 0xb1, 0x38},
|
|
||||||
{0x67, 0xa1, 0xa9, 0x75, 0x0e, 0x5b, 0xc6, 0xb4},
|
|
||||||
{0x51, 0x0f, 0x33, 0x0e, 0x4f, 0x67, 0xd2, 0x0c},
|
|
||||||
{0xf1, 0x73, 0x7e, 0xd8, 0x44, 0xea, 0xdb, 0xe5},
|
|
||||||
{0x14, 0x0e, 0x16, 0xce, 0x7f, 0x4a, 0x9c, 0x7b},
|
|
||||||
{0x4b, 0xfe, 0x43, 0xfd, 0xbf, 0x36, 0x04, 0x47},
|
|
||||||
{0xb1, 0xeb, 0x3e, 0x15, 0x36, 0xa7, 0xbb, 0xe2},
|
|
||||||
{0x6d, 0x0b, 0x41, 0xdd, 0x00, 0x98, 0x0b, 0x19},
|
|
||||||
{0xd3, 0xce, 0x45, 0xce, 0x1d, 0x56, 0xb7, 0xfc},
|
|
||||||
{0xd9, 0xf0, 0xfd, 0xda, 0xc0, 0x23, 0xb7, 0x93},
|
|
||||||
{0x4c, 0x6f, 0xa1, 0xe4, 0x0c, 0xa8, 0xca, 0x57},
|
|
||||||
{0xe6, 0x2f, 0x28, 0xa7, 0x0c, 0x94, 0x0d, 0x08},
|
|
||||||
{0x8f, 0xe3, 0xf0, 0xb6, 0x29, 0xe3, 0x44, 0x03},
|
|
||||||
{0xff, 0x98, 0xdd, 0x04, 0x45, 0xb4, 0x6d, 0x1f},
|
|
||||||
{0x9e, 0x45, 0x4d, 0x18, 0x40, 0x53, 0xdb, 0xef},
|
|
||||||
{0xb7, 0x3b, 0xef, 0x29, 0xbe, 0xa8, 0x13, 0x71},
|
|
||||||
{0x02, 0x54, 0x55, 0x41, 0x8e, 0x04, 0xfc, 0xad},
|
|
||||||
{0x6a, 0x0a, 0xee, 0x7c, 0x10, 0xd9, 0x19, 0xfe},
|
|
||||||
{0x0a, 0x22, 0xd9, 0x41, 0xcc, 0x23, 0x87, 0x13},
|
|
||||||
{0x6e, 0xff, 0x1f, 0xff, 0x36, 0x17, 0x9c, 0xbe},
|
|
||||||
{0x79, 0xad, 0xb7, 0x40, 0xf4, 0x9f, 0x51, 0xa6},
|
|
||||||
{0x97, 0x81, 0x99, 0xa4, 0xde, 0x9e, 0x9f, 0xb6},
|
|
||||||
{0x12, 0x19, 0x7a, 0x28, 0xd0, 0xdc, 0xcc, 0x92},
|
|
||||||
{0x81, 0xda, 0x60, 0x1e, 0x0e, 0xdd, 0x65, 0x56},
|
|
||||||
{0x7d, 0x76, 0x20, 0xb2, 0x73, 0xc9, 0x9e, 0xee},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSaltedCipher(t *testing.T) {
|
|
||||||
var key, salt [32]byte
|
|
||||||
for i := range key {
|
|
||||||
key[i] = byte(i)
|
|
||||||
salt[i] = byte(i + 32)
|
|
||||||
}
|
|
||||||
for i, v := range saltedVectors {
|
|
||||||
c, err := NewSaltedCipher(key[:], salt[:i])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
var buf [8]byte
|
|
||||||
c.Encrypt(buf[:], buf[:])
|
|
||||||
if v != buf {
|
|
||||||
t.Errorf("%d: expected %x, got %x", i, v, buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkExpandKeyWithSalt(b *testing.B) {
|
|
||||||
key := make([]byte, 32)
|
|
||||||
salt := make([]byte, 16)
|
|
||||||
c, _ := NewCipher(key)
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
expandKeyWithSalt(key, salt, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkExpandKey(b *testing.B) {
|
|
||||||
key := make([]byte, 32)
|
|
||||||
c, _ := NewCipher(key)
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
ExpandKey(key, c)
|
|
||||||
}
|
|
||||||
}
|
|
91
vendor/golang.org/x/crypto/blowfish/cipher.go
generated
vendored
91
vendor/golang.org/x/crypto/blowfish/cipher.go
generated
vendored
|
@ -1,91 +0,0 @@
|
||||||
// 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 blowfish implements Bruce Schneier's Blowfish encryption algorithm.
|
|
||||||
package blowfish // import "golang.org/x/crypto/blowfish"
|
|
||||||
|
|
||||||
// The code is a port of Bruce Schneier's C implementation.
|
|
||||||
// See http://www.schneier.com/blowfish.html.
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
// The Blowfish block size in bytes.
|
|
||||||
const BlockSize = 8
|
|
||||||
|
|
||||||
// A Cipher is an instance of Blowfish encryption using a particular key.
|
|
||||||
type Cipher struct {
|
|
||||||
p [18]uint32
|
|
||||||
s0, s1, s2, s3 [256]uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type KeySizeError int
|
|
||||||
|
|
||||||
func (k KeySizeError) Error() string {
|
|
||||||
return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCipher creates and returns a Cipher.
|
|
||||||
// The key argument should be the Blowfish key, from 1 to 56 bytes.
|
|
||||||
func NewCipher(key []byte) (*Cipher, error) {
|
|
||||||
var result Cipher
|
|
||||||
if k := len(key); k < 1 || k > 56 {
|
|
||||||
return nil, KeySizeError(k)
|
|
||||||
}
|
|
||||||
initCipher(&result)
|
|
||||||
ExpandKey(key, &result)
|
|
||||||
return &result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
|
|
||||||
// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
|
|
||||||
// sufficient and desirable. For bcrypt compatibility, the key can be over 56
|
|
||||||
// bytes.
|
|
||||||
func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
|
|
||||||
if len(salt) == 0 {
|
|
||||||
return NewCipher(key)
|
|
||||||
}
|
|
||||||
var result Cipher
|
|
||||||
if k := len(key); k < 1 {
|
|
||||||
return nil, KeySizeError(k)
|
|
||||||
}
|
|
||||||
initCipher(&result)
|
|
||||||
expandKeyWithSalt(key, salt, &result)
|
|
||||||
return &result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BlockSize returns the Blowfish block size, 8 bytes.
|
|
||||||
// It is necessary to satisfy the Block interface in the
|
|
||||||
// package "crypto/cipher".
|
|
||||||
func (c *Cipher) BlockSize() int { return BlockSize }
|
|
||||||
|
|
||||||
// Encrypt encrypts the 8-byte buffer src using the key k
|
|
||||||
// and stores the result in dst.
|
|
||||||
// Note that for amounts of data larger than a block,
|
|
||||||
// it is not safe to just call Encrypt on successive blocks;
|
|
||||||
// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
|
|
||||||
func (c *Cipher) Encrypt(dst, src []byte) {
|
|
||||||
l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
|
|
||||||
r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
|
|
||||||
l, r = encryptBlock(l, r, c)
|
|
||||||
dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
|
|
||||||
dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrypt decrypts the 8-byte buffer src using the key k
|
|
||||||
// and stores the result in dst.
|
|
||||||
func (c *Cipher) Decrypt(dst, src []byte) {
|
|
||||||
l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
|
|
||||||
r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
|
|
||||||
l, r = decryptBlock(l, r, c)
|
|
||||||
dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
|
|
||||||
dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func initCipher(c *Cipher) {
|
|
||||||
copy(c.p[0:], p[0:])
|
|
||||||
copy(c.s0[0:], s0[0:])
|
|
||||||
copy(c.s1[0:], s1[0:])
|
|
||||||
copy(c.s2[0:], s2[0:])
|
|
||||||
copy(c.s3[0:], s3[0:])
|
|
||||||
}
|
|
199
vendor/golang.org/x/crypto/blowfish/const.go
generated
vendored
199
vendor/golang.org/x/crypto/blowfish/const.go
generated
vendored
|
@ -1,199 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
// The startup permutation array and substitution boxes.
|
|
||||||
// They are the hexadecimal digits of PI; see:
|
|
||||||
// http://www.schneier.com/code/constants.txt.
|
|
||||||
|
|
||||||
package blowfish
|
|
||||||
|
|
||||||
var s0 = [256]uint32{
|
|
||||||
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
|
|
||||||
0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
|
|
||||||
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
|
|
||||||
0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
|
||||||
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
|
|
||||||
0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
|
|
||||||
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
|
|
||||||
0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
|
||||||
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
|
|
||||||
0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
|
|
||||||
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
|
|
||||||
0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
|
||||||
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
|
|
||||||
0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
|
|
||||||
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
|
|
||||||
0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
|
||||||
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
|
|
||||||
0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
|
|
||||||
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
|
|
||||||
0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
|
||||||
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
|
|
||||||
0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
|
|
||||||
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
|
|
||||||
0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
|
||||||
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
|
|
||||||
0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
|
|
||||||
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
|
|
||||||
0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
|
||||||
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
|
|
||||||
0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
|
|
||||||
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
|
|
||||||
0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
|
||||||
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
|
|
||||||
0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
|
|
||||||
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
|
|
||||||
0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
|
||||||
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
|
|
||||||
0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
|
|
||||||
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
|
|
||||||
0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
|
||||||
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
|
|
||||||
0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
|
|
||||||
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
|
|
||||||
}
|
|
||||||
|
|
||||||
var s1 = [256]uint32{
|
|
||||||
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
|
|
||||||
0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
|
|
||||||
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
|
|
||||||
0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
|
|
||||||
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
|
|
||||||
0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
|
|
||||||
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
|
|
||||||
0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
|
|
||||||
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
|
|
||||||
0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
|
|
||||||
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
|
|
||||||
0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
|
|
||||||
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
|
|
||||||
0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
|
|
||||||
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
|
|
||||||
0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
|
|
||||||
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
|
|
||||||
0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
|
|
||||||
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
|
|
||||||
0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
|
|
||||||
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
|
|
||||||
0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
|
|
||||||
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
|
|
||||||
0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
|
|
||||||
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
|
|
||||||
0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
|
|
||||||
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
|
|
||||||
0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
|
|
||||||
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
|
|
||||||
0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
|
|
||||||
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
|
|
||||||
0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
|
|
||||||
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
|
|
||||||
0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
|
|
||||||
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
|
|
||||||
0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
|
|
||||||
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
|
|
||||||
0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
|
|
||||||
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
|
|
||||||
0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
|
|
||||||
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
|
|
||||||
0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
|
|
||||||
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
|
|
||||||
}
|
|
||||||
|
|
||||||
var s2 = [256]uint32{
|
|
||||||
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
|
|
||||||
0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
|
|
||||||
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
|
|
||||||
0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
|
|
||||||
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
|
|
||||||
0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
|
|
||||||
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
|
|
||||||
0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
|
|
||||||
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
|
|
||||||
0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
|
|
||||||
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
|
|
||||||
0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
|
|
||||||
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
|
|
||||||
0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
|
|
||||||
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
|
|
||||||
0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
|
|
||||||
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
|
|
||||||
0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
|
|
||||||
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
|
|
||||||
0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
|
|
||||||
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
|
|
||||||
0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
|
|
||||||
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
|
|
||||||
0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
|
|
||||||
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
|
|
||||||
0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
|
|
||||||
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
|
|
||||||
0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
|
|
||||||
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
|
|
||||||
0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
|
|
||||||
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
|
|
||||||
0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
|
|
||||||
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
|
|
||||||
0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
|
|
||||||
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
|
|
||||||
0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
|
|
||||||
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
|
|
||||||
0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
|
|
||||||
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
|
|
||||||
0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
|
|
||||||
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
|
|
||||||
0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
|
|
||||||
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
|
|
||||||
}
|
|
||||||
|
|
||||||
var s3 = [256]uint32{
|
|
||||||
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
|
|
||||||
0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
|
|
||||||
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
|
|
||||||
0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
|
||||||
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
|
|
||||||
0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
|
|
||||||
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
|
|
||||||
0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
|
||||||
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
|
|
||||||
0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
|
|
||||||
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
|
|
||||||
0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
|
||||||
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
|
|
||||||
0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
|
|
||||||
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
|
|
||||||
0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
|
||||||
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
|
|
||||||
0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
|
|
||||||
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
|
|
||||||
0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
|
||||||
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
|
|
||||||
0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
|
|
||||||
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
|
|
||||||
0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
|
||||||
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
|
|
||||||
0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
|
|
||||||
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
|
|
||||||
0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
|
||||||
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
|
|
||||||
0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
|
|
||||||
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
|
|
||||||
0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
|
||||||
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
|
|
||||||
0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
|
|
||||||
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
|
|
||||||
0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
|
||||||
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
|
|
||||||
0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
|
|
||||||
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
|
|
||||||
0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
|
||||||
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
|
|
||||||
0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
|
|
||||||
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
|
|
||||||
}
|
|
||||||
|
|
||||||
var p = [18]uint32{
|
|
||||||
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
|
|
||||||
0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
|
|
||||||
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
|
|
||||||
}
|
|
404
vendor/golang.org/x/crypto/bn256/bn256.go
generated
vendored
404
vendor/golang.org/x/crypto/bn256/bn256.go
generated
vendored
|
@ -1,404 +0,0 @@
|
||||||
// Copyright 2012 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 bn256 implements a particular bilinear group at the 128-bit security level.
|
|
||||||
//
|
|
||||||
// Bilinear groups are the basis of many of the new cryptographic protocols
|
|
||||||
// that have been proposed over the past decade. They consist of a triplet of
|
|
||||||
// groups (G₁, G₂ and GT) such that there exists a function e(g₁ˣ,g₂ʸ)=gTˣʸ
|
|
||||||
// (where gₓ is a generator of the respective group). That function is called
|
|
||||||
// a pairing function.
|
|
||||||
//
|
|
||||||
// This package specifically implements the Optimal Ate pairing over a 256-bit
|
|
||||||
// Barreto-Naehrig curve as described in
|
|
||||||
// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible
|
|
||||||
// with the implementation described in that paper.
|
|
||||||
package bn256 // import "golang.org/x/crypto/bn256"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"io"
|
|
||||||
"math/big"
|
|
||||||
)
|
|
||||||
|
|
||||||
// BUG(agl): this implementation is not constant time.
|
|
||||||
// TODO(agl): keep GF(p²) elements in Mongomery form.
|
|
||||||
|
|
||||||
// G1 is an abstract cyclic group. The zero value is suitable for use as the
|
|
||||||
// output of an operation, but cannot be used as an input.
|
|
||||||
type G1 struct {
|
|
||||||
p *curvePoint
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomG1 returns x and g₁ˣ where x is a random, non-zero number read from r.
|
|
||||||
func RandomG1(r io.Reader) (*big.Int, *G1, error) {
|
|
||||||
var k *big.Int
|
|
||||||
var err error
|
|
||||||
|
|
||||||
for {
|
|
||||||
k, err = rand.Int(r, Order)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
if k.Sign() > 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return k, new(G1).ScalarBaseMult(k), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *G1) String() string {
|
|
||||||
return "bn256.G1" + g.p.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScalarBaseMult sets e to g*k where g is the generator of the group and
|
|
||||||
// then returns e.
|
|
||||||
func (e *G1) ScalarBaseMult(k *big.Int) *G1 {
|
|
||||||
if e.p == nil {
|
|
||||||
e.p = newCurvePoint(nil)
|
|
||||||
}
|
|
||||||
e.p.Mul(curveGen, k, new(bnPool))
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScalarMult sets e to a*k and then returns e.
|
|
||||||
func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 {
|
|
||||||
if e.p == nil {
|
|
||||||
e.p = newCurvePoint(nil)
|
|
||||||
}
|
|
||||||
e.p.Mul(a.p, k, new(bnPool))
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add sets e to a+b and then returns e.
|
|
||||||
// BUG(agl): this function is not complete: a==b fails.
|
|
||||||
func (e *G1) Add(a, b *G1) *G1 {
|
|
||||||
if e.p == nil {
|
|
||||||
e.p = newCurvePoint(nil)
|
|
||||||
}
|
|
||||||
e.p.Add(a.p, b.p, new(bnPool))
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// Neg sets e to -a and then returns e.
|
|
||||||
func (e *G1) Neg(a *G1) *G1 {
|
|
||||||
if e.p == nil {
|
|
||||||
e.p = newCurvePoint(nil)
|
|
||||||
}
|
|
||||||
e.p.Negative(a.p)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// Marshal converts n to a byte slice.
|
|
||||||
func (n *G1) Marshal() []byte {
|
|
||||||
n.p.MakeAffine(nil)
|
|
||||||
|
|
||||||
xBytes := new(big.Int).Mod(n.p.x, p).Bytes()
|
|
||||||
yBytes := new(big.Int).Mod(n.p.y, p).Bytes()
|
|
||||||
|
|
||||||
// Each value is a 256-bit number.
|
|
||||||
const numBytes = 256 / 8
|
|
||||||
|
|
||||||
ret := make([]byte, numBytes*2)
|
|
||||||
copy(ret[1*numBytes-len(xBytes):], xBytes)
|
|
||||||
copy(ret[2*numBytes-len(yBytes):], yBytes)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal sets e to the result of converting the output of Marshal back into
|
|
||||||
// a group element and then returns e.
|
|
||||||
func (e *G1) Unmarshal(m []byte) (*G1, bool) {
|
|
||||||
// Each value is a 256-bit number.
|
|
||||||
const numBytes = 256 / 8
|
|
||||||
|
|
||||||
if len(m) != 2*numBytes {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
if e.p == nil {
|
|
||||||
e.p = newCurvePoint(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
e.p.x.SetBytes(m[0*numBytes : 1*numBytes])
|
|
||||||
e.p.y.SetBytes(m[1*numBytes : 2*numBytes])
|
|
||||||
|
|
||||||
if e.p.x.Sign() == 0 && e.p.y.Sign() == 0 {
|
|
||||||
// This is the point at infinity.
|
|
||||||
e.p.y.SetInt64(1)
|
|
||||||
e.p.z.SetInt64(0)
|
|
||||||
e.p.t.SetInt64(0)
|
|
||||||
} else {
|
|
||||||
e.p.z.SetInt64(1)
|
|
||||||
e.p.t.SetInt64(1)
|
|
||||||
|
|
||||||
if !e.p.IsOnCurve() {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return e, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// G2 is an abstract cyclic group. The zero value is suitable for use as the
|
|
||||||
// output of an operation, but cannot be used as an input.
|
|
||||||
type G2 struct {
|
|
||||||
p *twistPoint
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomG1 returns x and g₂ˣ where x is a random, non-zero number read from r.
|
|
||||||
func RandomG2(r io.Reader) (*big.Int, *G2, error) {
|
|
||||||
var k *big.Int
|
|
||||||
var err error
|
|
||||||
|
|
||||||
for {
|
|
||||||
k, err = rand.Int(r, Order)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
if k.Sign() > 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return k, new(G2).ScalarBaseMult(k), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *G2) String() string {
|
|
||||||
return "bn256.G2" + g.p.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScalarBaseMult sets e to g*k where g is the generator of the group and
|
|
||||||
// then returns out.
|
|
||||||
func (e *G2) ScalarBaseMult(k *big.Int) *G2 {
|
|
||||||
if e.p == nil {
|
|
||||||
e.p = newTwistPoint(nil)
|
|
||||||
}
|
|
||||||
e.p.Mul(twistGen, k, new(bnPool))
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScalarMult sets e to a*k and then returns e.
|
|
||||||
func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 {
|
|
||||||
if e.p == nil {
|
|
||||||
e.p = newTwistPoint(nil)
|
|
||||||
}
|
|
||||||
e.p.Mul(a.p, k, new(bnPool))
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add sets e to a+b and then returns e.
|
|
||||||
// BUG(agl): this function is not complete: a==b fails.
|
|
||||||
func (e *G2) Add(a, b *G2) *G2 {
|
|
||||||
if e.p == nil {
|
|
||||||
e.p = newTwistPoint(nil)
|
|
||||||
}
|
|
||||||
e.p.Add(a.p, b.p, new(bnPool))
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// Marshal converts n into a byte slice.
|
|
||||||
func (n *G2) Marshal() []byte {
|
|
||||||
n.p.MakeAffine(nil)
|
|
||||||
|
|
||||||
xxBytes := new(big.Int).Mod(n.p.x.x, p).Bytes()
|
|
||||||
xyBytes := new(big.Int).Mod(n.p.x.y, p).Bytes()
|
|
||||||
yxBytes := new(big.Int).Mod(n.p.y.x, p).Bytes()
|
|
||||||
yyBytes := new(big.Int).Mod(n.p.y.y, p).Bytes()
|
|
||||||
|
|
||||||
// Each value is a 256-bit number.
|
|
||||||
const numBytes = 256 / 8
|
|
||||||
|
|
||||||
ret := make([]byte, numBytes*4)
|
|
||||||
copy(ret[1*numBytes-len(xxBytes):], xxBytes)
|
|
||||||
copy(ret[2*numBytes-len(xyBytes):], xyBytes)
|
|
||||||
copy(ret[3*numBytes-len(yxBytes):], yxBytes)
|
|
||||||
copy(ret[4*numBytes-len(yyBytes):], yyBytes)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal sets e to the result of converting the output of Marshal back into
|
|
||||||
// a group element and then returns e.
|
|
||||||
func (e *G2) Unmarshal(m []byte) (*G2, bool) {
|
|
||||||
// Each value is a 256-bit number.
|
|
||||||
const numBytes = 256 / 8
|
|
||||||
|
|
||||||
if len(m) != 4*numBytes {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
if e.p == nil {
|
|
||||||
e.p = newTwistPoint(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
e.p.x.x.SetBytes(m[0*numBytes : 1*numBytes])
|
|
||||||
e.p.x.y.SetBytes(m[1*numBytes : 2*numBytes])
|
|
||||||
e.p.y.x.SetBytes(m[2*numBytes : 3*numBytes])
|
|
||||||
e.p.y.y.SetBytes(m[3*numBytes : 4*numBytes])
|
|
||||||
|
|
||||||
if e.p.x.x.Sign() == 0 &&
|
|
||||||
e.p.x.y.Sign() == 0 &&
|
|
||||||
e.p.y.x.Sign() == 0 &&
|
|
||||||
e.p.y.y.Sign() == 0 {
|
|
||||||
// This is the point at infinity.
|
|
||||||
e.p.y.SetOne()
|
|
||||||
e.p.z.SetZero()
|
|
||||||
e.p.t.SetZero()
|
|
||||||
} else {
|
|
||||||
e.p.z.SetOne()
|
|
||||||
e.p.t.SetOne()
|
|
||||||
|
|
||||||
if !e.p.IsOnCurve() {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return e, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// GT is an abstract cyclic group. The zero value is suitable for use as the
|
|
||||||
// output of an operation, but cannot be used as an input.
|
|
||||||
type GT struct {
|
|
||||||
p *gfP12
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GT) String() string {
|
|
||||||
return "bn256.GT" + g.p.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScalarMult sets e to a*k and then returns e.
|
|
||||||
func (e *GT) ScalarMult(a *GT, k *big.Int) *GT {
|
|
||||||
if e.p == nil {
|
|
||||||
e.p = newGFp12(nil)
|
|
||||||
}
|
|
||||||
e.p.Exp(a.p, k, new(bnPool))
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add sets e to a+b and then returns e.
|
|
||||||
func (e *GT) Add(a, b *GT) *GT {
|
|
||||||
if e.p == nil {
|
|
||||||
e.p = newGFp12(nil)
|
|
||||||
}
|
|
||||||
e.p.Mul(a.p, b.p, new(bnPool))
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// Neg sets e to -a and then returns e.
|
|
||||||
func (e *GT) Neg(a *GT) *GT {
|
|
||||||
if e.p == nil {
|
|
||||||
e.p = newGFp12(nil)
|
|
||||||
}
|
|
||||||
e.p.Invert(a.p, new(bnPool))
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// Marshal converts n into a byte slice.
|
|
||||||
func (n *GT) Marshal() []byte {
|
|
||||||
n.p.Minimal()
|
|
||||||
|
|
||||||
xxxBytes := n.p.x.x.x.Bytes()
|
|
||||||
xxyBytes := n.p.x.x.y.Bytes()
|
|
||||||
xyxBytes := n.p.x.y.x.Bytes()
|
|
||||||
xyyBytes := n.p.x.y.y.Bytes()
|
|
||||||
xzxBytes := n.p.x.z.x.Bytes()
|
|
||||||
xzyBytes := n.p.x.z.y.Bytes()
|
|
||||||
yxxBytes := n.p.y.x.x.Bytes()
|
|
||||||
yxyBytes := n.p.y.x.y.Bytes()
|
|
||||||
yyxBytes := n.p.y.y.x.Bytes()
|
|
||||||
yyyBytes := n.p.y.y.y.Bytes()
|
|
||||||
yzxBytes := n.p.y.z.x.Bytes()
|
|
||||||
yzyBytes := n.p.y.z.y.Bytes()
|
|
||||||
|
|
||||||
// Each value is a 256-bit number.
|
|
||||||
const numBytes = 256 / 8
|
|
||||||
|
|
||||||
ret := make([]byte, numBytes*12)
|
|
||||||
copy(ret[1*numBytes-len(xxxBytes):], xxxBytes)
|
|
||||||
copy(ret[2*numBytes-len(xxyBytes):], xxyBytes)
|
|
||||||
copy(ret[3*numBytes-len(xyxBytes):], xyxBytes)
|
|
||||||
copy(ret[4*numBytes-len(xyyBytes):], xyyBytes)
|
|
||||||
copy(ret[5*numBytes-len(xzxBytes):], xzxBytes)
|
|
||||||
copy(ret[6*numBytes-len(xzyBytes):], xzyBytes)
|
|
||||||
copy(ret[7*numBytes-len(yxxBytes):], yxxBytes)
|
|
||||||
copy(ret[8*numBytes-len(yxyBytes):], yxyBytes)
|
|
||||||
copy(ret[9*numBytes-len(yyxBytes):], yyxBytes)
|
|
||||||
copy(ret[10*numBytes-len(yyyBytes):], yyyBytes)
|
|
||||||
copy(ret[11*numBytes-len(yzxBytes):], yzxBytes)
|
|
||||||
copy(ret[12*numBytes-len(yzyBytes):], yzyBytes)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal sets e to the result of converting the output of Marshal back into
|
|
||||||
// a group element and then returns e.
|
|
||||||
func (e *GT) Unmarshal(m []byte) (*GT, bool) {
|
|
||||||
// Each value is a 256-bit number.
|
|
||||||
const numBytes = 256 / 8
|
|
||||||
|
|
||||||
if len(m) != 12*numBytes {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
if e.p == nil {
|
|
||||||
e.p = newGFp12(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
e.p.x.x.x.SetBytes(m[0*numBytes : 1*numBytes])
|
|
||||||
e.p.x.x.y.SetBytes(m[1*numBytes : 2*numBytes])
|
|
||||||
e.p.x.y.x.SetBytes(m[2*numBytes : 3*numBytes])
|
|
||||||
e.p.x.y.y.SetBytes(m[3*numBytes : 4*numBytes])
|
|
||||||
e.p.x.z.x.SetBytes(m[4*numBytes : 5*numBytes])
|
|
||||||
e.p.x.z.y.SetBytes(m[5*numBytes : 6*numBytes])
|
|
||||||
e.p.y.x.x.SetBytes(m[6*numBytes : 7*numBytes])
|
|
||||||
e.p.y.x.y.SetBytes(m[7*numBytes : 8*numBytes])
|
|
||||||
e.p.y.y.x.SetBytes(m[8*numBytes : 9*numBytes])
|
|
||||||
e.p.y.y.y.SetBytes(m[9*numBytes : 10*numBytes])
|
|
||||||
e.p.y.z.x.SetBytes(m[10*numBytes : 11*numBytes])
|
|
||||||
e.p.y.z.y.SetBytes(m[11*numBytes : 12*numBytes])
|
|
||||||
|
|
||||||
return e, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pair calculates an Optimal Ate pairing.
|
|
||||||
func Pair(g1 *G1, g2 *G2) *GT {
|
|
||||||
return >{optimalAte(g2.p, g1.p, new(bnPool))}
|
|
||||||
}
|
|
||||||
|
|
||||||
// bnPool implements a tiny cache of *big.Int objects that's used to reduce the
|
|
||||||
// number of allocations made during processing.
|
|
||||||
type bnPool struct {
|
|
||||||
bns []*big.Int
|
|
||||||
count int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pool *bnPool) Get() *big.Int {
|
|
||||||
if pool == nil {
|
|
||||||
return new(big.Int)
|
|
||||||
}
|
|
||||||
|
|
||||||
pool.count++
|
|
||||||
l := len(pool.bns)
|
|
||||||
if l == 0 {
|
|
||||||
return new(big.Int)
|
|
||||||
}
|
|
||||||
|
|
||||||
bn := pool.bns[l-1]
|
|
||||||
pool.bns = pool.bns[:l-1]
|
|
||||||
return bn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pool *bnPool) Put(bn *big.Int) {
|
|
||||||
if pool == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pool.bns = append(pool.bns, bn)
|
|
||||||
pool.count--
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pool *bnPool) Count() int {
|
|
||||||
return pool.count
|
|
||||||
}
|
|
304
vendor/golang.org/x/crypto/bn256/bn256_test.go
generated
vendored
304
vendor/golang.org/x/crypto/bn256/bn256_test.go
generated
vendored
|
@ -1,304 +0,0 @@
|
||||||
// Copyright 2012 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 bn256
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
|
||||||
"math/big"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGFp2Invert(t *testing.T) {
|
|
||||||
pool := new(bnPool)
|
|
||||||
|
|
||||||
a := newGFp2(pool)
|
|
||||||
a.x.SetString("23423492374", 10)
|
|
||||||
a.y.SetString("12934872398472394827398470", 10)
|
|
||||||
|
|
||||||
inv := newGFp2(pool)
|
|
||||||
inv.Invert(a, pool)
|
|
||||||
|
|
||||||
b := newGFp2(pool).Mul(inv, a, pool)
|
|
||||||
if b.x.Int64() != 0 || b.y.Int64() != 1 {
|
|
||||||
t.Fatalf("bad result for a^-1*a: %s %s", b.x, b.y)
|
|
||||||
}
|
|
||||||
|
|
||||||
a.Put(pool)
|
|
||||||
b.Put(pool)
|
|
||||||
inv.Put(pool)
|
|
||||||
|
|
||||||
if c := pool.Count(); c > 0 {
|
|
||||||
t.Errorf("Pool count non-zero: %d\n", c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isZero(n *big.Int) bool {
|
|
||||||
return new(big.Int).Mod(n, p).Int64() == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func isOne(n *big.Int) bool {
|
|
||||||
return new(big.Int).Mod(n, p).Int64() == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGFp6Invert(t *testing.T) {
|
|
||||||
pool := new(bnPool)
|
|
||||||
|
|
||||||
a := newGFp6(pool)
|
|
||||||
a.x.x.SetString("239487238491", 10)
|
|
||||||
a.x.y.SetString("2356249827341", 10)
|
|
||||||
a.y.x.SetString("082659782", 10)
|
|
||||||
a.y.y.SetString("182703523765", 10)
|
|
||||||
a.z.x.SetString("978236549263", 10)
|
|
||||||
a.z.y.SetString("64893242", 10)
|
|
||||||
|
|
||||||
inv := newGFp6(pool)
|
|
||||||
inv.Invert(a, pool)
|
|
||||||
|
|
||||||
b := newGFp6(pool).Mul(inv, a, pool)
|
|
||||||
if !isZero(b.x.x) ||
|
|
||||||
!isZero(b.x.y) ||
|
|
||||||
!isZero(b.y.x) ||
|
|
||||||
!isZero(b.y.y) ||
|
|
||||||
!isZero(b.z.x) ||
|
|
||||||
!isOne(b.z.y) {
|
|
||||||
t.Fatalf("bad result for a^-1*a: %s", b)
|
|
||||||
}
|
|
||||||
|
|
||||||
a.Put(pool)
|
|
||||||
b.Put(pool)
|
|
||||||
inv.Put(pool)
|
|
||||||
|
|
||||||
if c := pool.Count(); c > 0 {
|
|
||||||
t.Errorf("Pool count non-zero: %d\n", c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGFp12Invert(t *testing.T) {
|
|
||||||
pool := new(bnPool)
|
|
||||||
|
|
||||||
a := newGFp12(pool)
|
|
||||||
a.x.x.x.SetString("239846234862342323958623", 10)
|
|
||||||
a.x.x.y.SetString("2359862352529835623", 10)
|
|
||||||
a.x.y.x.SetString("928836523", 10)
|
|
||||||
a.x.y.y.SetString("9856234", 10)
|
|
||||||
a.x.z.x.SetString("235635286", 10)
|
|
||||||
a.x.z.y.SetString("5628392833", 10)
|
|
||||||
a.y.x.x.SetString("252936598265329856238956532167968", 10)
|
|
||||||
a.y.x.y.SetString("23596239865236954178968", 10)
|
|
||||||
a.y.y.x.SetString("95421692834", 10)
|
|
||||||
a.y.y.y.SetString("236548", 10)
|
|
||||||
a.y.z.x.SetString("924523", 10)
|
|
||||||
a.y.z.y.SetString("12954623", 10)
|
|
||||||
|
|
||||||
inv := newGFp12(pool)
|
|
||||||
inv.Invert(a, pool)
|
|
||||||
|
|
||||||
b := newGFp12(pool).Mul(inv, a, pool)
|
|
||||||
if !isZero(b.x.x.x) ||
|
|
||||||
!isZero(b.x.x.y) ||
|
|
||||||
!isZero(b.x.y.x) ||
|
|
||||||
!isZero(b.x.y.y) ||
|
|
||||||
!isZero(b.x.z.x) ||
|
|
||||||
!isZero(b.x.z.y) ||
|
|
||||||
!isZero(b.y.x.x) ||
|
|
||||||
!isZero(b.y.x.y) ||
|
|
||||||
!isZero(b.y.y.x) ||
|
|
||||||
!isZero(b.y.y.y) ||
|
|
||||||
!isZero(b.y.z.x) ||
|
|
||||||
!isOne(b.y.z.y) {
|
|
||||||
t.Fatalf("bad result for a^-1*a: %s", b)
|
|
||||||
}
|
|
||||||
|
|
||||||
a.Put(pool)
|
|
||||||
b.Put(pool)
|
|
||||||
inv.Put(pool)
|
|
||||||
|
|
||||||
if c := pool.Count(); c > 0 {
|
|
||||||
t.Errorf("Pool count non-zero: %d\n", c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCurveImpl(t *testing.T) {
|
|
||||||
pool := new(bnPool)
|
|
||||||
|
|
||||||
g := &curvePoint{
|
|
||||||
pool.Get().SetInt64(1),
|
|
||||||
pool.Get().SetInt64(-2),
|
|
||||||
pool.Get().SetInt64(1),
|
|
||||||
pool.Get().SetInt64(0),
|
|
||||||
}
|
|
||||||
|
|
||||||
x := pool.Get().SetInt64(32498273234)
|
|
||||||
X := newCurvePoint(pool).Mul(g, x, pool)
|
|
||||||
|
|
||||||
y := pool.Get().SetInt64(98732423523)
|
|
||||||
Y := newCurvePoint(pool).Mul(g, y, pool)
|
|
||||||
|
|
||||||
s1 := newCurvePoint(pool).Mul(X, y, pool).MakeAffine(pool)
|
|
||||||
s2 := newCurvePoint(pool).Mul(Y, x, pool).MakeAffine(pool)
|
|
||||||
|
|
||||||
if s1.x.Cmp(s2.x) != 0 ||
|
|
||||||
s2.x.Cmp(s1.x) != 0 {
|
|
||||||
t.Errorf("DH points don't match: (%s, %s) (%s, %s)", s1.x, s1.y, s2.x, s2.y)
|
|
||||||
}
|
|
||||||
|
|
||||||
pool.Put(x)
|
|
||||||
X.Put(pool)
|
|
||||||
pool.Put(y)
|
|
||||||
Y.Put(pool)
|
|
||||||
s1.Put(pool)
|
|
||||||
s2.Put(pool)
|
|
||||||
g.Put(pool)
|
|
||||||
|
|
||||||
if c := pool.Count(); c > 0 {
|
|
||||||
t.Errorf("Pool count non-zero: %d\n", c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOrderG1(t *testing.T) {
|
|
||||||
g := new(G1).ScalarBaseMult(Order)
|
|
||||||
if !g.p.IsInfinity() {
|
|
||||||
t.Error("G1 has incorrect order")
|
|
||||||
}
|
|
||||||
|
|
||||||
one := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1))
|
|
||||||
g.Add(g, one)
|
|
||||||
g.p.MakeAffine(nil)
|
|
||||||
if g.p.x.Cmp(one.p.x) != 0 || g.p.y.Cmp(one.p.y) != 0 {
|
|
||||||
t.Errorf("1+0 != 1 in G1")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOrderG2(t *testing.T) {
|
|
||||||
g := new(G2).ScalarBaseMult(Order)
|
|
||||||
if !g.p.IsInfinity() {
|
|
||||||
t.Error("G2 has incorrect order")
|
|
||||||
}
|
|
||||||
|
|
||||||
one := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1))
|
|
||||||
g.Add(g, one)
|
|
||||||
g.p.MakeAffine(nil)
|
|
||||||
if g.p.x.x.Cmp(one.p.x.x) != 0 ||
|
|
||||||
g.p.x.y.Cmp(one.p.x.y) != 0 ||
|
|
||||||
g.p.y.x.Cmp(one.p.y.x) != 0 ||
|
|
||||||
g.p.y.y.Cmp(one.p.y.y) != 0 {
|
|
||||||
t.Errorf("1+0 != 1 in G2")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOrderGT(t *testing.T) {
|
|
||||||
gt := Pair(&G1{curveGen}, &G2{twistGen})
|
|
||||||
g := new(GT).ScalarMult(gt, Order)
|
|
||||||
if !g.p.IsOne() {
|
|
||||||
t.Error("GT has incorrect order")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBilinearity(t *testing.T) {
|
|
||||||
for i := 0; i < 2; i++ {
|
|
||||||
a, p1, _ := RandomG1(rand.Reader)
|
|
||||||
b, p2, _ := RandomG2(rand.Reader)
|
|
||||||
e1 := Pair(p1, p2)
|
|
||||||
|
|
||||||
e2 := Pair(&G1{curveGen}, &G2{twistGen})
|
|
||||||
e2.ScalarMult(e2, a)
|
|
||||||
e2.ScalarMult(e2, b)
|
|
||||||
|
|
||||||
minusE2 := new(GT).Neg(e2)
|
|
||||||
e1.Add(e1, minusE2)
|
|
||||||
|
|
||||||
if !e1.p.IsOne() {
|
|
||||||
t.Fatalf("bad pairing result: %s", e1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestG1Marshal(t *testing.T) {
|
|
||||||
g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1))
|
|
||||||
form := g.Marshal()
|
|
||||||
_, ok := new(G1).Unmarshal(form)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("failed to unmarshal")
|
|
||||||
}
|
|
||||||
|
|
||||||
g.ScalarBaseMult(Order)
|
|
||||||
form = g.Marshal()
|
|
||||||
g2, ok := new(G1).Unmarshal(form)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("failed to unmarshal ∞")
|
|
||||||
}
|
|
||||||
if !g2.p.IsInfinity() {
|
|
||||||
t.Fatalf("∞ unmarshaled incorrectly")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestG2Marshal(t *testing.T) {
|
|
||||||
g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1))
|
|
||||||
form := g.Marshal()
|
|
||||||
_, ok := new(G2).Unmarshal(form)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("failed to unmarshal")
|
|
||||||
}
|
|
||||||
|
|
||||||
g.ScalarBaseMult(Order)
|
|
||||||
form = g.Marshal()
|
|
||||||
g2, ok := new(G2).Unmarshal(form)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("failed to unmarshal ∞")
|
|
||||||
}
|
|
||||||
if !g2.p.IsInfinity() {
|
|
||||||
t.Fatalf("∞ unmarshaled incorrectly")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestG1Identity(t *testing.T) {
|
|
||||||
g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(0))
|
|
||||||
if !g.p.IsInfinity() {
|
|
||||||
t.Error("failure")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestG2Identity(t *testing.T) {
|
|
||||||
g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(0))
|
|
||||||
if !g.p.IsInfinity() {
|
|
||||||
t.Error("failure")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTripartiteDiffieHellman(t *testing.T) {
|
|
||||||
a, _ := rand.Int(rand.Reader, Order)
|
|
||||||
b, _ := rand.Int(rand.Reader, Order)
|
|
||||||
c, _ := rand.Int(rand.Reader, Order)
|
|
||||||
|
|
||||||
pa, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(a).Marshal())
|
|
||||||
qa, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(a).Marshal())
|
|
||||||
pb, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(b).Marshal())
|
|
||||||
qb, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(b).Marshal())
|
|
||||||
pc, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(c).Marshal())
|
|
||||||
qc, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(c).Marshal())
|
|
||||||
|
|
||||||
k1 := Pair(pb, qc)
|
|
||||||
k1.ScalarMult(k1, a)
|
|
||||||
k1Bytes := k1.Marshal()
|
|
||||||
|
|
||||||
k2 := Pair(pc, qa)
|
|
||||||
k2.ScalarMult(k2, b)
|
|
||||||
k2Bytes := k2.Marshal()
|
|
||||||
|
|
||||||
k3 := Pair(pa, qb)
|
|
||||||
k3.ScalarMult(k3, c)
|
|
||||||
k3Bytes := k3.Marshal()
|
|
||||||
|
|
||||||
if !bytes.Equal(k1Bytes, k2Bytes) || !bytes.Equal(k2Bytes, k3Bytes) {
|
|
||||||
t.Errorf("keys didn't agree")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkPairing(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
Pair(&G1{curveGen}, &G2{twistGen})
|
|
||||||
}
|
|
||||||
}
|
|
44
vendor/golang.org/x/crypto/bn256/constants.go
generated
vendored
44
vendor/golang.org/x/crypto/bn256/constants.go
generated
vendored
|
@ -1,44 +0,0 @@
|
||||||
// Copyright 2012 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 bn256
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/big"
|
|
||||||
)
|
|
||||||
|
|
||||||
func bigFromBase10(s string) *big.Int {
|
|
||||||
n, _ := new(big.Int).SetString(s, 10)
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
// u is the BN parameter that determines the prime: 1868033³.
|
|
||||||
var u = bigFromBase10("6518589491078791937")
|
|
||||||
|
|
||||||
// p is a prime over which we form a basic field: 36u⁴+36u³+24u³+6u+1.
|
|
||||||
var p = bigFromBase10("65000549695646603732796438742359905742825358107623003571877145026864184071783")
|
|
||||||
|
|
||||||
// Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u³+6u+1.
|
|
||||||
var Order = bigFromBase10("65000549695646603732796438742359905742570406053903786389881062969044166799969")
|
|
||||||
|
|
||||||
// xiToPMinus1Over6 is ξ^((p-1)/6) where ξ = i+3.
|
|
||||||
var xiToPMinus1Over6 = &gfP2{bigFromBase10("8669379979083712429711189836753509758585994370025260553045152614783263110636"), bigFromBase10("19998038925833620163537568958541907098007303196759855091367510456613536016040")}
|
|
||||||
|
|
||||||
// xiToPMinus1Over3 is ξ^((p-1)/3) where ξ = i+3.
|
|
||||||
var xiToPMinus1Over3 = &gfP2{bigFromBase10("26098034838977895781559542626833399156321265654106457577426020397262786167059"), bigFromBase10("15931493369629630809226283458085260090334794394361662678240713231519278691715")}
|
|
||||||
|
|
||||||
// xiToPMinus1Over2 is ξ^((p-1)/2) where ξ = i+3.
|
|
||||||
var xiToPMinus1Over2 = &gfP2{bigFromBase10("50997318142241922852281555961173165965672272825141804376761836765206060036244"), bigFromBase10("38665955945962842195025998234511023902832543644254935982879660597356748036009")}
|
|
||||||
|
|
||||||
// xiToPSquaredMinus1Over3 is ξ^((p²-1)/3) where ξ = i+3.
|
|
||||||
var xiToPSquaredMinus1Over3 = bigFromBase10("65000549695646603727810655408050771481677621702948236658134783353303381437752")
|
|
||||||
|
|
||||||
// xiTo2PSquaredMinus2Over3 is ξ^((2p²-2)/3) where ξ = i+3 (a cubic root of unity, mod p).
|
|
||||||
var xiTo2PSquaredMinus2Over3 = bigFromBase10("4985783334309134261147736404674766913742361673560802634030")
|
|
||||||
|
|
||||||
// xiToPSquaredMinus1Over6 is ξ^((1p²-1)/6) where ξ = i+3 (a cubic root of -1, mod p).
|
|
||||||
var xiToPSquaredMinus1Over6 = bigFromBase10("65000549695646603727810655408050771481677621702948236658134783353303381437753")
|
|
||||||
|
|
||||||
// xiTo2PMinus2Over3 is ξ^((2p-2)/3) where ξ = i+3.
|
|
||||||
var xiTo2PMinus2Over3 = &gfP2{bigFromBase10("19885131339612776214803633203834694332692106372356013117629940868870585019582"), bigFromBase10("21645619881471562101905880913352894726728173167203616652430647841922248593627")}
|
|
278
vendor/golang.org/x/crypto/bn256/curve.go
generated
vendored
278
vendor/golang.org/x/crypto/bn256/curve.go
generated
vendored
|
@ -1,278 +0,0 @@
|
||||||
// Copyright 2012 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 bn256
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/big"
|
|
||||||
)
|
|
||||||
|
|
||||||
// curvePoint implements the elliptic curve y²=x³+3. Points are kept in
|
|
||||||
// Jacobian form and t=z² when valid. G₁ is the set of points of this curve on
|
|
||||||
// GF(p).
|
|
||||||
type curvePoint struct {
|
|
||||||
x, y, z, t *big.Int
|
|
||||||
}
|
|
||||||
|
|
||||||
var curveB = new(big.Int).SetInt64(3)
|
|
||||||
|
|
||||||
// curveGen is the generator of G₁.
|
|
||||||
var curveGen = &curvePoint{
|
|
||||||
new(big.Int).SetInt64(1),
|
|
||||||
new(big.Int).SetInt64(-2),
|
|
||||||
new(big.Int).SetInt64(1),
|
|
||||||
new(big.Int).SetInt64(1),
|
|
||||||
}
|
|
||||||
|
|
||||||
func newCurvePoint(pool *bnPool) *curvePoint {
|
|
||||||
return &curvePoint{
|
|
||||||
pool.Get(),
|
|
||||||
pool.Get(),
|
|
||||||
pool.Get(),
|
|
||||||
pool.Get(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *curvePoint) String() string {
|
|
||||||
c.MakeAffine(new(bnPool))
|
|
||||||
return "(" + c.x.String() + ", " + c.y.String() + ")"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *curvePoint) Put(pool *bnPool) {
|
|
||||||
pool.Put(c.x)
|
|
||||||
pool.Put(c.y)
|
|
||||||
pool.Put(c.z)
|
|
||||||
pool.Put(c.t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *curvePoint) Set(a *curvePoint) {
|
|
||||||
c.x.Set(a.x)
|
|
||||||
c.y.Set(a.y)
|
|
||||||
c.z.Set(a.z)
|
|
||||||
c.t.Set(a.t)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsOnCurve returns true iff c is on the curve where c must be in affine form.
|
|
||||||
func (c *curvePoint) IsOnCurve() bool {
|
|
||||||
yy := new(big.Int).Mul(c.y, c.y)
|
|
||||||
xxx := new(big.Int).Mul(c.x, c.x)
|
|
||||||
xxx.Mul(xxx, c.x)
|
|
||||||
yy.Sub(yy, xxx)
|
|
||||||
yy.Sub(yy, curveB)
|
|
||||||
if yy.Sign() < 0 || yy.Cmp(p) >= 0 {
|
|
||||||
yy.Mod(yy, p)
|
|
||||||
}
|
|
||||||
return yy.Sign() == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *curvePoint) SetInfinity() {
|
|
||||||
c.z.SetInt64(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *curvePoint) IsInfinity() bool {
|
|
||||||
return c.z.Sign() == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *curvePoint) Add(a, b *curvePoint, pool *bnPool) {
|
|
||||||
if a.IsInfinity() {
|
|
||||||
c.Set(b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if b.IsInfinity() {
|
|
||||||
c.Set(a)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
|
|
||||||
|
|
||||||
// Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2]
|
|
||||||
// by [u1:s1:z1·z2] and [u2:s2:z1·z2]
|
|
||||||
// where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³
|
|
||||||
z1z1 := pool.Get().Mul(a.z, a.z)
|
|
||||||
z1z1.Mod(z1z1, p)
|
|
||||||
z2z2 := pool.Get().Mul(b.z, b.z)
|
|
||||||
z2z2.Mod(z2z2, p)
|
|
||||||
u1 := pool.Get().Mul(a.x, z2z2)
|
|
||||||
u1.Mod(u1, p)
|
|
||||||
u2 := pool.Get().Mul(b.x, z1z1)
|
|
||||||
u2.Mod(u2, p)
|
|
||||||
|
|
||||||
t := pool.Get().Mul(b.z, z2z2)
|
|
||||||
t.Mod(t, p)
|
|
||||||
s1 := pool.Get().Mul(a.y, t)
|
|
||||||
s1.Mod(s1, p)
|
|
||||||
|
|
||||||
t.Mul(a.z, z1z1)
|
|
||||||
t.Mod(t, p)
|
|
||||||
s2 := pool.Get().Mul(b.y, t)
|
|
||||||
s2.Mod(s2, p)
|
|
||||||
|
|
||||||
// Compute x = (2h)²(s²-u1-u2)
|
|
||||||
// where s = (s2-s1)/(u2-u1) is the slope of the line through
|
|
||||||
// (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below.
|
|
||||||
// This is also:
|
|
||||||
// 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1)
|
|
||||||
// = r² - j - 2v
|
|
||||||
// with the notations below.
|
|
||||||
h := pool.Get().Sub(u2, u1)
|
|
||||||
xEqual := h.Sign() == 0
|
|
||||||
|
|
||||||
t.Add(h, h)
|
|
||||||
// i = 4h²
|
|
||||||
i := pool.Get().Mul(t, t)
|
|
||||||
i.Mod(i, p)
|
|
||||||
// j = 4h³
|
|
||||||
j := pool.Get().Mul(h, i)
|
|
||||||
j.Mod(j, p)
|
|
||||||
|
|
||||||
t.Sub(s2, s1)
|
|
||||||
yEqual := t.Sign() == 0
|
|
||||||
if xEqual && yEqual {
|
|
||||||
c.Double(a, pool)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
r := pool.Get().Add(t, t)
|
|
||||||
|
|
||||||
v := pool.Get().Mul(u1, i)
|
|
||||||
v.Mod(v, p)
|
|
||||||
|
|
||||||
// t4 = 4(s2-s1)²
|
|
||||||
t4 := pool.Get().Mul(r, r)
|
|
||||||
t4.Mod(t4, p)
|
|
||||||
t.Add(v, v)
|
|
||||||
t6 := pool.Get().Sub(t4, j)
|
|
||||||
c.x.Sub(t6, t)
|
|
||||||
|
|
||||||
// Set y = -(2h)³(s1 + s*(x/4h²-u1))
|
|
||||||
// This is also
|
|
||||||
// y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j
|
|
||||||
t.Sub(v, c.x) // t7
|
|
||||||
t4.Mul(s1, j) // t8
|
|
||||||
t4.Mod(t4, p)
|
|
||||||
t6.Add(t4, t4) // t9
|
|
||||||
t4.Mul(r, t) // t10
|
|
||||||
t4.Mod(t4, p)
|
|
||||||
c.y.Sub(t4, t6)
|
|
||||||
|
|
||||||
// Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2
|
|
||||||
t.Add(a.z, b.z) // t11
|
|
||||||
t4.Mul(t, t) // t12
|
|
||||||
t4.Mod(t4, p)
|
|
||||||
t.Sub(t4, z1z1) // t13
|
|
||||||
t4.Sub(t, z2z2) // t14
|
|
||||||
c.z.Mul(t4, h)
|
|
||||||
c.z.Mod(c.z, p)
|
|
||||||
|
|
||||||
pool.Put(z1z1)
|
|
||||||
pool.Put(z2z2)
|
|
||||||
pool.Put(u1)
|
|
||||||
pool.Put(u2)
|
|
||||||
pool.Put(t)
|
|
||||||
pool.Put(s1)
|
|
||||||
pool.Put(s2)
|
|
||||||
pool.Put(h)
|
|
||||||
pool.Put(i)
|
|
||||||
pool.Put(j)
|
|
||||||
pool.Put(r)
|
|
||||||
pool.Put(v)
|
|
||||||
pool.Put(t4)
|
|
||||||
pool.Put(t6)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *curvePoint) Double(a *curvePoint, pool *bnPool) {
|
|
||||||
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
|
|
||||||
A := pool.Get().Mul(a.x, a.x)
|
|
||||||
A.Mod(A, p)
|
|
||||||
B := pool.Get().Mul(a.y, a.y)
|
|
||||||
B.Mod(B, p)
|
|
||||||
C := pool.Get().Mul(B, B)
|
|
||||||
C.Mod(C, p)
|
|
||||||
|
|
||||||
t := pool.Get().Add(a.x, B)
|
|
||||||
t2 := pool.Get().Mul(t, t)
|
|
||||||
t2.Mod(t2, p)
|
|
||||||
t.Sub(t2, A)
|
|
||||||
t2.Sub(t, C)
|
|
||||||
d := pool.Get().Add(t2, t2)
|
|
||||||
t.Add(A, A)
|
|
||||||
e := pool.Get().Add(t, A)
|
|
||||||
f := pool.Get().Mul(e, e)
|
|
||||||
f.Mod(f, p)
|
|
||||||
|
|
||||||
t.Add(d, d)
|
|
||||||
c.x.Sub(f, t)
|
|
||||||
|
|
||||||
t.Add(C, C)
|
|
||||||
t2.Add(t, t)
|
|
||||||
t.Add(t2, t2)
|
|
||||||
c.y.Sub(d, c.x)
|
|
||||||
t2.Mul(e, c.y)
|
|
||||||
t2.Mod(t2, p)
|
|
||||||
c.y.Sub(t2, t)
|
|
||||||
|
|
||||||
t.Mul(a.y, a.z)
|
|
||||||
t.Mod(t, p)
|
|
||||||
c.z.Add(t, t)
|
|
||||||
|
|
||||||
pool.Put(A)
|
|
||||||
pool.Put(B)
|
|
||||||
pool.Put(C)
|
|
||||||
pool.Put(t)
|
|
||||||
pool.Put(t2)
|
|
||||||
pool.Put(d)
|
|
||||||
pool.Put(e)
|
|
||||||
pool.Put(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoint {
|
|
||||||
sum := newCurvePoint(pool)
|
|
||||||
sum.SetInfinity()
|
|
||||||
t := newCurvePoint(pool)
|
|
||||||
|
|
||||||
for i := scalar.BitLen(); i >= 0; i-- {
|
|
||||||
t.Double(sum, pool)
|
|
||||||
if scalar.Bit(i) != 0 {
|
|
||||||
sum.Add(t, a, pool)
|
|
||||||
} else {
|
|
||||||
sum.Set(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Set(sum)
|
|
||||||
sum.Put(pool)
|
|
||||||
t.Put(pool)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint {
|
|
||||||
if words := c.z.Bits(); len(words) == 1 && words[0] == 1 {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
zInv := pool.Get().ModInverse(c.z, p)
|
|
||||||
t := pool.Get().Mul(c.y, zInv)
|
|
||||||
t.Mod(t, p)
|
|
||||||
zInv2 := pool.Get().Mul(zInv, zInv)
|
|
||||||
zInv2.Mod(zInv2, p)
|
|
||||||
c.y.Mul(t, zInv2)
|
|
||||||
c.y.Mod(c.y, p)
|
|
||||||
t.Mul(c.x, zInv2)
|
|
||||||
t.Mod(t, p)
|
|
||||||
c.x.Set(t)
|
|
||||||
c.z.SetInt64(1)
|
|
||||||
c.t.SetInt64(1)
|
|
||||||
|
|
||||||
pool.Put(zInv)
|
|
||||||
pool.Put(t)
|
|
||||||
pool.Put(zInv2)
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *curvePoint) Negative(a *curvePoint) {
|
|
||||||
c.x.Set(a.x)
|
|
||||||
c.y.Neg(a.y)
|
|
||||||
c.z.Set(a.z)
|
|
||||||
c.t.SetInt64(0)
|
|
||||||
}
|
|
43
vendor/golang.org/x/crypto/bn256/example_test.go
generated
vendored
43
vendor/golang.org/x/crypto/bn256/example_test.go
generated
vendored
|
@ -1,43 +0,0 @@
|
||||||
// Copyright 2012 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 bn256
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExamplePair() {
|
|
||||||
// This implements the tripartite Diffie-Hellman algorithm from "A One
|
|
||||||
// Round Protocol for Tripartite Diffie-Hellman", A. Joux.
|
|
||||||
// http://www.springerlink.com/content/cddc57yyva0hburb/fulltext.pdf
|
|
||||||
|
|
||||||
// Each of three parties, a, b and c, generate a private value.
|
|
||||||
a, _ := rand.Int(rand.Reader, Order)
|
|
||||||
b, _ := rand.Int(rand.Reader, Order)
|
|
||||||
c, _ := rand.Int(rand.Reader, Order)
|
|
||||||
|
|
||||||
// Then each party calculates g₁ and g₂ times their private value.
|
|
||||||
pa := new(G1).ScalarBaseMult(a)
|
|
||||||
qa := new(G2).ScalarBaseMult(a)
|
|
||||||
|
|
||||||
pb := new(G1).ScalarBaseMult(b)
|
|
||||||
qb := new(G2).ScalarBaseMult(b)
|
|
||||||
|
|
||||||
pc := new(G1).ScalarBaseMult(c)
|
|
||||||
qc := new(G2).ScalarBaseMult(c)
|
|
||||||
|
|
||||||
// Now each party exchanges its public values with the other two and
|
|
||||||
// all parties can calculate the shared key.
|
|
||||||
k1 := Pair(pb, qc)
|
|
||||||
k1.ScalarMult(k1, a)
|
|
||||||
|
|
||||||
k2 := Pair(pc, qa)
|
|
||||||
k2.ScalarMult(k2, b)
|
|
||||||
|
|
||||||
k3 := Pair(pa, qb)
|
|
||||||
k3.ScalarMult(k3, c)
|
|
||||||
|
|
||||||
// k1, k2 and k3 will all be equal.
|
|
||||||
}
|
|
200
vendor/golang.org/x/crypto/bn256/gfp12.go
generated
vendored
200
vendor/golang.org/x/crypto/bn256/gfp12.go
generated
vendored
|
@ -1,200 +0,0 @@
|
||||||
// Copyright 2012 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 bn256
|
|
||||||
|
|
||||||
// For details of the algorithms used, see "Multiplication and Squaring on
|
|
||||||
// Pairing-Friendly Fields, Devegili et al.
|
|
||||||
// http://eprint.iacr.org/2006/471.pdf.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/big"
|
|
||||||
)
|
|
||||||
|
|
||||||
// gfP12 implements the field of size p¹² as a quadratic extension of gfP6
|
|
||||||
// where ω²=τ.
|
|
||||||
type gfP12 struct {
|
|
||||||
x, y *gfP6 // value is xω + y
|
|
||||||
}
|
|
||||||
|
|
||||||
func newGFp12(pool *bnPool) *gfP12 {
|
|
||||||
return &gfP12{newGFp6(pool), newGFp6(pool)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP12) String() string {
|
|
||||||
return "(" + e.x.String() + "," + e.y.String() + ")"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP12) Put(pool *bnPool) {
|
|
||||||
e.x.Put(pool)
|
|
||||||
e.y.Put(pool)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP12) Set(a *gfP12) *gfP12 {
|
|
||||||
e.x.Set(a.x)
|
|
||||||
e.y.Set(a.y)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP12) SetZero() *gfP12 {
|
|
||||||
e.x.SetZero()
|
|
||||||
e.y.SetZero()
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP12) SetOne() *gfP12 {
|
|
||||||
e.x.SetZero()
|
|
||||||
e.y.SetOne()
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP12) Minimal() {
|
|
||||||
e.x.Minimal()
|
|
||||||
e.y.Minimal()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP12) IsZero() bool {
|
|
||||||
e.Minimal()
|
|
||||||
return e.x.IsZero() && e.y.IsZero()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP12) IsOne() bool {
|
|
||||||
e.Minimal()
|
|
||||||
return e.x.IsZero() && e.y.IsOne()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP12) Conjugate(a *gfP12) *gfP12 {
|
|
||||||
e.x.Negative(a.x)
|
|
||||||
e.y.Set(a.y)
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP12) Negative(a *gfP12) *gfP12 {
|
|
||||||
e.x.Negative(a.x)
|
|
||||||
e.y.Negative(a.y)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p
|
|
||||||
func (e *gfP12) Frobenius(a *gfP12, pool *bnPool) *gfP12 {
|
|
||||||
e.x.Frobenius(a.x, pool)
|
|
||||||
e.y.Frobenius(a.y, pool)
|
|
||||||
e.x.MulScalar(e.x, xiToPMinus1Over6, pool)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p²
|
|
||||||
func (e *gfP12) FrobeniusP2(a *gfP12, pool *bnPool) *gfP12 {
|
|
||||||
e.x.FrobeniusP2(a.x)
|
|
||||||
e.x.MulGFP(e.x, xiToPSquaredMinus1Over6)
|
|
||||||
e.y.FrobeniusP2(a.y)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP12) Add(a, b *gfP12) *gfP12 {
|
|
||||||
e.x.Add(a.x, b.x)
|
|
||||||
e.y.Add(a.y, b.y)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP12) Sub(a, b *gfP12) *gfP12 {
|
|
||||||
e.x.Sub(a.x, b.x)
|
|
||||||
e.y.Sub(a.y, b.y)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 {
|
|
||||||
tx := newGFp6(pool)
|
|
||||||
tx.Mul(a.x, b.y, pool)
|
|
||||||
t := newGFp6(pool)
|
|
||||||
t.Mul(b.x, a.y, pool)
|
|
||||||
tx.Add(tx, t)
|
|
||||||
|
|
||||||
ty := newGFp6(pool)
|
|
||||||
ty.Mul(a.y, b.y, pool)
|
|
||||||
t.Mul(a.x, b.x, pool)
|
|
||||||
t.MulTau(t, pool)
|
|
||||||
e.y.Add(ty, t)
|
|
||||||
e.x.Set(tx)
|
|
||||||
|
|
||||||
tx.Put(pool)
|
|
||||||
ty.Put(pool)
|
|
||||||
t.Put(pool)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 {
|
|
||||||
e.x.Mul(e.x, b, pool)
|
|
||||||
e.y.Mul(e.y, b, pool)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 {
|
|
||||||
sum := newGFp12(pool)
|
|
||||||
sum.SetOne()
|
|
||||||
t := newGFp12(pool)
|
|
||||||
|
|
||||||
for i := power.BitLen() - 1; i >= 0; i-- {
|
|
||||||
t.Square(sum, pool)
|
|
||||||
if power.Bit(i) != 0 {
|
|
||||||
sum.Mul(t, a, pool)
|
|
||||||
} else {
|
|
||||||
sum.Set(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Set(sum)
|
|
||||||
|
|
||||||
sum.Put(pool)
|
|
||||||
t.Put(pool)
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 {
|
|
||||||
// Complex squaring algorithm
|
|
||||||
v0 := newGFp6(pool)
|
|
||||||
v0.Mul(a.x, a.y, pool)
|
|
||||||
|
|
||||||
t := newGFp6(pool)
|
|
||||||
t.MulTau(a.x, pool)
|
|
||||||
t.Add(a.y, t)
|
|
||||||
ty := newGFp6(pool)
|
|
||||||
ty.Add(a.x, a.y)
|
|
||||||
ty.Mul(ty, t, pool)
|
|
||||||
ty.Sub(ty, v0)
|
|
||||||
t.MulTau(v0, pool)
|
|
||||||
ty.Sub(ty, t)
|
|
||||||
|
|
||||||
e.y.Set(ty)
|
|
||||||
e.x.Double(v0)
|
|
||||||
|
|
||||||
v0.Put(pool)
|
|
||||||
t.Put(pool)
|
|
||||||
ty.Put(pool)
|
|
||||||
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP12) Invert(a *gfP12, pool *bnPool) *gfP12 {
|
|
||||||
// See "Implementing cryptographic pairings", M. Scott, section 3.2.
|
|
||||||
// ftp://136.206.11.249/pub/crypto/pairings.pdf
|
|
||||||
t1 := newGFp6(pool)
|
|
||||||
t2 := newGFp6(pool)
|
|
||||||
|
|
||||||
t1.Square(a.x, pool)
|
|
||||||
t2.Square(a.y, pool)
|
|
||||||
t1.MulTau(t1, pool)
|
|
||||||
t1.Sub(t2, t1)
|
|
||||||
t2.Invert(t1, pool)
|
|
||||||
|
|
||||||
e.x.Negative(a.x)
|
|
||||||
e.y.Set(a.y)
|
|
||||||
e.MulScalar(e, t2, pool)
|
|
||||||
|
|
||||||
t1.Put(pool)
|
|
||||||
t2.Put(pool)
|
|
||||||
|
|
||||||
return e
|
|
||||||
}
|
|
219
vendor/golang.org/x/crypto/bn256/gfp2.go
generated
vendored
219
vendor/golang.org/x/crypto/bn256/gfp2.go
generated
vendored
|
@ -1,219 +0,0 @@
|
||||||
// Copyright 2012 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 bn256
|
|
||||||
|
|
||||||
// For details of the algorithms used, see "Multiplication and Squaring on
|
|
||||||
// Pairing-Friendly Fields, Devegili et al.
|
|
||||||
// http://eprint.iacr.org/2006/471.pdf.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/big"
|
|
||||||
)
|
|
||||||
|
|
||||||
// gfP2 implements a field of size p² as a quadratic extension of the base
|
|
||||||
// field where i²=-1.
|
|
||||||
type gfP2 struct {
|
|
||||||
x, y *big.Int // value is xi+y.
|
|
||||||
}
|
|
||||||
|
|
||||||
func newGFp2(pool *bnPool) *gfP2 {
|
|
||||||
return &gfP2{pool.Get(), pool.Get()}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP2) String() string {
|
|
||||||
x := new(big.Int).Mod(e.x, p)
|
|
||||||
y := new(big.Int).Mod(e.y, p)
|
|
||||||
return "(" + x.String() + "," + y.String() + ")"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP2) Put(pool *bnPool) {
|
|
||||||
pool.Put(e.x)
|
|
||||||
pool.Put(e.y)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP2) Set(a *gfP2) *gfP2 {
|
|
||||||
e.x.Set(a.x)
|
|
||||||
e.y.Set(a.y)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP2) SetZero() *gfP2 {
|
|
||||||
e.x.SetInt64(0)
|
|
||||||
e.y.SetInt64(0)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP2) SetOne() *gfP2 {
|
|
||||||
e.x.SetInt64(0)
|
|
||||||
e.y.SetInt64(1)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP2) Minimal() {
|
|
||||||
if e.x.Sign() < 0 || e.x.Cmp(p) >= 0 {
|
|
||||||
e.x.Mod(e.x, p)
|
|
||||||
}
|
|
||||||
if e.y.Sign() < 0 || e.y.Cmp(p) >= 0 {
|
|
||||||
e.y.Mod(e.y, p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP2) IsZero() bool {
|
|
||||||
return e.x.Sign() == 0 && e.y.Sign() == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP2) IsOne() bool {
|
|
||||||
if e.x.Sign() != 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
words := e.y.Bits()
|
|
||||||
return len(words) == 1 && words[0] == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP2) Conjugate(a *gfP2) *gfP2 {
|
|
||||||
e.y.Set(a.y)
|
|
||||||
e.x.Neg(a.x)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP2) Negative(a *gfP2) *gfP2 {
|
|
||||||
e.x.Neg(a.x)
|
|
||||||
e.y.Neg(a.y)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP2) Add(a, b *gfP2) *gfP2 {
|
|
||||||
e.x.Add(a.x, b.x)
|
|
||||||
e.y.Add(a.y, b.y)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP2) Sub(a, b *gfP2) *gfP2 {
|
|
||||||
e.x.Sub(a.x, b.x)
|
|
||||||
e.y.Sub(a.y, b.y)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP2) Double(a *gfP2) *gfP2 {
|
|
||||||
e.x.Lsh(a.x, 1)
|
|
||||||
e.y.Lsh(a.y, 1)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 {
|
|
||||||
sum := newGFp2(pool)
|
|
||||||
sum.SetOne()
|
|
||||||
t := newGFp2(pool)
|
|
||||||
|
|
||||||
for i := power.BitLen() - 1; i >= 0; i-- {
|
|
||||||
t.Square(sum, pool)
|
|
||||||
if power.Bit(i) != 0 {
|
|
||||||
sum.Mul(t, a, pool)
|
|
||||||
} else {
|
|
||||||
sum.Set(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Set(sum)
|
|
||||||
|
|
||||||
sum.Put(pool)
|
|
||||||
t.Put(pool)
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// See "Multiplication and Squaring in Pairing-Friendly Fields",
|
|
||||||
// http://eprint.iacr.org/2006/471.pdf
|
|
||||||
func (e *gfP2) Mul(a, b *gfP2, pool *bnPool) *gfP2 {
|
|
||||||
tx := pool.Get().Mul(a.x, b.y)
|
|
||||||
t := pool.Get().Mul(b.x, a.y)
|
|
||||||
tx.Add(tx, t)
|
|
||||||
tx.Mod(tx, p)
|
|
||||||
|
|
||||||
ty := pool.Get().Mul(a.y, b.y)
|
|
||||||
t.Mul(a.x, b.x)
|
|
||||||
ty.Sub(ty, t)
|
|
||||||
e.y.Mod(ty, p)
|
|
||||||
e.x.Set(tx)
|
|
||||||
|
|
||||||
pool.Put(tx)
|
|
||||||
pool.Put(ty)
|
|
||||||
pool.Put(t)
|
|
||||||
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP2) MulScalar(a *gfP2, b *big.Int) *gfP2 {
|
|
||||||
e.x.Mul(a.x, b)
|
|
||||||
e.y.Mul(a.y, b)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// MulXi sets e=ξa where ξ=i+3 and then returns e.
|
|
||||||
func (e *gfP2) MulXi(a *gfP2, pool *bnPool) *gfP2 {
|
|
||||||
// (xi+y)(i+3) = (3x+y)i+(3y-x)
|
|
||||||
tx := pool.Get().Lsh(a.x, 1)
|
|
||||||
tx.Add(tx, a.x)
|
|
||||||
tx.Add(tx, a.y)
|
|
||||||
|
|
||||||
ty := pool.Get().Lsh(a.y, 1)
|
|
||||||
ty.Add(ty, a.y)
|
|
||||||
ty.Sub(ty, a.x)
|
|
||||||
|
|
||||||
e.x.Set(tx)
|
|
||||||
e.y.Set(ty)
|
|
||||||
|
|
||||||
pool.Put(tx)
|
|
||||||
pool.Put(ty)
|
|
||||||
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP2) Square(a *gfP2, pool *bnPool) *gfP2 {
|
|
||||||
// Complex squaring algorithm:
|
|
||||||
// (xi+b)² = (x+y)(y-x) + 2*i*x*y
|
|
||||||
t1 := pool.Get().Sub(a.y, a.x)
|
|
||||||
t2 := pool.Get().Add(a.x, a.y)
|
|
||||||
ty := pool.Get().Mul(t1, t2)
|
|
||||||
ty.Mod(ty, p)
|
|
||||||
|
|
||||||
t1.Mul(a.x, a.y)
|
|
||||||
t1.Lsh(t1, 1)
|
|
||||||
|
|
||||||
e.x.Mod(t1, p)
|
|
||||||
e.y.Set(ty)
|
|
||||||
|
|
||||||
pool.Put(t1)
|
|
||||||
pool.Put(t2)
|
|
||||||
pool.Put(ty)
|
|
||||||
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP2) Invert(a *gfP2, pool *bnPool) *gfP2 {
|
|
||||||
// See "Implementing cryptographic pairings", M. Scott, section 3.2.
|
|
||||||
// ftp://136.206.11.249/pub/crypto/pairings.pdf
|
|
||||||
t := pool.Get()
|
|
||||||
t.Mul(a.y, a.y)
|
|
||||||
t2 := pool.Get()
|
|
||||||
t2.Mul(a.x, a.x)
|
|
||||||
t.Add(t, t2)
|
|
||||||
|
|
||||||
inv := pool.Get()
|
|
||||||
inv.ModInverse(t, p)
|
|
||||||
|
|
||||||
e.x.Neg(a.x)
|
|
||||||
e.x.Mul(e.x, inv)
|
|
||||||
e.x.Mod(e.x, p)
|
|
||||||
|
|
||||||
e.y.Mul(a.y, inv)
|
|
||||||
e.y.Mod(e.y, p)
|
|
||||||
|
|
||||||
pool.Put(t)
|
|
||||||
pool.Put(t2)
|
|
||||||
pool.Put(inv)
|
|
||||||
|
|
||||||
return e
|
|
||||||
}
|
|
296
vendor/golang.org/x/crypto/bn256/gfp6.go
generated
vendored
296
vendor/golang.org/x/crypto/bn256/gfp6.go
generated
vendored
|
@ -1,296 +0,0 @@
|
||||||
// Copyright 2012 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 bn256
|
|
||||||
|
|
||||||
// For details of the algorithms used, see "Multiplication and Squaring on
|
|
||||||
// Pairing-Friendly Fields, Devegili et al.
|
|
||||||
// http://eprint.iacr.org/2006/471.pdf.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/big"
|
|
||||||
)
|
|
||||||
|
|
||||||
// gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ
|
|
||||||
// and ξ=i+3.
|
|
||||||
type gfP6 struct {
|
|
||||||
x, y, z *gfP2 // value is xτ² + yτ + z
|
|
||||||
}
|
|
||||||
|
|
||||||
func newGFp6(pool *bnPool) *gfP6 {
|
|
||||||
return &gfP6{newGFp2(pool), newGFp2(pool), newGFp2(pool)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) String() string {
|
|
||||||
return "(" + e.x.String() + "," + e.y.String() + "," + e.z.String() + ")"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) Put(pool *bnPool) {
|
|
||||||
e.x.Put(pool)
|
|
||||||
e.y.Put(pool)
|
|
||||||
e.z.Put(pool)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) Set(a *gfP6) *gfP6 {
|
|
||||||
e.x.Set(a.x)
|
|
||||||
e.y.Set(a.y)
|
|
||||||
e.z.Set(a.z)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) SetZero() *gfP6 {
|
|
||||||
e.x.SetZero()
|
|
||||||
e.y.SetZero()
|
|
||||||
e.z.SetZero()
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) SetOne() *gfP6 {
|
|
||||||
e.x.SetZero()
|
|
||||||
e.y.SetZero()
|
|
||||||
e.z.SetOne()
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) Minimal() {
|
|
||||||
e.x.Minimal()
|
|
||||||
e.y.Minimal()
|
|
||||||
e.z.Minimal()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) IsZero() bool {
|
|
||||||
return e.x.IsZero() && e.y.IsZero() && e.z.IsZero()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) IsOne() bool {
|
|
||||||
return e.x.IsZero() && e.y.IsZero() && e.z.IsOne()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) Negative(a *gfP6) *gfP6 {
|
|
||||||
e.x.Negative(a.x)
|
|
||||||
e.y.Negative(a.y)
|
|
||||||
e.z.Negative(a.z)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) Frobenius(a *gfP6, pool *bnPool) *gfP6 {
|
|
||||||
e.x.Conjugate(a.x)
|
|
||||||
e.y.Conjugate(a.y)
|
|
||||||
e.z.Conjugate(a.z)
|
|
||||||
|
|
||||||
e.x.Mul(e.x, xiTo2PMinus2Over3, pool)
|
|
||||||
e.y.Mul(e.y, xiToPMinus1Over3, pool)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// FrobeniusP2 computes (xτ²+yτ+z)^(p²) = xτ^(2p²) + yτ^(p²) + z
|
|
||||||
func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 {
|
|
||||||
// τ^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3)
|
|
||||||
e.x.MulScalar(a.x, xiTo2PSquaredMinus2Over3)
|
|
||||||
// τ^(p²) = ττ^(p²-1) = τξ^((p²-1)/3)
|
|
||||||
e.y.MulScalar(a.y, xiToPSquaredMinus1Over3)
|
|
||||||
e.z.Set(a.z)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) Add(a, b *gfP6) *gfP6 {
|
|
||||||
e.x.Add(a.x, b.x)
|
|
||||||
e.y.Add(a.y, b.y)
|
|
||||||
e.z.Add(a.z, b.z)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) Sub(a, b *gfP6) *gfP6 {
|
|
||||||
e.x.Sub(a.x, b.x)
|
|
||||||
e.y.Sub(a.y, b.y)
|
|
||||||
e.z.Sub(a.z, b.z)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) Double(a *gfP6) *gfP6 {
|
|
||||||
e.x.Double(a.x)
|
|
||||||
e.y.Double(a.y)
|
|
||||||
e.z.Double(a.z)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) Mul(a, b *gfP6, pool *bnPool) *gfP6 {
|
|
||||||
// "Multiplication and Squaring on Pairing-Friendly Fields"
|
|
||||||
// Section 4, Karatsuba method.
|
|
||||||
// http://eprint.iacr.org/2006/471.pdf
|
|
||||||
|
|
||||||
v0 := newGFp2(pool)
|
|
||||||
v0.Mul(a.z, b.z, pool)
|
|
||||||
v1 := newGFp2(pool)
|
|
||||||
v1.Mul(a.y, b.y, pool)
|
|
||||||
v2 := newGFp2(pool)
|
|
||||||
v2.Mul(a.x, b.x, pool)
|
|
||||||
|
|
||||||
t0 := newGFp2(pool)
|
|
||||||
t0.Add(a.x, a.y)
|
|
||||||
t1 := newGFp2(pool)
|
|
||||||
t1.Add(b.x, b.y)
|
|
||||||
tz := newGFp2(pool)
|
|
||||||
tz.Mul(t0, t1, pool)
|
|
||||||
|
|
||||||
tz.Sub(tz, v1)
|
|
||||||
tz.Sub(tz, v2)
|
|
||||||
tz.MulXi(tz, pool)
|
|
||||||
tz.Add(tz, v0)
|
|
||||||
|
|
||||||
t0.Add(a.y, a.z)
|
|
||||||
t1.Add(b.y, b.z)
|
|
||||||
ty := newGFp2(pool)
|
|
||||||
ty.Mul(t0, t1, pool)
|
|
||||||
ty.Sub(ty, v0)
|
|
||||||
ty.Sub(ty, v1)
|
|
||||||
t0.MulXi(v2, pool)
|
|
||||||
ty.Add(ty, t0)
|
|
||||||
|
|
||||||
t0.Add(a.x, a.z)
|
|
||||||
t1.Add(b.x, b.z)
|
|
||||||
tx := newGFp2(pool)
|
|
||||||
tx.Mul(t0, t1, pool)
|
|
||||||
tx.Sub(tx, v0)
|
|
||||||
tx.Add(tx, v1)
|
|
||||||
tx.Sub(tx, v2)
|
|
||||||
|
|
||||||
e.x.Set(tx)
|
|
||||||
e.y.Set(ty)
|
|
||||||
e.z.Set(tz)
|
|
||||||
|
|
||||||
t0.Put(pool)
|
|
||||||
t1.Put(pool)
|
|
||||||
tx.Put(pool)
|
|
||||||
ty.Put(pool)
|
|
||||||
tz.Put(pool)
|
|
||||||
v0.Put(pool)
|
|
||||||
v1.Put(pool)
|
|
||||||
v2.Put(pool)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) MulScalar(a *gfP6, b *gfP2, pool *bnPool) *gfP6 {
|
|
||||||
e.x.Mul(a.x, b, pool)
|
|
||||||
e.y.Mul(a.y, b, pool)
|
|
||||||
e.z.Mul(a.z, b, pool)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) MulGFP(a *gfP6, b *big.Int) *gfP6 {
|
|
||||||
e.x.MulScalar(a.x, b)
|
|
||||||
e.y.MulScalar(a.y, b)
|
|
||||||
e.z.MulScalar(a.z, b)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ
|
|
||||||
func (e *gfP6) MulTau(a *gfP6, pool *bnPool) {
|
|
||||||
tz := newGFp2(pool)
|
|
||||||
tz.MulXi(a.x, pool)
|
|
||||||
ty := newGFp2(pool)
|
|
||||||
ty.Set(a.y)
|
|
||||||
e.y.Set(a.z)
|
|
||||||
e.x.Set(ty)
|
|
||||||
e.z.Set(tz)
|
|
||||||
tz.Put(pool)
|
|
||||||
ty.Put(pool)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) Square(a *gfP6, pool *bnPool) *gfP6 {
|
|
||||||
v0 := newGFp2(pool).Square(a.z, pool)
|
|
||||||
v1 := newGFp2(pool).Square(a.y, pool)
|
|
||||||
v2 := newGFp2(pool).Square(a.x, pool)
|
|
||||||
|
|
||||||
c0 := newGFp2(pool).Add(a.x, a.y)
|
|
||||||
c0.Square(c0, pool)
|
|
||||||
c0.Sub(c0, v1)
|
|
||||||
c0.Sub(c0, v2)
|
|
||||||
c0.MulXi(c0, pool)
|
|
||||||
c0.Add(c0, v0)
|
|
||||||
|
|
||||||
c1 := newGFp2(pool).Add(a.y, a.z)
|
|
||||||
c1.Square(c1, pool)
|
|
||||||
c1.Sub(c1, v0)
|
|
||||||
c1.Sub(c1, v1)
|
|
||||||
xiV2 := newGFp2(pool).MulXi(v2, pool)
|
|
||||||
c1.Add(c1, xiV2)
|
|
||||||
|
|
||||||
c2 := newGFp2(pool).Add(a.x, a.z)
|
|
||||||
c2.Square(c2, pool)
|
|
||||||
c2.Sub(c2, v0)
|
|
||||||
c2.Add(c2, v1)
|
|
||||||
c2.Sub(c2, v2)
|
|
||||||
|
|
||||||
e.x.Set(c2)
|
|
||||||
e.y.Set(c1)
|
|
||||||
e.z.Set(c0)
|
|
||||||
|
|
||||||
v0.Put(pool)
|
|
||||||
v1.Put(pool)
|
|
||||||
v2.Put(pool)
|
|
||||||
c0.Put(pool)
|
|
||||||
c1.Put(pool)
|
|
||||||
c2.Put(pool)
|
|
||||||
xiV2.Put(pool)
|
|
||||||
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 {
|
|
||||||
// See "Implementing cryptographic pairings", M. Scott, section 3.2.
|
|
||||||
// ftp://136.206.11.249/pub/crypto/pairings.pdf
|
|
||||||
|
|
||||||
// Here we can give a short explanation of how it works: let j be a cubic root of
|
|
||||||
// unity in GF(p²) so that 1+j+j²=0.
|
|
||||||
// Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
|
|
||||||
// = (xτ² + yτ + z)(Cτ²+Bτ+A)
|
|
||||||
// = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm).
|
|
||||||
//
|
|
||||||
// On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
|
|
||||||
// = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy)
|
|
||||||
//
|
|
||||||
// So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz)
|
|
||||||
t1 := newGFp2(pool)
|
|
||||||
|
|
||||||
A := newGFp2(pool)
|
|
||||||
A.Square(a.z, pool)
|
|
||||||
t1.Mul(a.x, a.y, pool)
|
|
||||||
t1.MulXi(t1, pool)
|
|
||||||
A.Sub(A, t1)
|
|
||||||
|
|
||||||
B := newGFp2(pool)
|
|
||||||
B.Square(a.x, pool)
|
|
||||||
B.MulXi(B, pool)
|
|
||||||
t1.Mul(a.y, a.z, pool)
|
|
||||||
B.Sub(B, t1)
|
|
||||||
|
|
||||||
C := newGFp2(pool)
|
|
||||||
C.Square(a.y, pool)
|
|
||||||
t1.Mul(a.x, a.z, pool)
|
|
||||||
C.Sub(C, t1)
|
|
||||||
|
|
||||||
F := newGFp2(pool)
|
|
||||||
F.Mul(C, a.y, pool)
|
|
||||||
F.MulXi(F, pool)
|
|
||||||
t1.Mul(A, a.z, pool)
|
|
||||||
F.Add(F, t1)
|
|
||||||
t1.Mul(B, a.x, pool)
|
|
||||||
t1.MulXi(t1, pool)
|
|
||||||
F.Add(F, t1)
|
|
||||||
|
|
||||||
F.Invert(F, pool)
|
|
||||||
|
|
||||||
e.x.Mul(C, F, pool)
|
|
||||||
e.y.Mul(B, F, pool)
|
|
||||||
e.z.Mul(A, F, pool)
|
|
||||||
|
|
||||||
t1.Put(pool)
|
|
||||||
A.Put(pool)
|
|
||||||
B.Put(pool)
|
|
||||||
C.Put(pool)
|
|
||||||
F.Put(pool)
|
|
||||||
|
|
||||||
return e
|
|
||||||
}
|
|
395
vendor/golang.org/x/crypto/bn256/optate.go
generated
vendored
395
vendor/golang.org/x/crypto/bn256/optate.go
generated
vendored
|
@ -1,395 +0,0 @@
|
||||||
// Copyright 2012 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 bn256
|
|
||||||
|
|
||||||
func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) {
|
|
||||||
// See the mixed addition algorithm from "Faster Computation of the
|
|
||||||
// Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
|
|
||||||
|
|
||||||
B := newGFp2(pool).Mul(p.x, r.t, pool)
|
|
||||||
|
|
||||||
D := newGFp2(pool).Add(p.y, r.z)
|
|
||||||
D.Square(D, pool)
|
|
||||||
D.Sub(D, r2)
|
|
||||||
D.Sub(D, r.t)
|
|
||||||
D.Mul(D, r.t, pool)
|
|
||||||
|
|
||||||
H := newGFp2(pool).Sub(B, r.x)
|
|
||||||
I := newGFp2(pool).Square(H, pool)
|
|
||||||
|
|
||||||
E := newGFp2(pool).Add(I, I)
|
|
||||||
E.Add(E, E)
|
|
||||||
|
|
||||||
J := newGFp2(pool).Mul(H, E, pool)
|
|
||||||
|
|
||||||
L1 := newGFp2(pool).Sub(D, r.y)
|
|
||||||
L1.Sub(L1, r.y)
|
|
||||||
|
|
||||||
V := newGFp2(pool).Mul(r.x, E, pool)
|
|
||||||
|
|
||||||
rOut = newTwistPoint(pool)
|
|
||||||
rOut.x.Square(L1, pool)
|
|
||||||
rOut.x.Sub(rOut.x, J)
|
|
||||||
rOut.x.Sub(rOut.x, V)
|
|
||||||
rOut.x.Sub(rOut.x, V)
|
|
||||||
|
|
||||||
rOut.z.Add(r.z, H)
|
|
||||||
rOut.z.Square(rOut.z, pool)
|
|
||||||
rOut.z.Sub(rOut.z, r.t)
|
|
||||||
rOut.z.Sub(rOut.z, I)
|
|
||||||
|
|
||||||
t := newGFp2(pool).Sub(V, rOut.x)
|
|
||||||
t.Mul(t, L1, pool)
|
|
||||||
t2 := newGFp2(pool).Mul(r.y, J, pool)
|
|
||||||
t2.Add(t2, t2)
|
|
||||||
rOut.y.Sub(t, t2)
|
|
||||||
|
|
||||||
rOut.t.Square(rOut.z, pool)
|
|
||||||
|
|
||||||
t.Add(p.y, rOut.z)
|
|
||||||
t.Square(t, pool)
|
|
||||||
t.Sub(t, r2)
|
|
||||||
t.Sub(t, rOut.t)
|
|
||||||
|
|
||||||
t2.Mul(L1, p.x, pool)
|
|
||||||
t2.Add(t2, t2)
|
|
||||||
a = newGFp2(pool)
|
|
||||||
a.Sub(t2, t)
|
|
||||||
|
|
||||||
c = newGFp2(pool)
|
|
||||||
c.MulScalar(rOut.z, q.y)
|
|
||||||
c.Add(c, c)
|
|
||||||
|
|
||||||
b = newGFp2(pool)
|
|
||||||
b.SetZero()
|
|
||||||
b.Sub(b, L1)
|
|
||||||
b.MulScalar(b, q.x)
|
|
||||||
b.Add(b, b)
|
|
||||||
|
|
||||||
B.Put(pool)
|
|
||||||
D.Put(pool)
|
|
||||||
H.Put(pool)
|
|
||||||
I.Put(pool)
|
|
||||||
E.Put(pool)
|
|
||||||
J.Put(pool)
|
|
||||||
L1.Put(pool)
|
|
||||||
V.Put(pool)
|
|
||||||
t.Put(pool)
|
|
||||||
t2.Put(pool)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) {
|
|
||||||
// See the doubling algorithm for a=0 from "Faster Computation of the
|
|
||||||
// Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
|
|
||||||
|
|
||||||
A := newGFp2(pool).Square(r.x, pool)
|
|
||||||
B := newGFp2(pool).Square(r.y, pool)
|
|
||||||
C := newGFp2(pool).Square(B, pool)
|
|
||||||
|
|
||||||
D := newGFp2(pool).Add(r.x, B)
|
|
||||||
D.Square(D, pool)
|
|
||||||
D.Sub(D, A)
|
|
||||||
D.Sub(D, C)
|
|
||||||
D.Add(D, D)
|
|
||||||
|
|
||||||
E := newGFp2(pool).Add(A, A)
|
|
||||||
E.Add(E, A)
|
|
||||||
|
|
||||||
G := newGFp2(pool).Square(E, pool)
|
|
||||||
|
|
||||||
rOut = newTwistPoint(pool)
|
|
||||||
rOut.x.Sub(G, D)
|
|
||||||
rOut.x.Sub(rOut.x, D)
|
|
||||||
|
|
||||||
rOut.z.Add(r.y, r.z)
|
|
||||||
rOut.z.Square(rOut.z, pool)
|
|
||||||
rOut.z.Sub(rOut.z, B)
|
|
||||||
rOut.z.Sub(rOut.z, r.t)
|
|
||||||
|
|
||||||
rOut.y.Sub(D, rOut.x)
|
|
||||||
rOut.y.Mul(rOut.y, E, pool)
|
|
||||||
t := newGFp2(pool).Add(C, C)
|
|
||||||
t.Add(t, t)
|
|
||||||
t.Add(t, t)
|
|
||||||
rOut.y.Sub(rOut.y, t)
|
|
||||||
|
|
||||||
rOut.t.Square(rOut.z, pool)
|
|
||||||
|
|
||||||
t.Mul(E, r.t, pool)
|
|
||||||
t.Add(t, t)
|
|
||||||
b = newGFp2(pool)
|
|
||||||
b.SetZero()
|
|
||||||
b.Sub(b, t)
|
|
||||||
b.MulScalar(b, q.x)
|
|
||||||
|
|
||||||
a = newGFp2(pool)
|
|
||||||
a.Add(r.x, E)
|
|
||||||
a.Square(a, pool)
|
|
||||||
a.Sub(a, A)
|
|
||||||
a.Sub(a, G)
|
|
||||||
t.Add(B, B)
|
|
||||||
t.Add(t, t)
|
|
||||||
a.Sub(a, t)
|
|
||||||
|
|
||||||
c = newGFp2(pool)
|
|
||||||
c.Mul(rOut.z, r.t, pool)
|
|
||||||
c.Add(c, c)
|
|
||||||
c.MulScalar(c, q.y)
|
|
||||||
|
|
||||||
A.Put(pool)
|
|
||||||
B.Put(pool)
|
|
||||||
C.Put(pool)
|
|
||||||
D.Put(pool)
|
|
||||||
E.Put(pool)
|
|
||||||
G.Put(pool)
|
|
||||||
t.Put(pool)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func mulLine(ret *gfP12, a, b, c *gfP2, pool *bnPool) {
|
|
||||||
a2 := newGFp6(pool)
|
|
||||||
a2.x.SetZero()
|
|
||||||
a2.y.Set(a)
|
|
||||||
a2.z.Set(b)
|
|
||||||
a2.Mul(a2, ret.x, pool)
|
|
||||||
t3 := newGFp6(pool).MulScalar(ret.y, c, pool)
|
|
||||||
|
|
||||||
t := newGFp2(pool)
|
|
||||||
t.Add(b, c)
|
|
||||||
t2 := newGFp6(pool)
|
|
||||||
t2.x.SetZero()
|
|
||||||
t2.y.Set(a)
|
|
||||||
t2.z.Set(t)
|
|
||||||
ret.x.Add(ret.x, ret.y)
|
|
||||||
|
|
||||||
ret.y.Set(t3)
|
|
||||||
|
|
||||||
ret.x.Mul(ret.x, t2, pool)
|
|
||||||
ret.x.Sub(ret.x, a2)
|
|
||||||
ret.x.Sub(ret.x, ret.y)
|
|
||||||
a2.MulTau(a2, pool)
|
|
||||||
ret.y.Add(ret.y, a2)
|
|
||||||
|
|
||||||
a2.Put(pool)
|
|
||||||
t3.Put(pool)
|
|
||||||
t2.Put(pool)
|
|
||||||
t.Put(pool)
|
|
||||||
}
|
|
||||||
|
|
||||||
// sixuPlus2NAF is 6u+2 in non-adjacent form.
|
|
||||||
var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, -1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 1}
|
|
||||||
|
|
||||||
// miller implements the Miller loop for calculating the Optimal Ate pairing.
|
|
||||||
// See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf
|
|
||||||
func miller(q *twistPoint, p *curvePoint, pool *bnPool) *gfP12 {
|
|
||||||
ret := newGFp12(pool)
|
|
||||||
ret.SetOne()
|
|
||||||
|
|
||||||
aAffine := newTwistPoint(pool)
|
|
||||||
aAffine.Set(q)
|
|
||||||
aAffine.MakeAffine(pool)
|
|
||||||
|
|
||||||
bAffine := newCurvePoint(pool)
|
|
||||||
bAffine.Set(p)
|
|
||||||
bAffine.MakeAffine(pool)
|
|
||||||
|
|
||||||
minusA := newTwistPoint(pool)
|
|
||||||
minusA.Negative(aAffine, pool)
|
|
||||||
|
|
||||||
r := newTwistPoint(pool)
|
|
||||||
r.Set(aAffine)
|
|
||||||
|
|
||||||
r2 := newGFp2(pool)
|
|
||||||
r2.Square(aAffine.y, pool)
|
|
||||||
|
|
||||||
for i := len(sixuPlus2NAF) - 1; i > 0; i-- {
|
|
||||||
a, b, c, newR := lineFunctionDouble(r, bAffine, pool)
|
|
||||||
if i != len(sixuPlus2NAF)-1 {
|
|
||||||
ret.Square(ret, pool)
|
|
||||||
}
|
|
||||||
|
|
||||||
mulLine(ret, a, b, c, pool)
|
|
||||||
a.Put(pool)
|
|
||||||
b.Put(pool)
|
|
||||||
c.Put(pool)
|
|
||||||
r.Put(pool)
|
|
||||||
r = newR
|
|
||||||
|
|
||||||
switch sixuPlus2NAF[i-1] {
|
|
||||||
case 1:
|
|
||||||
a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2, pool)
|
|
||||||
case -1:
|
|
||||||
a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2, pool)
|
|
||||||
default:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
mulLine(ret, a, b, c, pool)
|
|
||||||
a.Put(pool)
|
|
||||||
b.Put(pool)
|
|
||||||
c.Put(pool)
|
|
||||||
r.Put(pool)
|
|
||||||
r = newR
|
|
||||||
}
|
|
||||||
|
|
||||||
// In order to calculate Q1 we have to convert q from the sextic twist
|
|
||||||
// to the full GF(p^12) group, apply the Frobenius there, and convert
|
|
||||||
// back.
|
|
||||||
//
|
|
||||||
// The twist isomorphism is (x', y') -> (xω², yω³). If we consider just
|
|
||||||
// x for a moment, then after applying the Frobenius, we have x̄ω^(2p)
|
|
||||||
// where x̄ is the conjugate of x. If we are going to apply the inverse
|
|
||||||
// isomorphism we need a value with a single coefficient of ω² so we
|
|
||||||
// rewrite this as x̄ω^(2p-2)ω². ξ⁶ = ω and, due to the construction of
|
|
||||||
// p, 2p-2 is a multiple of six. Therefore we can rewrite as
|
|
||||||
// x̄ξ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the
|
|
||||||
// ω².
|
|
||||||
//
|
|
||||||
// A similar argument can be made for the y value.
|
|
||||||
|
|
||||||
q1 := newTwistPoint(pool)
|
|
||||||
q1.x.Conjugate(aAffine.x)
|
|
||||||
q1.x.Mul(q1.x, xiToPMinus1Over3, pool)
|
|
||||||
q1.y.Conjugate(aAffine.y)
|
|
||||||
q1.y.Mul(q1.y, xiToPMinus1Over2, pool)
|
|
||||||
q1.z.SetOne()
|
|
||||||
q1.t.SetOne()
|
|
||||||
|
|
||||||
// For Q2 we are applying the p² Frobenius. The two conjugations cancel
|
|
||||||
// out and we are left only with the factors from the isomorphism. In
|
|
||||||
// the case of x, we end up with a pure number which is why
|
|
||||||
// xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We
|
|
||||||
// ignore this to end up with -Q2.
|
|
||||||
|
|
||||||
minusQ2 := newTwistPoint(pool)
|
|
||||||
minusQ2.x.MulScalar(aAffine.x, xiToPSquaredMinus1Over3)
|
|
||||||
minusQ2.y.Set(aAffine.y)
|
|
||||||
minusQ2.z.SetOne()
|
|
||||||
minusQ2.t.SetOne()
|
|
||||||
|
|
||||||
r2.Square(q1.y, pool)
|
|
||||||
a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2, pool)
|
|
||||||
mulLine(ret, a, b, c, pool)
|
|
||||||
a.Put(pool)
|
|
||||||
b.Put(pool)
|
|
||||||
c.Put(pool)
|
|
||||||
r.Put(pool)
|
|
||||||
r = newR
|
|
||||||
|
|
||||||
r2.Square(minusQ2.y, pool)
|
|
||||||
a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2, pool)
|
|
||||||
mulLine(ret, a, b, c, pool)
|
|
||||||
a.Put(pool)
|
|
||||||
b.Put(pool)
|
|
||||||
c.Put(pool)
|
|
||||||
r.Put(pool)
|
|
||||||
r = newR
|
|
||||||
|
|
||||||
aAffine.Put(pool)
|
|
||||||
bAffine.Put(pool)
|
|
||||||
minusA.Put(pool)
|
|
||||||
r.Put(pool)
|
|
||||||
r2.Put(pool)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
// finalExponentiation computes the (p¹²-1)/Order-th power of an element of
|
|
||||||
// GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from
|
|
||||||
// http://cryptojedi.org/papers/dclxvi-20100714.pdf)
|
|
||||||
func finalExponentiation(in *gfP12, pool *bnPool) *gfP12 {
|
|
||||||
t1 := newGFp12(pool)
|
|
||||||
|
|
||||||
// This is the p^6-Frobenius
|
|
||||||
t1.x.Negative(in.x)
|
|
||||||
t1.y.Set(in.y)
|
|
||||||
|
|
||||||
inv := newGFp12(pool)
|
|
||||||
inv.Invert(in, pool)
|
|
||||||
t1.Mul(t1, inv, pool)
|
|
||||||
|
|
||||||
t2 := newGFp12(pool).FrobeniusP2(t1, pool)
|
|
||||||
t1.Mul(t1, t2, pool)
|
|
||||||
|
|
||||||
fp := newGFp12(pool).Frobenius(t1, pool)
|
|
||||||
fp2 := newGFp12(pool).FrobeniusP2(t1, pool)
|
|
||||||
fp3 := newGFp12(pool).Frobenius(fp2, pool)
|
|
||||||
|
|
||||||
fu, fu2, fu3 := newGFp12(pool), newGFp12(pool), newGFp12(pool)
|
|
||||||
fu.Exp(t1, u, pool)
|
|
||||||
fu2.Exp(fu, u, pool)
|
|
||||||
fu3.Exp(fu2, u, pool)
|
|
||||||
|
|
||||||
y3 := newGFp12(pool).Frobenius(fu, pool)
|
|
||||||
fu2p := newGFp12(pool).Frobenius(fu2, pool)
|
|
||||||
fu3p := newGFp12(pool).Frobenius(fu3, pool)
|
|
||||||
y2 := newGFp12(pool).FrobeniusP2(fu2, pool)
|
|
||||||
|
|
||||||
y0 := newGFp12(pool)
|
|
||||||
y0.Mul(fp, fp2, pool)
|
|
||||||
y0.Mul(y0, fp3, pool)
|
|
||||||
|
|
||||||
y1, y4, y5 := newGFp12(pool), newGFp12(pool), newGFp12(pool)
|
|
||||||
y1.Conjugate(t1)
|
|
||||||
y5.Conjugate(fu2)
|
|
||||||
y3.Conjugate(y3)
|
|
||||||
y4.Mul(fu, fu2p, pool)
|
|
||||||
y4.Conjugate(y4)
|
|
||||||
|
|
||||||
y6 := newGFp12(pool)
|
|
||||||
y6.Mul(fu3, fu3p, pool)
|
|
||||||
y6.Conjugate(y6)
|
|
||||||
|
|
||||||
t0 := newGFp12(pool)
|
|
||||||
t0.Square(y6, pool)
|
|
||||||
t0.Mul(t0, y4, pool)
|
|
||||||
t0.Mul(t0, y5, pool)
|
|
||||||
t1.Mul(y3, y5, pool)
|
|
||||||
t1.Mul(t1, t0, pool)
|
|
||||||
t0.Mul(t0, y2, pool)
|
|
||||||
t1.Square(t1, pool)
|
|
||||||
t1.Mul(t1, t0, pool)
|
|
||||||
t1.Square(t1, pool)
|
|
||||||
t0.Mul(t1, y1, pool)
|
|
||||||
t1.Mul(t1, y0, pool)
|
|
||||||
t0.Square(t0, pool)
|
|
||||||
t0.Mul(t0, t1, pool)
|
|
||||||
|
|
||||||
inv.Put(pool)
|
|
||||||
t1.Put(pool)
|
|
||||||
t2.Put(pool)
|
|
||||||
fp.Put(pool)
|
|
||||||
fp2.Put(pool)
|
|
||||||
fp3.Put(pool)
|
|
||||||
fu.Put(pool)
|
|
||||||
fu2.Put(pool)
|
|
||||||
fu3.Put(pool)
|
|
||||||
fu2p.Put(pool)
|
|
||||||
fu3p.Put(pool)
|
|
||||||
y0.Put(pool)
|
|
||||||
y1.Put(pool)
|
|
||||||
y2.Put(pool)
|
|
||||||
y3.Put(pool)
|
|
||||||
y4.Put(pool)
|
|
||||||
y5.Put(pool)
|
|
||||||
y6.Put(pool)
|
|
||||||
|
|
||||||
return t0
|
|
||||||
}
|
|
||||||
|
|
||||||
func optimalAte(a *twistPoint, b *curvePoint, pool *bnPool) *gfP12 {
|
|
||||||
e := miller(a, b, pool)
|
|
||||||
ret := finalExponentiation(e, pool)
|
|
||||||
e.Put(pool)
|
|
||||||
|
|
||||||
if a.IsInfinity() || b.IsInfinity() {
|
|
||||||
ret.SetOne()
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
|
249
vendor/golang.org/x/crypto/bn256/twist.go
generated
vendored
249
vendor/golang.org/x/crypto/bn256/twist.go
generated
vendored
|
@ -1,249 +0,0 @@
|
||||||
// Copyright 2012 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 bn256
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/big"
|
|
||||||
)
|
|
||||||
|
|
||||||
// twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are
|
|
||||||
// kept in Jacobian form and t=z² when valid. The group G₂ is the set of
|
|
||||||
// n-torsion points of this curve over GF(p²) (where n = Order)
|
|
||||||
type twistPoint struct {
|
|
||||||
x, y, z, t *gfP2
|
|
||||||
}
|
|
||||||
|
|
||||||
var twistB = &gfP2{
|
|
||||||
bigFromBase10("6500054969564660373279643874235990574282535810762300357187714502686418407178"),
|
|
||||||
bigFromBase10("45500384786952622612957507119651934019977750675336102500314001518804928850249"),
|
|
||||||
}
|
|
||||||
|
|
||||||
// twistGen is the generator of group G₂.
|
|
||||||
var twistGen = &twistPoint{
|
|
||||||
&gfP2{
|
|
||||||
bigFromBase10("21167961636542580255011770066570541300993051739349375019639421053990175267184"),
|
|
||||||
bigFromBase10("64746500191241794695844075326670126197795977525365406531717464316923369116492"),
|
|
||||||
},
|
|
||||||
&gfP2{
|
|
||||||
bigFromBase10("20666913350058776956210519119118544732556678129809273996262322366050359951122"),
|
|
||||||
bigFromBase10("17778617556404439934652658462602675281523610326338642107814333856843981424549"),
|
|
||||||
},
|
|
||||||
&gfP2{
|
|
||||||
bigFromBase10("0"),
|
|
||||||
bigFromBase10("1"),
|
|
||||||
},
|
|
||||||
&gfP2{
|
|
||||||
bigFromBase10("0"),
|
|
||||||
bigFromBase10("1"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func newTwistPoint(pool *bnPool) *twistPoint {
|
|
||||||
return &twistPoint{
|
|
||||||
newGFp2(pool),
|
|
||||||
newGFp2(pool),
|
|
||||||
newGFp2(pool),
|
|
||||||
newGFp2(pool),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *twistPoint) String() string {
|
|
||||||
return "(" + c.x.String() + ", " + c.y.String() + ", " + c.z.String() + ")"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *twistPoint) Put(pool *bnPool) {
|
|
||||||
c.x.Put(pool)
|
|
||||||
c.y.Put(pool)
|
|
||||||
c.z.Put(pool)
|
|
||||||
c.t.Put(pool)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *twistPoint) Set(a *twistPoint) {
|
|
||||||
c.x.Set(a.x)
|
|
||||||
c.y.Set(a.y)
|
|
||||||
c.z.Set(a.z)
|
|
||||||
c.t.Set(a.t)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsOnCurve returns true iff c is on the curve where c must be in affine form.
|
|
||||||
func (c *twistPoint) IsOnCurve() bool {
|
|
||||||
pool := new(bnPool)
|
|
||||||
yy := newGFp2(pool).Square(c.y, pool)
|
|
||||||
xxx := newGFp2(pool).Square(c.x, pool)
|
|
||||||
xxx.Mul(xxx, c.x, pool)
|
|
||||||
yy.Sub(yy, xxx)
|
|
||||||
yy.Sub(yy, twistB)
|
|
||||||
yy.Minimal()
|
|
||||||
return yy.x.Sign() == 0 && yy.y.Sign() == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *twistPoint) SetInfinity() {
|
|
||||||
c.z.SetZero()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *twistPoint) IsInfinity() bool {
|
|
||||||
return c.z.IsZero()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) {
|
|
||||||
// For additional comments, see the same function in curve.go.
|
|
||||||
|
|
||||||
if a.IsInfinity() {
|
|
||||||
c.Set(b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if b.IsInfinity() {
|
|
||||||
c.Set(a)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
|
|
||||||
z1z1 := newGFp2(pool).Square(a.z, pool)
|
|
||||||
z2z2 := newGFp2(pool).Square(b.z, pool)
|
|
||||||
u1 := newGFp2(pool).Mul(a.x, z2z2, pool)
|
|
||||||
u2 := newGFp2(pool).Mul(b.x, z1z1, pool)
|
|
||||||
|
|
||||||
t := newGFp2(pool).Mul(b.z, z2z2, pool)
|
|
||||||
s1 := newGFp2(pool).Mul(a.y, t, pool)
|
|
||||||
|
|
||||||
t.Mul(a.z, z1z1, pool)
|
|
||||||
s2 := newGFp2(pool).Mul(b.y, t, pool)
|
|
||||||
|
|
||||||
h := newGFp2(pool).Sub(u2, u1)
|
|
||||||
xEqual := h.IsZero()
|
|
||||||
|
|
||||||
t.Add(h, h)
|
|
||||||
i := newGFp2(pool).Square(t, pool)
|
|
||||||
j := newGFp2(pool).Mul(h, i, pool)
|
|
||||||
|
|
||||||
t.Sub(s2, s1)
|
|
||||||
yEqual := t.IsZero()
|
|
||||||
if xEqual && yEqual {
|
|
||||||
c.Double(a, pool)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
r := newGFp2(pool).Add(t, t)
|
|
||||||
|
|
||||||
v := newGFp2(pool).Mul(u1, i, pool)
|
|
||||||
|
|
||||||
t4 := newGFp2(pool).Square(r, pool)
|
|
||||||
t.Add(v, v)
|
|
||||||
t6 := newGFp2(pool).Sub(t4, j)
|
|
||||||
c.x.Sub(t6, t)
|
|
||||||
|
|
||||||
t.Sub(v, c.x) // t7
|
|
||||||
t4.Mul(s1, j, pool) // t8
|
|
||||||
t6.Add(t4, t4) // t9
|
|
||||||
t4.Mul(r, t, pool) // t10
|
|
||||||
c.y.Sub(t4, t6)
|
|
||||||
|
|
||||||
t.Add(a.z, b.z) // t11
|
|
||||||
t4.Square(t, pool) // t12
|
|
||||||
t.Sub(t4, z1z1) // t13
|
|
||||||
t4.Sub(t, z2z2) // t14
|
|
||||||
c.z.Mul(t4, h, pool)
|
|
||||||
|
|
||||||
z1z1.Put(pool)
|
|
||||||
z2z2.Put(pool)
|
|
||||||
u1.Put(pool)
|
|
||||||
u2.Put(pool)
|
|
||||||
t.Put(pool)
|
|
||||||
s1.Put(pool)
|
|
||||||
s2.Put(pool)
|
|
||||||
h.Put(pool)
|
|
||||||
i.Put(pool)
|
|
||||||
j.Put(pool)
|
|
||||||
r.Put(pool)
|
|
||||||
v.Put(pool)
|
|
||||||
t4.Put(pool)
|
|
||||||
t6.Put(pool)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *twistPoint) Double(a *twistPoint, pool *bnPool) {
|
|
||||||
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
|
|
||||||
A := newGFp2(pool).Square(a.x, pool)
|
|
||||||
B := newGFp2(pool).Square(a.y, pool)
|
|
||||||
C := newGFp2(pool).Square(B, pool)
|
|
||||||
|
|
||||||
t := newGFp2(pool).Add(a.x, B)
|
|
||||||
t2 := newGFp2(pool).Square(t, pool)
|
|
||||||
t.Sub(t2, A)
|
|
||||||
t2.Sub(t, C)
|
|
||||||
d := newGFp2(pool).Add(t2, t2)
|
|
||||||
t.Add(A, A)
|
|
||||||
e := newGFp2(pool).Add(t, A)
|
|
||||||
f := newGFp2(pool).Square(e, pool)
|
|
||||||
|
|
||||||
t.Add(d, d)
|
|
||||||
c.x.Sub(f, t)
|
|
||||||
|
|
||||||
t.Add(C, C)
|
|
||||||
t2.Add(t, t)
|
|
||||||
t.Add(t2, t2)
|
|
||||||
c.y.Sub(d, c.x)
|
|
||||||
t2.Mul(e, c.y, pool)
|
|
||||||
c.y.Sub(t2, t)
|
|
||||||
|
|
||||||
t.Mul(a.y, a.z, pool)
|
|
||||||
c.z.Add(t, t)
|
|
||||||
|
|
||||||
A.Put(pool)
|
|
||||||
B.Put(pool)
|
|
||||||
C.Put(pool)
|
|
||||||
t.Put(pool)
|
|
||||||
t2.Put(pool)
|
|
||||||
d.Put(pool)
|
|
||||||
e.Put(pool)
|
|
||||||
f.Put(pool)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint {
|
|
||||||
sum := newTwistPoint(pool)
|
|
||||||
sum.SetInfinity()
|
|
||||||
t := newTwistPoint(pool)
|
|
||||||
|
|
||||||
for i := scalar.BitLen(); i >= 0; i-- {
|
|
||||||
t.Double(sum, pool)
|
|
||||||
if scalar.Bit(i) != 0 {
|
|
||||||
sum.Add(t, a, pool)
|
|
||||||
} else {
|
|
||||||
sum.Set(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Set(sum)
|
|
||||||
sum.Put(pool)
|
|
||||||
t.Put(pool)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint {
|
|
||||||
if c.z.IsOne() {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
zInv := newGFp2(pool).Invert(c.z, pool)
|
|
||||||
t := newGFp2(pool).Mul(c.y, zInv, pool)
|
|
||||||
zInv2 := newGFp2(pool).Square(zInv, pool)
|
|
||||||
c.y.Mul(t, zInv2, pool)
|
|
||||||
t.Mul(c.x, zInv2, pool)
|
|
||||||
c.x.Set(t)
|
|
||||||
c.z.SetOne()
|
|
||||||
c.t.SetOne()
|
|
||||||
|
|
||||||
zInv.Put(pool)
|
|
||||||
t.Put(pool)
|
|
||||||
zInv2.Put(pool)
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) {
|
|
||||||
c.x.Set(a.x)
|
|
||||||
c.y.SetZero()
|
|
||||||
c.y.Sub(c.y, a.y)
|
|
||||||
c.z.Set(a.z)
|
|
||||||
c.t.SetZero()
|
|
||||||
}
|
|
526
vendor/golang.org/x/crypto/cast5/cast5.go
generated
vendored
526
vendor/golang.org/x/crypto/cast5/cast5.go
generated
vendored
|
@ -1,526 +0,0 @@
|
||||||
// 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 cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common
|
|
||||||
// OpenPGP cipher.
|
|
||||||
package cast5 // import "golang.org/x/crypto/cast5"
|
|
||||||
|
|
||||||
import "errors"
|
|
||||||
|
|
||||||
const BlockSize = 8
|
|
||||||
const KeySize = 16
|
|
||||||
|
|
||||||
type Cipher struct {
|
|
||||||
masking [16]uint32
|
|
||||||
rotate [16]uint8
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewCipher(key []byte) (c *Cipher, err error) {
|
|
||||||
if len(key) != KeySize {
|
|
||||||
return nil, errors.New("CAST5: keys must be 16 bytes")
|
|
||||||
}
|
|
||||||
|
|
||||||
c = new(Cipher)
|
|
||||||
c.keySchedule(key)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Cipher) BlockSize() int {
|
|
||||||
return BlockSize
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Cipher) Encrypt(dst, src []byte) {
|
|
||||||
l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
|
|
||||||
r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
|
|
||||||
|
|
||||||
l, r = r, l^f1(r, c.masking[0], c.rotate[0])
|
|
||||||
l, r = r, l^f2(r, c.masking[1], c.rotate[1])
|
|
||||||
l, r = r, l^f3(r, c.masking[2], c.rotate[2])
|
|
||||||
l, r = r, l^f1(r, c.masking[3], c.rotate[3])
|
|
||||||
|
|
||||||
l, r = r, l^f2(r, c.masking[4], c.rotate[4])
|
|
||||||
l, r = r, l^f3(r, c.masking[5], c.rotate[5])
|
|
||||||
l, r = r, l^f1(r, c.masking[6], c.rotate[6])
|
|
||||||
l, r = r, l^f2(r, c.masking[7], c.rotate[7])
|
|
||||||
|
|
||||||
l, r = r, l^f3(r, c.masking[8], c.rotate[8])
|
|
||||||
l, r = r, l^f1(r, c.masking[9], c.rotate[9])
|
|
||||||
l, r = r, l^f2(r, c.masking[10], c.rotate[10])
|
|
||||||
l, r = r, l^f3(r, c.masking[11], c.rotate[11])
|
|
||||||
|
|
||||||
l, r = r, l^f1(r, c.masking[12], c.rotate[12])
|
|
||||||
l, r = r, l^f2(r, c.masking[13], c.rotate[13])
|
|
||||||
l, r = r, l^f3(r, c.masking[14], c.rotate[14])
|
|
||||||
l, r = r, l^f1(r, c.masking[15], c.rotate[15])
|
|
||||||
|
|
||||||
dst[0] = uint8(r >> 24)
|
|
||||||
dst[1] = uint8(r >> 16)
|
|
||||||
dst[2] = uint8(r >> 8)
|
|
||||||
dst[3] = uint8(r)
|
|
||||||
dst[4] = uint8(l >> 24)
|
|
||||||
dst[5] = uint8(l >> 16)
|
|
||||||
dst[6] = uint8(l >> 8)
|
|
||||||
dst[7] = uint8(l)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Cipher) Decrypt(dst, src []byte) {
|
|
||||||
l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
|
|
||||||
r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
|
|
||||||
|
|
||||||
l, r = r, l^f1(r, c.masking[15], c.rotate[15])
|
|
||||||
l, r = r, l^f3(r, c.masking[14], c.rotate[14])
|
|
||||||
l, r = r, l^f2(r, c.masking[13], c.rotate[13])
|
|
||||||
l, r = r, l^f1(r, c.masking[12], c.rotate[12])
|
|
||||||
|
|
||||||
l, r = r, l^f3(r, c.masking[11], c.rotate[11])
|
|
||||||
l, r = r, l^f2(r, c.masking[10], c.rotate[10])
|
|
||||||
l, r = r, l^f1(r, c.masking[9], c.rotate[9])
|
|
||||||
l, r = r, l^f3(r, c.masking[8], c.rotate[8])
|
|
||||||
|
|
||||||
l, r = r, l^f2(r, c.masking[7], c.rotate[7])
|
|
||||||
l, r = r, l^f1(r, c.masking[6], c.rotate[6])
|
|
||||||
l, r = r, l^f3(r, c.masking[5], c.rotate[5])
|
|
||||||
l, r = r, l^f2(r, c.masking[4], c.rotate[4])
|
|
||||||
|
|
||||||
l, r = r, l^f1(r, c.masking[3], c.rotate[3])
|
|
||||||
l, r = r, l^f3(r, c.masking[2], c.rotate[2])
|
|
||||||
l, r = r, l^f2(r, c.masking[1], c.rotate[1])
|
|
||||||
l, r = r, l^f1(r, c.masking[0], c.rotate[0])
|
|
||||||
|
|
||||||
dst[0] = uint8(r >> 24)
|
|
||||||
dst[1] = uint8(r >> 16)
|
|
||||||
dst[2] = uint8(r >> 8)
|
|
||||||
dst[3] = uint8(r)
|
|
||||||
dst[4] = uint8(l >> 24)
|
|
||||||
dst[5] = uint8(l >> 16)
|
|
||||||
dst[6] = uint8(l >> 8)
|
|
||||||
dst[7] = uint8(l)
|
|
||||||
}
|
|
||||||
|
|
||||||
type keyScheduleA [4][7]uint8
|
|
||||||
type keyScheduleB [4][5]uint8
|
|
||||||
|
|
||||||
// keyScheduleRound contains the magic values for a round of the key schedule.
|
|
||||||
// The keyScheduleA deals with the lines like:
|
|
||||||
// z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8]
|
|
||||||
// Conceptually, both x and z are in the same array, x first. The first
|
|
||||||
// element describes which word of this array gets written to and the
|
|
||||||
// second, which word gets read. So, for the line above, it's "4, 0", because
|
|
||||||
// it's writing to the first word of z, which, being after x, is word 4, and
|
|
||||||
// reading from the first word of x: word 0.
|
|
||||||
//
|
|
||||||
// Next are the indexes into the S-boxes. Now the array is treated as bytes. So
|
|
||||||
// "xD" is 0xd. The first byte of z is written as "16 + 0", just to be clear
|
|
||||||
// that it's z that we're indexing.
|
|
||||||
//
|
|
||||||
// keyScheduleB deals with lines like:
|
|
||||||
// K1 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2]
|
|
||||||
// "K1" is ignored because key words are always written in order. So the five
|
|
||||||
// elements are the S-box indexes. They use the same form as in keyScheduleA,
|
|
||||||
// above.
|
|
||||||
|
|
||||||
type keyScheduleRound struct{}
|
|
||||||
type keySchedule []keyScheduleRound
|
|
||||||
|
|
||||||
var schedule = []struct {
|
|
||||||
a keyScheduleA
|
|
||||||
b keyScheduleB
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
keyScheduleA{
|
|
||||||
{4, 0, 0xd, 0xf, 0xc, 0xe, 0x8},
|
|
||||||
{5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
|
|
||||||
{6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
|
|
||||||
{7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
|
|
||||||
},
|
|
||||||
keyScheduleB{
|
|
||||||
{16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2},
|
|
||||||
{16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6},
|
|
||||||
{16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9},
|
|
||||||
{16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
keyScheduleA{
|
|
||||||
{0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
|
|
||||||
{1, 4, 0, 2, 1, 3, 16 + 2},
|
|
||||||
{2, 5, 7, 6, 5, 4, 16 + 1},
|
|
||||||
{3, 7, 0xa, 9, 0xb, 8, 16 + 3},
|
|
||||||
},
|
|
||||||
keyScheduleB{
|
|
||||||
{3, 2, 0xc, 0xd, 8},
|
|
||||||
{1, 0, 0xe, 0xf, 0xd},
|
|
||||||
{7, 6, 8, 9, 3},
|
|
||||||
{5, 4, 0xa, 0xb, 7},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
keyScheduleA{
|
|
||||||
{4, 0, 0xd, 0xf, 0xc, 0xe, 8},
|
|
||||||
{5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
|
|
||||||
{6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
|
|
||||||
{7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
|
|
||||||
},
|
|
||||||
keyScheduleB{
|
|
||||||
{16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9},
|
|
||||||
{16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc},
|
|
||||||
{16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2},
|
|
||||||
{16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
keyScheduleA{
|
|
||||||
{0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
|
|
||||||
{1, 4, 0, 2, 1, 3, 16 + 2},
|
|
||||||
{2, 5, 7, 6, 5, 4, 16 + 1},
|
|
||||||
{3, 7, 0xa, 9, 0xb, 8, 16 + 3},
|
|
||||||
},
|
|
||||||
keyScheduleB{
|
|
||||||
{8, 9, 7, 6, 3},
|
|
||||||
{0xa, 0xb, 5, 4, 7},
|
|
||||||
{0xc, 0xd, 3, 2, 8},
|
|
||||||
{0xe, 0xf, 1, 0, 0xd},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Cipher) keySchedule(in []byte) {
|
|
||||||
var t [8]uint32
|
|
||||||
var k [32]uint32
|
|
||||||
|
|
||||||
for i := 0; i < 4; i++ {
|
|
||||||
j := i * 4
|
|
||||||
t[i] = uint32(in[j])<<24 | uint32(in[j+1])<<16 | uint32(in[j+2])<<8 | uint32(in[j+3])
|
|
||||||
}
|
|
||||||
|
|
||||||
x := []byte{6, 7, 4, 5}
|
|
||||||
ki := 0
|
|
||||||
|
|
||||||
for half := 0; half < 2; half++ {
|
|
||||||
for _, round := range schedule {
|
|
||||||
for j := 0; j < 4; j++ {
|
|
||||||
var a [7]uint8
|
|
||||||
copy(a[:], round.a[j][:])
|
|
||||||
w := t[a[1]]
|
|
||||||
w ^= sBox[4][(t[a[2]>>2]>>(24-8*(a[2]&3)))&0xff]
|
|
||||||
w ^= sBox[5][(t[a[3]>>2]>>(24-8*(a[3]&3)))&0xff]
|
|
||||||
w ^= sBox[6][(t[a[4]>>2]>>(24-8*(a[4]&3)))&0xff]
|
|
||||||
w ^= sBox[7][(t[a[5]>>2]>>(24-8*(a[5]&3)))&0xff]
|
|
||||||
w ^= sBox[x[j]][(t[a[6]>>2]>>(24-8*(a[6]&3)))&0xff]
|
|
||||||
t[a[0]] = w
|
|
||||||
}
|
|
||||||
|
|
||||||
for j := 0; j < 4; j++ {
|
|
||||||
var b [5]uint8
|
|
||||||
copy(b[:], round.b[j][:])
|
|
||||||
w := sBox[4][(t[b[0]>>2]>>(24-8*(b[0]&3)))&0xff]
|
|
||||||
w ^= sBox[5][(t[b[1]>>2]>>(24-8*(b[1]&3)))&0xff]
|
|
||||||
w ^= sBox[6][(t[b[2]>>2]>>(24-8*(b[2]&3)))&0xff]
|
|
||||||
w ^= sBox[7][(t[b[3]>>2]>>(24-8*(b[3]&3)))&0xff]
|
|
||||||
w ^= sBox[4+j][(t[b[4]>>2]>>(24-8*(b[4]&3)))&0xff]
|
|
||||||
k[ki] = w
|
|
||||||
ki++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < 16; i++ {
|
|
||||||
c.masking[i] = k[i]
|
|
||||||
c.rotate[i] = uint8(k[16+i] & 0x1f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// These are the three 'f' functions. See RFC 2144, section 2.2.
|
|
||||||
func f1(d, m uint32, r uint8) uint32 {
|
|
||||||
t := m + d
|
|
||||||
I := (t << r) | (t >> (32 - r))
|
|
||||||
return ((sBox[0][I>>24] ^ sBox[1][(I>>16)&0xff]) - sBox[2][(I>>8)&0xff]) + sBox[3][I&0xff]
|
|
||||||
}
|
|
||||||
|
|
||||||
func f2(d, m uint32, r uint8) uint32 {
|
|
||||||
t := m ^ d
|
|
||||||
I := (t << r) | (t >> (32 - r))
|
|
||||||
return ((sBox[0][I>>24] - sBox[1][(I>>16)&0xff]) + sBox[2][(I>>8)&0xff]) ^ sBox[3][I&0xff]
|
|
||||||
}
|
|
||||||
|
|
||||||
func f3(d, m uint32, r uint8) uint32 {
|
|
||||||
t := m - d
|
|
||||||
I := (t << r) | (t >> (32 - r))
|
|
||||||
return ((sBox[0][I>>24] + sBox[1][(I>>16)&0xff]) ^ sBox[2][(I>>8)&0xff]) - sBox[3][I&0xff]
|
|
||||||
}
|
|
||||||
|
|
||||||
var sBox = [8][256]uint32{
|
|
||||||
{
|
|
||||||
0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
|
|
||||||
0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
|
|
||||||
0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
|
|
||||||
0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
|
|
||||||
0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
|
|
||||||
0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
|
|
||||||
0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
|
|
||||||
0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
|
|
||||||
0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
|
|
||||||
0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
|
|
||||||
0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
|
|
||||||
0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
|
|
||||||
0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
|
|
||||||
0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
|
|
||||||
0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
|
|
||||||
0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
|
|
||||||
0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
|
|
||||||
0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
|
|
||||||
0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
|
|
||||||
0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
|
|
||||||
0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
|
|
||||||
0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
|
|
||||||
0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
|
|
||||||
0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
|
|
||||||
0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
|
|
||||||
0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
|
|
||||||
0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
|
|
||||||
0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
|
|
||||||
0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
|
|
||||||
0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
|
|
||||||
0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
|
|
||||||
0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
|
|
||||||
0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
|
|
||||||
0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
|
|
||||||
0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
|
|
||||||
0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
|
|
||||||
0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
|
|
||||||
0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
|
|
||||||
0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
|
|
||||||
0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
|
|
||||||
0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
|
|
||||||
0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
|
|
||||||
0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
|
|
||||||
0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
|
|
||||||
0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
|
|
||||||
0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
|
|
||||||
0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
|
|
||||||
0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
|
|
||||||
0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
|
|
||||||
0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
|
|
||||||
0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
|
|
||||||
0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
|
|
||||||
0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
|
|
||||||
0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
|
|
||||||
0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
|
|
||||||
0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
|
|
||||||
0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
|
|
||||||
0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
|
|
||||||
0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
|
|
||||||
0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
|
|
||||||
0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
|
|
||||||
0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
|
|
||||||
0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
|
|
||||||
0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
|
|
||||||
0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
|
|
||||||
0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
|
|
||||||
0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
|
|
||||||
0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
|
|
||||||
0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
|
|
||||||
0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
|
|
||||||
0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
|
|
||||||
0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
|
|
||||||
0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
|
|
||||||
0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
|
|
||||||
0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
|
|
||||||
0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
|
|
||||||
0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
|
|
||||||
0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
|
|
||||||
0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
|
|
||||||
0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
|
|
||||||
0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
|
|
||||||
0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
|
|
||||||
0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
|
|
||||||
0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
|
|
||||||
0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
|
|
||||||
0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
|
|
||||||
0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
|
|
||||||
0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
|
|
||||||
0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
|
|
||||||
0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
|
|
||||||
0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
|
|
||||||
0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
|
|
||||||
0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
|
|
||||||
0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
|
|
||||||
0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
|
|
||||||
0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
|
|
||||||
0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
|
|
||||||
0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
|
|
||||||
0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
|
|
||||||
0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
|
|
||||||
0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
|
|
||||||
0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
|
|
||||||
0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
|
|
||||||
0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
|
|
||||||
0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
|
|
||||||
0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
|
|
||||||
0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
|
|
||||||
0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
|
|
||||||
0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
|
|
||||||
0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
|
|
||||||
0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
|
|
||||||
0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
|
|
||||||
0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
|
|
||||||
0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
|
|
||||||
0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
|
|
||||||
0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
|
|
||||||
0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
|
|
||||||
0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
|
|
||||||
0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
|
|
||||||
0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
|
|
||||||
0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
|
|
||||||
0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
|
|
||||||
0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
|
|
||||||
0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
|
|
||||||
0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
|
|
||||||
0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
|
|
||||||
0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
|
|
||||||
0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
|
|
||||||
0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
|
|
||||||
0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
|
|
||||||
0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
|
|
||||||
0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
|
|
||||||
0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
|
|
||||||
0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
|
|
||||||
0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
|
|
||||||
0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
|
|
||||||
0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
|
|
||||||
0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
|
|
||||||
0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
|
|
||||||
0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
|
|
||||||
0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
|
|
||||||
0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
|
|
||||||
0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
|
|
||||||
0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
|
|
||||||
0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
|
|
||||||
0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
|
|
||||||
0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
|
|
||||||
0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
|
|
||||||
0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
|
|
||||||
0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
|
|
||||||
0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
|
|
||||||
0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
|
|
||||||
0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
|
|
||||||
0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
|
|
||||||
0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
|
|
||||||
0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
|
|
||||||
0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
|
|
||||||
0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
|
|
||||||
0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
|
|
||||||
0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
|
|
||||||
0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
|
|
||||||
0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
|
|
||||||
0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
|
|
||||||
0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
|
|
||||||
0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
|
|
||||||
0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
|
|
||||||
0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
|
|
||||||
0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
|
|
||||||
0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
|
|
||||||
0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
|
|
||||||
0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
|
|
||||||
0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
|
|
||||||
0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
|
|
||||||
0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
|
|
||||||
0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
|
|
||||||
0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
|
|
||||||
0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
|
|
||||||
0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
|
|
||||||
0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
|
|
||||||
0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
|
|
||||||
0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
|
|
||||||
0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
|
|
||||||
0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
|
|
||||||
0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
|
|
||||||
0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
|
|
||||||
0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
|
|
||||||
0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
|
|
||||||
0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
|
|
||||||
0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
|
|
||||||
0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
|
|
||||||
0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
|
|
||||||
0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
|
|
||||||
0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
|
|
||||||
0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
|
|
||||||
0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
|
|
||||||
0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
|
|
||||||
0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
|
|
||||||
0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
|
|
||||||
0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
|
|
||||||
0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
|
|
||||||
0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
|
|
||||||
0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
|
|
||||||
0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
|
|
||||||
0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
|
|
||||||
0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
|
|
||||||
0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
|
|
||||||
0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
|
|
||||||
0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
|
|
||||||
0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
|
|
||||||
0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
|
|
||||||
0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
|
|
||||||
0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
|
|
||||||
0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
|
|
||||||
0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
|
|
||||||
0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
|
|
||||||
0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
|
|
||||||
0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
|
|
||||||
0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
|
|
||||||
0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
|
|
||||||
0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
|
|
||||||
0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
|
|
||||||
0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
|
|
||||||
0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
|
|
||||||
0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
|
|
||||||
0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
|
|
||||||
0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
|
|
||||||
0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
|
|
||||||
0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
|
|
||||||
0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
|
|
||||||
0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
|
|
||||||
0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
|
|
||||||
0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
|
|
||||||
0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
|
|
||||||
0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
|
|
||||||
0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
|
|
||||||
0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
|
|
||||||
0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
|
|
||||||
0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
|
|
||||||
0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
|
|
||||||
0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
|
|
||||||
0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
|
|
||||||
0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
|
|
||||||
0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
|
|
||||||
0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
|
|
||||||
0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
|
|
||||||
0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
|
|
||||||
0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
|
|
||||||
0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
|
|
||||||
0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e,
|
|
||||||
},
|
|
||||||
}
|
|
106
vendor/golang.org/x/crypto/cast5/cast5_test.go
generated
vendored
106
vendor/golang.org/x/crypto/cast5/cast5_test.go
generated
vendored
|
@ -1,106 +0,0 @@
|
||||||
// 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 cast5
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This test vector is taken from RFC 2144, App B.1.
|
|
||||||
// Since the other two test vectors are for reduced-round variants, we can't
|
|
||||||
// use them.
|
|
||||||
var basicTests = []struct {
|
|
||||||
key, plainText, cipherText string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"0123456712345678234567893456789a",
|
|
||||||
"0123456789abcdef",
|
|
||||||
"238b4fe5847e44b2",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBasic(t *testing.T) {
|
|
||||||
for i, test := range basicTests {
|
|
||||||
key, _ := hex.DecodeString(test.key)
|
|
||||||
plainText, _ := hex.DecodeString(test.plainText)
|
|
||||||
expected, _ := hex.DecodeString(test.cipherText)
|
|
||||||
|
|
||||||
c, err := NewCipher(key)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("#%d: failed to create Cipher: %s", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var cipherText [BlockSize]byte
|
|
||||||
c.Encrypt(cipherText[:], plainText)
|
|
||||||
if !bytes.Equal(cipherText[:], expected) {
|
|
||||||
t.Errorf("#%d: got:%x want:%x", i, cipherText, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
var plainTextAgain [BlockSize]byte
|
|
||||||
c.Decrypt(plainTextAgain[:], cipherText[:])
|
|
||||||
if !bytes.Equal(plainTextAgain[:], plainText) {
|
|
||||||
t.Errorf("#%d: got:%x want:%x", i, plainTextAgain, plainText)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestFull performs the test specified in RFC 2144, App B.2.
|
|
||||||
// However, due to the length of time taken, it's disabled here and a more
|
|
||||||
// limited version is included, below.
|
|
||||||
func TestFull(t *testing.T) {
|
|
||||||
if testing.Short() {
|
|
||||||
// This is too slow for normal testing
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
a, b := iterate(1000000)
|
|
||||||
|
|
||||||
const expectedA = "eea9d0a249fd3ba6b3436fb89d6dca92"
|
|
||||||
const expectedB = "b2c95eb00c31ad7180ac05b8e83d696e"
|
|
||||||
|
|
||||||
if hex.EncodeToString(a) != expectedA {
|
|
||||||
t.Errorf("a: got:%x want:%s", a, expectedA)
|
|
||||||
}
|
|
||||||
if hex.EncodeToString(b) != expectedB {
|
|
||||||
t.Errorf("b: got:%x want:%s", b, expectedB)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func iterate(iterations int) ([]byte, []byte) {
|
|
||||||
const initValueHex = "0123456712345678234567893456789a"
|
|
||||||
|
|
||||||
initValue, _ := hex.DecodeString(initValueHex)
|
|
||||||
|
|
||||||
var a, b [16]byte
|
|
||||||
copy(a[:], initValue)
|
|
||||||
copy(b[:], initValue)
|
|
||||||
|
|
||||||
for i := 0; i < iterations; i++ {
|
|
||||||
c, _ := NewCipher(b[:])
|
|
||||||
c.Encrypt(a[:8], a[:8])
|
|
||||||
c.Encrypt(a[8:], a[8:])
|
|
||||||
c, _ = NewCipher(a[:])
|
|
||||||
c.Encrypt(b[:8], b[:8])
|
|
||||||
c.Encrypt(b[8:], b[8:])
|
|
||||||
}
|
|
||||||
|
|
||||||
return a[:], b[:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLimited(t *testing.T) {
|
|
||||||
a, b := iterate(1000)
|
|
||||||
|
|
||||||
const expectedA = "23f73b14b02a2ad7dfb9f2c35644798d"
|
|
||||||
const expectedB = "e5bf37eff14c456a40b21ce369370a9f"
|
|
||||||
|
|
||||||
if hex.EncodeToString(a) != expectedA {
|
|
||||||
t.Errorf("a: got:%x want:%s", a, expectedA)
|
|
||||||
}
|
|
||||||
if hex.EncodeToString(b) != expectedB {
|
|
||||||
t.Errorf("b: got:%x want:%s", b, expectedB)
|
|
||||||
}
|
|
||||||
}
|
|
1
vendor/golang.org/x/crypto/codereview.cfg
generated
vendored
1
vendor/golang.org/x/crypto/codereview.cfg
generated
vendored
|
@ -1 +0,0 @@
|
||||||
issuerepo: golang/go
|
|
20
vendor/golang.org/x/crypto/curve25519/const_amd64.s
generated
vendored
20
vendor/golang.org/x/crypto/curve25519/const_amd64.s
generated
vendored
|
@ -1,20 +0,0 @@
|
||||||
// Copyright 2012 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.
|
|
||||||
|
|
||||||
// This code was translated into a form compatible with 6a from the public
|
|
||||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
|
||||||
|
|
||||||
DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF
|
|
||||||
GLOBL ·REDMASK51(SB), 8, $8
|
|
||||||
|
|
||||||
DATA ·_121666_213(SB)/8, $996687872
|
|
||||||
GLOBL ·_121666_213(SB), 8, $8
|
|
||||||
|
|
||||||
DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA
|
|
||||||
GLOBL ·_2P0(SB), 8, $8
|
|
||||||
|
|
||||||
DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE
|
|
||||||
GLOBL ·_2P1234(SB), 8, $8
|
|
88
vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
generated
vendored
88
vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
generated
vendored
|
@ -1,88 +0,0 @@
|
||||||
// Copyright 2012 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.
|
|
||||||
|
|
||||||
// This code was translated into a form compatible with 6a from the public
|
|
||||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
|
||||||
|
|
||||||
// func cswap(inout *[5]uint64, v uint64)
|
|
||||||
TEXT ·cswap(SB),7,$0
|
|
||||||
MOVQ inout+0(FP),DI
|
|
||||||
MOVQ v+8(FP),SI
|
|
||||||
|
|
||||||
CMPQ SI,$1
|
|
||||||
MOVQ 0(DI),SI
|
|
||||||
MOVQ 80(DI),DX
|
|
||||||
MOVQ 8(DI),CX
|
|
||||||
MOVQ 88(DI),R8
|
|
||||||
MOVQ SI,R9
|
|
||||||
CMOVQEQ DX,SI
|
|
||||||
CMOVQEQ R9,DX
|
|
||||||
MOVQ CX,R9
|
|
||||||
CMOVQEQ R8,CX
|
|
||||||
CMOVQEQ R9,R8
|
|
||||||
MOVQ SI,0(DI)
|
|
||||||
MOVQ DX,80(DI)
|
|
||||||
MOVQ CX,8(DI)
|
|
||||||
MOVQ R8,88(DI)
|
|
||||||
MOVQ 16(DI),SI
|
|
||||||
MOVQ 96(DI),DX
|
|
||||||
MOVQ 24(DI),CX
|
|
||||||
MOVQ 104(DI),R8
|
|
||||||
MOVQ SI,R9
|
|
||||||
CMOVQEQ DX,SI
|
|
||||||
CMOVQEQ R9,DX
|
|
||||||
MOVQ CX,R9
|
|
||||||
CMOVQEQ R8,CX
|
|
||||||
CMOVQEQ R9,R8
|
|
||||||
MOVQ SI,16(DI)
|
|
||||||
MOVQ DX,96(DI)
|
|
||||||
MOVQ CX,24(DI)
|
|
||||||
MOVQ R8,104(DI)
|
|
||||||
MOVQ 32(DI),SI
|
|
||||||
MOVQ 112(DI),DX
|
|
||||||
MOVQ 40(DI),CX
|
|
||||||
MOVQ 120(DI),R8
|
|
||||||
MOVQ SI,R9
|
|
||||||
CMOVQEQ DX,SI
|
|
||||||
CMOVQEQ R9,DX
|
|
||||||
MOVQ CX,R9
|
|
||||||
CMOVQEQ R8,CX
|
|
||||||
CMOVQEQ R9,R8
|
|
||||||
MOVQ SI,32(DI)
|
|
||||||
MOVQ DX,112(DI)
|
|
||||||
MOVQ CX,40(DI)
|
|
||||||
MOVQ R8,120(DI)
|
|
||||||
MOVQ 48(DI),SI
|
|
||||||
MOVQ 128(DI),DX
|
|
||||||
MOVQ 56(DI),CX
|
|
||||||
MOVQ 136(DI),R8
|
|
||||||
MOVQ SI,R9
|
|
||||||
CMOVQEQ DX,SI
|
|
||||||
CMOVQEQ R9,DX
|
|
||||||
MOVQ CX,R9
|
|
||||||
CMOVQEQ R8,CX
|
|
||||||
CMOVQEQ R9,R8
|
|
||||||
MOVQ SI,48(DI)
|
|
||||||
MOVQ DX,128(DI)
|
|
||||||
MOVQ CX,56(DI)
|
|
||||||
MOVQ R8,136(DI)
|
|
||||||
MOVQ 64(DI),SI
|
|
||||||
MOVQ 144(DI),DX
|
|
||||||
MOVQ 72(DI),CX
|
|
||||||
MOVQ 152(DI),R8
|
|
||||||
MOVQ SI,R9
|
|
||||||
CMOVQEQ DX,SI
|
|
||||||
CMOVQEQ R9,DX
|
|
||||||
MOVQ CX,R9
|
|
||||||
CMOVQEQ R8,CX
|
|
||||||
CMOVQEQ R9,R8
|
|
||||||
MOVQ SI,64(DI)
|
|
||||||
MOVQ DX,144(DI)
|
|
||||||
MOVQ CX,72(DI)
|
|
||||||
MOVQ R8,152(DI)
|
|
||||||
MOVQ DI,AX
|
|
||||||
MOVQ SI,DX
|
|
||||||
RET
|
|
841
vendor/golang.org/x/crypto/curve25519/curve25519.go
generated
vendored
841
vendor/golang.org/x/crypto/curve25519/curve25519.go
generated
vendored
|
@ -1,841 +0,0 @@
|
||||||
// Copyright 2013 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.
|
|
||||||
|
|
||||||
// We have a implementation in amd64 assembly so this code is only run on
|
|
||||||
// non-amd64 platforms. The amd64 assembly does not support gccgo.
|
|
||||||
// +build !amd64 gccgo appengine
|
|
||||||
|
|
||||||
package curve25519
|
|
||||||
|
|
||||||
// This code is a port of the public domain, "ref10" implementation of
|
|
||||||
// curve25519 from SUPERCOP 20130419 by D. J. Bernstein.
|
|
||||||
|
|
||||||
// fieldElement represents an element of the field GF(2^255 - 19). An element
|
|
||||||
// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
|
|
||||||
// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
|
|
||||||
// context.
|
|
||||||
type fieldElement [10]int32
|
|
||||||
|
|
||||||
func feZero(fe *fieldElement) {
|
|
||||||
for i := range fe {
|
|
||||||
fe[i] = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func feOne(fe *fieldElement) {
|
|
||||||
feZero(fe)
|
|
||||||
fe[0] = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func feAdd(dst, a, b *fieldElement) {
|
|
||||||
for i := range dst {
|
|
||||||
dst[i] = a[i] + b[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func feSub(dst, a, b *fieldElement) {
|
|
||||||
for i := range dst {
|
|
||||||
dst[i] = a[i] - b[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func feCopy(dst, src *fieldElement) {
|
|
||||||
for i := range dst {
|
|
||||||
dst[i] = src[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0.
|
|
||||||
//
|
|
||||||
// Preconditions: b in {0,1}.
|
|
||||||
func feCSwap(f, g *fieldElement, b int32) {
|
|
||||||
var x fieldElement
|
|
||||||
b = -b
|
|
||||||
for i := range x {
|
|
||||||
x[i] = b & (f[i] ^ g[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range f {
|
|
||||||
f[i] ^= x[i]
|
|
||||||
}
|
|
||||||
for i := range g {
|
|
||||||
g[i] ^= x[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// load3 reads a 24-bit, little-endian value from in.
|
|
||||||
func load3(in []byte) int64 {
|
|
||||||
var r int64
|
|
||||||
r = int64(in[0])
|
|
||||||
r |= int64(in[1]) << 8
|
|
||||||
r |= int64(in[2]) << 16
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// load4 reads a 32-bit, little-endian value from in.
|
|
||||||
func load4(in []byte) int64 {
|
|
||||||
var r int64
|
|
||||||
r = int64(in[0])
|
|
||||||
r |= int64(in[1]) << 8
|
|
||||||
r |= int64(in[2]) << 16
|
|
||||||
r |= int64(in[3]) << 24
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func feFromBytes(dst *fieldElement, src *[32]byte) {
|
|
||||||
h0 := load4(src[:])
|
|
||||||
h1 := load3(src[4:]) << 6
|
|
||||||
h2 := load3(src[7:]) << 5
|
|
||||||
h3 := load3(src[10:]) << 3
|
|
||||||
h4 := load3(src[13:]) << 2
|
|
||||||
h5 := load4(src[16:])
|
|
||||||
h6 := load3(src[20:]) << 7
|
|
||||||
h7 := load3(src[23:]) << 5
|
|
||||||
h8 := load3(src[26:]) << 4
|
|
||||||
h9 := load3(src[29:]) << 2
|
|
||||||
|
|
||||||
var carry [10]int64
|
|
||||||
carry[9] = (h9 + 1<<24) >> 25
|
|
||||||
h0 += carry[9] * 19
|
|
||||||
h9 -= carry[9] << 25
|
|
||||||
carry[1] = (h1 + 1<<24) >> 25
|
|
||||||
h2 += carry[1]
|
|
||||||
h1 -= carry[1] << 25
|
|
||||||
carry[3] = (h3 + 1<<24) >> 25
|
|
||||||
h4 += carry[3]
|
|
||||||
h3 -= carry[3] << 25
|
|
||||||
carry[5] = (h5 + 1<<24) >> 25
|
|
||||||
h6 += carry[5]
|
|
||||||
h5 -= carry[5] << 25
|
|
||||||
carry[7] = (h7 + 1<<24) >> 25
|
|
||||||
h8 += carry[7]
|
|
||||||
h7 -= carry[7] << 25
|
|
||||||
|
|
||||||
carry[0] = (h0 + 1<<25) >> 26
|
|
||||||
h1 += carry[0]
|
|
||||||
h0 -= carry[0] << 26
|
|
||||||
carry[2] = (h2 + 1<<25) >> 26
|
|
||||||
h3 += carry[2]
|
|
||||||
h2 -= carry[2] << 26
|
|
||||||
carry[4] = (h4 + 1<<25) >> 26
|
|
||||||
h5 += carry[4]
|
|
||||||
h4 -= carry[4] << 26
|
|
||||||
carry[6] = (h6 + 1<<25) >> 26
|
|
||||||
h7 += carry[6]
|
|
||||||
h6 -= carry[6] << 26
|
|
||||||
carry[8] = (h8 + 1<<25) >> 26
|
|
||||||
h9 += carry[8]
|
|
||||||
h8 -= carry[8] << 26
|
|
||||||
|
|
||||||
dst[0] = int32(h0)
|
|
||||||
dst[1] = int32(h1)
|
|
||||||
dst[2] = int32(h2)
|
|
||||||
dst[3] = int32(h3)
|
|
||||||
dst[4] = int32(h4)
|
|
||||||
dst[5] = int32(h5)
|
|
||||||
dst[6] = int32(h6)
|
|
||||||
dst[7] = int32(h7)
|
|
||||||
dst[8] = int32(h8)
|
|
||||||
dst[9] = int32(h9)
|
|
||||||
}
|
|
||||||
|
|
||||||
// feToBytes marshals h to s.
|
|
||||||
// Preconditions:
|
|
||||||
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|
|
||||||
//
|
|
||||||
// Write p=2^255-19; q=floor(h/p).
|
|
||||||
// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
|
|
||||||
//
|
|
||||||
// Proof:
|
|
||||||
// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
|
|
||||||
// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4.
|
|
||||||
//
|
|
||||||
// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
|
|
||||||
// Then 0<y<1.
|
|
||||||
//
|
|
||||||
// Write r=h-pq.
|
|
||||||
// Have 0<=r<=p-1=2^255-20.
|
|
||||||
// Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
|
|
||||||
//
|
|
||||||
// Write x=r+19(2^-255)r+y.
|
|
||||||
// Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
|
|
||||||
//
|
|
||||||
// Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
|
|
||||||
// so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
|
|
||||||
func feToBytes(s *[32]byte, h *fieldElement) {
|
|
||||||
var carry [10]int32
|
|
||||||
|
|
||||||
q := (19*h[9] + (1 << 24)) >> 25
|
|
||||||
q = (h[0] + q) >> 26
|
|
||||||
q = (h[1] + q) >> 25
|
|
||||||
q = (h[2] + q) >> 26
|
|
||||||
q = (h[3] + q) >> 25
|
|
||||||
q = (h[4] + q) >> 26
|
|
||||||
q = (h[5] + q) >> 25
|
|
||||||
q = (h[6] + q) >> 26
|
|
||||||
q = (h[7] + q) >> 25
|
|
||||||
q = (h[8] + q) >> 26
|
|
||||||
q = (h[9] + q) >> 25
|
|
||||||
|
|
||||||
// Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
|
|
||||||
h[0] += 19 * q
|
|
||||||
// Goal: Output h-2^255 q, which is between 0 and 2^255-20.
|
|
||||||
|
|
||||||
carry[0] = h[0] >> 26
|
|
||||||
h[1] += carry[0]
|
|
||||||
h[0] -= carry[0] << 26
|
|
||||||
carry[1] = h[1] >> 25
|
|
||||||
h[2] += carry[1]
|
|
||||||
h[1] -= carry[1] << 25
|
|
||||||
carry[2] = h[2] >> 26
|
|
||||||
h[3] += carry[2]
|
|
||||||
h[2] -= carry[2] << 26
|
|
||||||
carry[3] = h[3] >> 25
|
|
||||||
h[4] += carry[3]
|
|
||||||
h[3] -= carry[3] << 25
|
|
||||||
carry[4] = h[4] >> 26
|
|
||||||
h[5] += carry[4]
|
|
||||||
h[4] -= carry[4] << 26
|
|
||||||
carry[5] = h[5] >> 25
|
|
||||||
h[6] += carry[5]
|
|
||||||
h[5] -= carry[5] << 25
|
|
||||||
carry[6] = h[6] >> 26
|
|
||||||
h[7] += carry[6]
|
|
||||||
h[6] -= carry[6] << 26
|
|
||||||
carry[7] = h[7] >> 25
|
|
||||||
h[8] += carry[7]
|
|
||||||
h[7] -= carry[7] << 25
|
|
||||||
carry[8] = h[8] >> 26
|
|
||||||
h[9] += carry[8]
|
|
||||||
h[8] -= carry[8] << 26
|
|
||||||
carry[9] = h[9] >> 25
|
|
||||||
h[9] -= carry[9] << 25
|
|
||||||
// h10 = carry9
|
|
||||||
|
|
||||||
// Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
|
|
||||||
// Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
|
|
||||||
// evidently 2^255 h10-2^255 q = 0.
|
|
||||||
// Goal: Output h[0]+...+2^230 h[9].
|
|
||||||
|
|
||||||
s[0] = byte(h[0] >> 0)
|
|
||||||
s[1] = byte(h[0] >> 8)
|
|
||||||
s[2] = byte(h[0] >> 16)
|
|
||||||
s[3] = byte((h[0] >> 24) | (h[1] << 2))
|
|
||||||
s[4] = byte(h[1] >> 6)
|
|
||||||
s[5] = byte(h[1] >> 14)
|
|
||||||
s[6] = byte((h[1] >> 22) | (h[2] << 3))
|
|
||||||
s[7] = byte(h[2] >> 5)
|
|
||||||
s[8] = byte(h[2] >> 13)
|
|
||||||
s[9] = byte((h[2] >> 21) | (h[3] << 5))
|
|
||||||
s[10] = byte(h[3] >> 3)
|
|
||||||
s[11] = byte(h[3] >> 11)
|
|
||||||
s[12] = byte((h[3] >> 19) | (h[4] << 6))
|
|
||||||
s[13] = byte(h[4] >> 2)
|
|
||||||
s[14] = byte(h[4] >> 10)
|
|
||||||
s[15] = byte(h[4] >> 18)
|
|
||||||
s[16] = byte(h[5] >> 0)
|
|
||||||
s[17] = byte(h[5] >> 8)
|
|
||||||
s[18] = byte(h[5] >> 16)
|
|
||||||
s[19] = byte((h[5] >> 24) | (h[6] << 1))
|
|
||||||
s[20] = byte(h[6] >> 7)
|
|
||||||
s[21] = byte(h[6] >> 15)
|
|
||||||
s[22] = byte((h[6] >> 23) | (h[7] << 3))
|
|
||||||
s[23] = byte(h[7] >> 5)
|
|
||||||
s[24] = byte(h[7] >> 13)
|
|
||||||
s[25] = byte((h[7] >> 21) | (h[8] << 4))
|
|
||||||
s[26] = byte(h[8] >> 4)
|
|
||||||
s[27] = byte(h[8] >> 12)
|
|
||||||
s[28] = byte((h[8] >> 20) | (h[9] << 6))
|
|
||||||
s[29] = byte(h[9] >> 2)
|
|
||||||
s[30] = byte(h[9] >> 10)
|
|
||||||
s[31] = byte(h[9] >> 18)
|
|
||||||
}
|
|
||||||
|
|
||||||
// feMul calculates h = f * g
|
|
||||||
// Can overlap h with f or g.
|
|
||||||
//
|
|
||||||
// Preconditions:
|
|
||||||
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
|
||||||
// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
|
||||||
//
|
|
||||||
// Postconditions:
|
|
||||||
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|
|
||||||
//
|
|
||||||
// Notes on implementation strategy:
|
|
||||||
//
|
|
||||||
// Using schoolbook multiplication.
|
|
||||||
// Karatsuba would save a little in some cost models.
|
|
||||||
//
|
|
||||||
// Most multiplications by 2 and 19 are 32-bit precomputations;
|
|
||||||
// cheaper than 64-bit postcomputations.
|
|
||||||
//
|
|
||||||
// There is one remaining multiplication by 19 in the carry chain;
|
|
||||||
// one *19 precomputation can be merged into this,
|
|
||||||
// but the resulting data flow is considerably less clean.
|
|
||||||
//
|
|
||||||
// There are 12 carries below.
|
|
||||||
// 10 of them are 2-way parallelizable and vectorizable.
|
|
||||||
// Can get away with 11 carries, but then data flow is much deeper.
|
|
||||||
//
|
|
||||||
// With tighter constraints on inputs can squeeze carries into int32.
|
|
||||||
func feMul(h, f, g *fieldElement) {
|
|
||||||
f0 := f[0]
|
|
||||||
f1 := f[1]
|
|
||||||
f2 := f[2]
|
|
||||||
f3 := f[3]
|
|
||||||
f4 := f[4]
|
|
||||||
f5 := f[5]
|
|
||||||
f6 := f[6]
|
|
||||||
f7 := f[7]
|
|
||||||
f8 := f[8]
|
|
||||||
f9 := f[9]
|
|
||||||
g0 := g[0]
|
|
||||||
g1 := g[1]
|
|
||||||
g2 := g[2]
|
|
||||||
g3 := g[3]
|
|
||||||
g4 := g[4]
|
|
||||||
g5 := g[5]
|
|
||||||
g6 := g[6]
|
|
||||||
g7 := g[7]
|
|
||||||
g8 := g[8]
|
|
||||||
g9 := g[9]
|
|
||||||
g1_19 := 19 * g1 // 1.4*2^29
|
|
||||||
g2_19 := 19 * g2 // 1.4*2^30; still ok
|
|
||||||
g3_19 := 19 * g3
|
|
||||||
g4_19 := 19 * g4
|
|
||||||
g5_19 := 19 * g5
|
|
||||||
g6_19 := 19 * g6
|
|
||||||
g7_19 := 19 * g7
|
|
||||||
g8_19 := 19 * g8
|
|
||||||
g9_19 := 19 * g9
|
|
||||||
f1_2 := 2 * f1
|
|
||||||
f3_2 := 2 * f3
|
|
||||||
f5_2 := 2 * f5
|
|
||||||
f7_2 := 2 * f7
|
|
||||||
f9_2 := 2 * f9
|
|
||||||
f0g0 := int64(f0) * int64(g0)
|
|
||||||
f0g1 := int64(f0) * int64(g1)
|
|
||||||
f0g2 := int64(f0) * int64(g2)
|
|
||||||
f0g3 := int64(f0) * int64(g3)
|
|
||||||
f0g4 := int64(f0) * int64(g4)
|
|
||||||
f0g5 := int64(f0) * int64(g5)
|
|
||||||
f0g6 := int64(f0) * int64(g6)
|
|
||||||
f0g7 := int64(f0) * int64(g7)
|
|
||||||
f0g8 := int64(f0) * int64(g8)
|
|
||||||
f0g9 := int64(f0) * int64(g9)
|
|
||||||
f1g0 := int64(f1) * int64(g0)
|
|
||||||
f1g1_2 := int64(f1_2) * int64(g1)
|
|
||||||
f1g2 := int64(f1) * int64(g2)
|
|
||||||
f1g3_2 := int64(f1_2) * int64(g3)
|
|
||||||
f1g4 := int64(f1) * int64(g4)
|
|
||||||
f1g5_2 := int64(f1_2) * int64(g5)
|
|
||||||
f1g6 := int64(f1) * int64(g6)
|
|
||||||
f1g7_2 := int64(f1_2) * int64(g7)
|
|
||||||
f1g8 := int64(f1) * int64(g8)
|
|
||||||
f1g9_38 := int64(f1_2) * int64(g9_19)
|
|
||||||
f2g0 := int64(f2) * int64(g0)
|
|
||||||
f2g1 := int64(f2) * int64(g1)
|
|
||||||
f2g2 := int64(f2) * int64(g2)
|
|
||||||
f2g3 := int64(f2) * int64(g3)
|
|
||||||
f2g4 := int64(f2) * int64(g4)
|
|
||||||
f2g5 := int64(f2) * int64(g5)
|
|
||||||
f2g6 := int64(f2) * int64(g6)
|
|
||||||
f2g7 := int64(f2) * int64(g7)
|
|
||||||
f2g8_19 := int64(f2) * int64(g8_19)
|
|
||||||
f2g9_19 := int64(f2) * int64(g9_19)
|
|
||||||
f3g0 := int64(f3) * int64(g0)
|
|
||||||
f3g1_2 := int64(f3_2) * int64(g1)
|
|
||||||
f3g2 := int64(f3) * int64(g2)
|
|
||||||
f3g3_2 := int64(f3_2) * int64(g3)
|
|
||||||
f3g4 := int64(f3) * int64(g4)
|
|
||||||
f3g5_2 := int64(f3_2) * int64(g5)
|
|
||||||
f3g6 := int64(f3) * int64(g6)
|
|
||||||
f3g7_38 := int64(f3_2) * int64(g7_19)
|
|
||||||
f3g8_19 := int64(f3) * int64(g8_19)
|
|
||||||
f3g9_38 := int64(f3_2) * int64(g9_19)
|
|
||||||
f4g0 := int64(f4) * int64(g0)
|
|
||||||
f4g1 := int64(f4) * int64(g1)
|
|
||||||
f4g2 := int64(f4) * int64(g2)
|
|
||||||
f4g3 := int64(f4) * int64(g3)
|
|
||||||
f4g4 := int64(f4) * int64(g4)
|
|
||||||
f4g5 := int64(f4) * int64(g5)
|
|
||||||
f4g6_19 := int64(f4) * int64(g6_19)
|
|
||||||
f4g7_19 := int64(f4) * int64(g7_19)
|
|
||||||
f4g8_19 := int64(f4) * int64(g8_19)
|
|
||||||
f4g9_19 := int64(f4) * int64(g9_19)
|
|
||||||
f5g0 := int64(f5) * int64(g0)
|
|
||||||
f5g1_2 := int64(f5_2) * int64(g1)
|
|
||||||
f5g2 := int64(f5) * int64(g2)
|
|
||||||
f5g3_2 := int64(f5_2) * int64(g3)
|
|
||||||
f5g4 := int64(f5) * int64(g4)
|
|
||||||
f5g5_38 := int64(f5_2) * int64(g5_19)
|
|
||||||
f5g6_19 := int64(f5) * int64(g6_19)
|
|
||||||
f5g7_38 := int64(f5_2) * int64(g7_19)
|
|
||||||
f5g8_19 := int64(f5) * int64(g8_19)
|
|
||||||
f5g9_38 := int64(f5_2) * int64(g9_19)
|
|
||||||
f6g0 := int64(f6) * int64(g0)
|
|
||||||
f6g1 := int64(f6) * int64(g1)
|
|
||||||
f6g2 := int64(f6) * int64(g2)
|
|
||||||
f6g3 := int64(f6) * int64(g3)
|
|
||||||
f6g4_19 := int64(f6) * int64(g4_19)
|
|
||||||
f6g5_19 := int64(f6) * int64(g5_19)
|
|
||||||
f6g6_19 := int64(f6) * int64(g6_19)
|
|
||||||
f6g7_19 := int64(f6) * int64(g7_19)
|
|
||||||
f6g8_19 := int64(f6) * int64(g8_19)
|
|
||||||
f6g9_19 := int64(f6) * int64(g9_19)
|
|
||||||
f7g0 := int64(f7) * int64(g0)
|
|
||||||
f7g1_2 := int64(f7_2) * int64(g1)
|
|
||||||
f7g2 := int64(f7) * int64(g2)
|
|
||||||
f7g3_38 := int64(f7_2) * int64(g3_19)
|
|
||||||
f7g4_19 := int64(f7) * int64(g4_19)
|
|
||||||
f7g5_38 := int64(f7_2) * int64(g5_19)
|
|
||||||
f7g6_19 := int64(f7) * int64(g6_19)
|
|
||||||
f7g7_38 := int64(f7_2) * int64(g7_19)
|
|
||||||
f7g8_19 := int64(f7) * int64(g8_19)
|
|
||||||
f7g9_38 := int64(f7_2) * int64(g9_19)
|
|
||||||
f8g0 := int64(f8) * int64(g0)
|
|
||||||
f8g1 := int64(f8) * int64(g1)
|
|
||||||
f8g2_19 := int64(f8) * int64(g2_19)
|
|
||||||
f8g3_19 := int64(f8) * int64(g3_19)
|
|
||||||
f8g4_19 := int64(f8) * int64(g4_19)
|
|
||||||
f8g5_19 := int64(f8) * int64(g5_19)
|
|
||||||
f8g6_19 := int64(f8) * int64(g6_19)
|
|
||||||
f8g7_19 := int64(f8) * int64(g7_19)
|
|
||||||
f8g8_19 := int64(f8) * int64(g8_19)
|
|
||||||
f8g9_19 := int64(f8) * int64(g9_19)
|
|
||||||
f9g0 := int64(f9) * int64(g0)
|
|
||||||
f9g1_38 := int64(f9_2) * int64(g1_19)
|
|
||||||
f9g2_19 := int64(f9) * int64(g2_19)
|
|
||||||
f9g3_38 := int64(f9_2) * int64(g3_19)
|
|
||||||
f9g4_19 := int64(f9) * int64(g4_19)
|
|
||||||
f9g5_38 := int64(f9_2) * int64(g5_19)
|
|
||||||
f9g6_19 := int64(f9) * int64(g6_19)
|
|
||||||
f9g7_38 := int64(f9_2) * int64(g7_19)
|
|
||||||
f9g8_19 := int64(f9) * int64(g8_19)
|
|
||||||
f9g9_38 := int64(f9_2) * int64(g9_19)
|
|
||||||
h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38
|
|
||||||
h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19
|
|
||||||
h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38
|
|
||||||
h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19
|
|
||||||
h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38
|
|
||||||
h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19
|
|
||||||
h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38
|
|
||||||
h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19
|
|
||||||
h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38
|
|
||||||
h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0
|
|
||||||
var carry [10]int64
|
|
||||||
|
|
||||||
// |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
|
|
||||||
// i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8
|
|
||||||
// |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
|
|
||||||
// i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9
|
|
||||||
|
|
||||||
carry[0] = (h0 + (1 << 25)) >> 26
|
|
||||||
h1 += carry[0]
|
|
||||||
h0 -= carry[0] << 26
|
|
||||||
carry[4] = (h4 + (1 << 25)) >> 26
|
|
||||||
h5 += carry[4]
|
|
||||||
h4 -= carry[4] << 26
|
|
||||||
// |h0| <= 2^25
|
|
||||||
// |h4| <= 2^25
|
|
||||||
// |h1| <= 1.51*2^58
|
|
||||||
// |h5| <= 1.51*2^58
|
|
||||||
|
|
||||||
carry[1] = (h1 + (1 << 24)) >> 25
|
|
||||||
h2 += carry[1]
|
|
||||||
h1 -= carry[1] << 25
|
|
||||||
carry[5] = (h5 + (1 << 24)) >> 25
|
|
||||||
h6 += carry[5]
|
|
||||||
h5 -= carry[5] << 25
|
|
||||||
// |h1| <= 2^24; from now on fits into int32
|
|
||||||
// |h5| <= 2^24; from now on fits into int32
|
|
||||||
// |h2| <= 1.21*2^59
|
|
||||||
// |h6| <= 1.21*2^59
|
|
||||||
|
|
||||||
carry[2] = (h2 + (1 << 25)) >> 26
|
|
||||||
h3 += carry[2]
|
|
||||||
h2 -= carry[2] << 26
|
|
||||||
carry[6] = (h6 + (1 << 25)) >> 26
|
|
||||||
h7 += carry[6]
|
|
||||||
h6 -= carry[6] << 26
|
|
||||||
// |h2| <= 2^25; from now on fits into int32 unchanged
|
|
||||||
// |h6| <= 2^25; from now on fits into int32 unchanged
|
|
||||||
// |h3| <= 1.51*2^58
|
|
||||||
// |h7| <= 1.51*2^58
|
|
||||||
|
|
||||||
carry[3] = (h3 + (1 << 24)) >> 25
|
|
||||||
h4 += carry[3]
|
|
||||||
h3 -= carry[3] << 25
|
|
||||||
carry[7] = (h7 + (1 << 24)) >> 25
|
|
||||||
h8 += carry[7]
|
|
||||||
h7 -= carry[7] << 25
|
|
||||||
// |h3| <= 2^24; from now on fits into int32 unchanged
|
|
||||||
// |h7| <= 2^24; from now on fits into int32 unchanged
|
|
||||||
// |h4| <= 1.52*2^33
|
|
||||||
// |h8| <= 1.52*2^33
|
|
||||||
|
|
||||||
carry[4] = (h4 + (1 << 25)) >> 26
|
|
||||||
h5 += carry[4]
|
|
||||||
h4 -= carry[4] << 26
|
|
||||||
carry[8] = (h8 + (1 << 25)) >> 26
|
|
||||||
h9 += carry[8]
|
|
||||||
h8 -= carry[8] << 26
|
|
||||||
// |h4| <= 2^25; from now on fits into int32 unchanged
|
|
||||||
// |h8| <= 2^25; from now on fits into int32 unchanged
|
|
||||||
// |h5| <= 1.01*2^24
|
|
||||||
// |h9| <= 1.51*2^58
|
|
||||||
|
|
||||||
carry[9] = (h9 + (1 << 24)) >> 25
|
|
||||||
h0 += carry[9] * 19
|
|
||||||
h9 -= carry[9] << 25
|
|
||||||
// |h9| <= 2^24; from now on fits into int32 unchanged
|
|
||||||
// |h0| <= 1.8*2^37
|
|
||||||
|
|
||||||
carry[0] = (h0 + (1 << 25)) >> 26
|
|
||||||
h1 += carry[0]
|
|
||||||
h0 -= carry[0] << 26
|
|
||||||
// |h0| <= 2^25; from now on fits into int32 unchanged
|
|
||||||
// |h1| <= 1.01*2^24
|
|
||||||
|
|
||||||
h[0] = int32(h0)
|
|
||||||
h[1] = int32(h1)
|
|
||||||
h[2] = int32(h2)
|
|
||||||
h[3] = int32(h3)
|
|
||||||
h[4] = int32(h4)
|
|
||||||
h[5] = int32(h5)
|
|
||||||
h[6] = int32(h6)
|
|
||||||
h[7] = int32(h7)
|
|
||||||
h[8] = int32(h8)
|
|
||||||
h[9] = int32(h9)
|
|
||||||
}
|
|
||||||
|
|
||||||
// feSquare calculates h = f*f. Can overlap h with f.
|
|
||||||
//
|
|
||||||
// Preconditions:
|
|
||||||
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
|
||||||
//
|
|
||||||
// Postconditions:
|
|
||||||
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|
|
||||||
func feSquare(h, f *fieldElement) {
|
|
||||||
f0 := f[0]
|
|
||||||
f1 := f[1]
|
|
||||||
f2 := f[2]
|
|
||||||
f3 := f[3]
|
|
||||||
f4 := f[4]
|
|
||||||
f5 := f[5]
|
|
||||||
f6 := f[6]
|
|
||||||
f7 := f[7]
|
|
||||||
f8 := f[8]
|
|
||||||
f9 := f[9]
|
|
||||||
f0_2 := 2 * f0
|
|
||||||
f1_2 := 2 * f1
|
|
||||||
f2_2 := 2 * f2
|
|
||||||
f3_2 := 2 * f3
|
|
||||||
f4_2 := 2 * f4
|
|
||||||
f5_2 := 2 * f5
|
|
||||||
f6_2 := 2 * f6
|
|
||||||
f7_2 := 2 * f7
|
|
||||||
f5_38 := 38 * f5 // 1.31*2^30
|
|
||||||
f6_19 := 19 * f6 // 1.31*2^30
|
|
||||||
f7_38 := 38 * f7 // 1.31*2^30
|
|
||||||
f8_19 := 19 * f8 // 1.31*2^30
|
|
||||||
f9_38 := 38 * f9 // 1.31*2^30
|
|
||||||
f0f0 := int64(f0) * int64(f0)
|
|
||||||
f0f1_2 := int64(f0_2) * int64(f1)
|
|
||||||
f0f2_2 := int64(f0_2) * int64(f2)
|
|
||||||
f0f3_2 := int64(f0_2) * int64(f3)
|
|
||||||
f0f4_2 := int64(f0_2) * int64(f4)
|
|
||||||
f0f5_2 := int64(f0_2) * int64(f5)
|
|
||||||
f0f6_2 := int64(f0_2) * int64(f6)
|
|
||||||
f0f7_2 := int64(f0_2) * int64(f7)
|
|
||||||
f0f8_2 := int64(f0_2) * int64(f8)
|
|
||||||
f0f9_2 := int64(f0_2) * int64(f9)
|
|
||||||
f1f1_2 := int64(f1_2) * int64(f1)
|
|
||||||
f1f2_2 := int64(f1_2) * int64(f2)
|
|
||||||
f1f3_4 := int64(f1_2) * int64(f3_2)
|
|
||||||
f1f4_2 := int64(f1_2) * int64(f4)
|
|
||||||
f1f5_4 := int64(f1_2) * int64(f5_2)
|
|
||||||
f1f6_2 := int64(f1_2) * int64(f6)
|
|
||||||
f1f7_4 := int64(f1_2) * int64(f7_2)
|
|
||||||
f1f8_2 := int64(f1_2) * int64(f8)
|
|
||||||
f1f9_76 := int64(f1_2) * int64(f9_38)
|
|
||||||
f2f2 := int64(f2) * int64(f2)
|
|
||||||
f2f3_2 := int64(f2_2) * int64(f3)
|
|
||||||
f2f4_2 := int64(f2_2) * int64(f4)
|
|
||||||
f2f5_2 := int64(f2_2) * int64(f5)
|
|
||||||
f2f6_2 := int64(f2_2) * int64(f6)
|
|
||||||
f2f7_2 := int64(f2_2) * int64(f7)
|
|
||||||
f2f8_38 := int64(f2_2) * int64(f8_19)
|
|
||||||
f2f9_38 := int64(f2) * int64(f9_38)
|
|
||||||
f3f3_2 := int64(f3_2) * int64(f3)
|
|
||||||
f3f4_2 := int64(f3_2) * int64(f4)
|
|
||||||
f3f5_4 := int64(f3_2) * int64(f5_2)
|
|
||||||
f3f6_2 := int64(f3_2) * int64(f6)
|
|
||||||
f3f7_76 := int64(f3_2) * int64(f7_38)
|
|
||||||
f3f8_38 := int64(f3_2) * int64(f8_19)
|
|
||||||
f3f9_76 := int64(f3_2) * int64(f9_38)
|
|
||||||
f4f4 := int64(f4) * int64(f4)
|
|
||||||
f4f5_2 := int64(f4_2) * int64(f5)
|
|
||||||
f4f6_38 := int64(f4_2) * int64(f6_19)
|
|
||||||
f4f7_38 := int64(f4) * int64(f7_38)
|
|
||||||
f4f8_38 := int64(f4_2) * int64(f8_19)
|
|
||||||
f4f9_38 := int64(f4) * int64(f9_38)
|
|
||||||
f5f5_38 := int64(f5) * int64(f5_38)
|
|
||||||
f5f6_38 := int64(f5_2) * int64(f6_19)
|
|
||||||
f5f7_76 := int64(f5_2) * int64(f7_38)
|
|
||||||
f5f8_38 := int64(f5_2) * int64(f8_19)
|
|
||||||
f5f9_76 := int64(f5_2) * int64(f9_38)
|
|
||||||
f6f6_19 := int64(f6) * int64(f6_19)
|
|
||||||
f6f7_38 := int64(f6) * int64(f7_38)
|
|
||||||
f6f8_38 := int64(f6_2) * int64(f8_19)
|
|
||||||
f6f9_38 := int64(f6) * int64(f9_38)
|
|
||||||
f7f7_38 := int64(f7) * int64(f7_38)
|
|
||||||
f7f8_38 := int64(f7_2) * int64(f8_19)
|
|
||||||
f7f9_76 := int64(f7_2) * int64(f9_38)
|
|
||||||
f8f8_19 := int64(f8) * int64(f8_19)
|
|
||||||
f8f9_38 := int64(f8) * int64(f9_38)
|
|
||||||
f9f9_38 := int64(f9) * int64(f9_38)
|
|
||||||
h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38
|
|
||||||
h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38
|
|
||||||
h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19
|
|
||||||
h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38
|
|
||||||
h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38
|
|
||||||
h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38
|
|
||||||
h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19
|
|
||||||
h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38
|
|
||||||
h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38
|
|
||||||
h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2
|
|
||||||
var carry [10]int64
|
|
||||||
|
|
||||||
carry[0] = (h0 + (1 << 25)) >> 26
|
|
||||||
h1 += carry[0]
|
|
||||||
h0 -= carry[0] << 26
|
|
||||||
carry[4] = (h4 + (1 << 25)) >> 26
|
|
||||||
h5 += carry[4]
|
|
||||||
h4 -= carry[4] << 26
|
|
||||||
|
|
||||||
carry[1] = (h1 + (1 << 24)) >> 25
|
|
||||||
h2 += carry[1]
|
|
||||||
h1 -= carry[1] << 25
|
|
||||||
carry[5] = (h5 + (1 << 24)) >> 25
|
|
||||||
h6 += carry[5]
|
|
||||||
h5 -= carry[5] << 25
|
|
||||||
|
|
||||||
carry[2] = (h2 + (1 << 25)) >> 26
|
|
||||||
h3 += carry[2]
|
|
||||||
h2 -= carry[2] << 26
|
|
||||||
carry[6] = (h6 + (1 << 25)) >> 26
|
|
||||||
h7 += carry[6]
|
|
||||||
h6 -= carry[6] << 26
|
|
||||||
|
|
||||||
carry[3] = (h3 + (1 << 24)) >> 25
|
|
||||||
h4 += carry[3]
|
|
||||||
h3 -= carry[3] << 25
|
|
||||||
carry[7] = (h7 + (1 << 24)) >> 25
|
|
||||||
h8 += carry[7]
|
|
||||||
h7 -= carry[7] << 25
|
|
||||||
|
|
||||||
carry[4] = (h4 + (1 << 25)) >> 26
|
|
||||||
h5 += carry[4]
|
|
||||||
h4 -= carry[4] << 26
|
|
||||||
carry[8] = (h8 + (1 << 25)) >> 26
|
|
||||||
h9 += carry[8]
|
|
||||||
h8 -= carry[8] << 26
|
|
||||||
|
|
||||||
carry[9] = (h9 + (1 << 24)) >> 25
|
|
||||||
h0 += carry[9] * 19
|
|
||||||
h9 -= carry[9] << 25
|
|
||||||
|
|
||||||
carry[0] = (h0 + (1 << 25)) >> 26
|
|
||||||
h1 += carry[0]
|
|
||||||
h0 -= carry[0] << 26
|
|
||||||
|
|
||||||
h[0] = int32(h0)
|
|
||||||
h[1] = int32(h1)
|
|
||||||
h[2] = int32(h2)
|
|
||||||
h[3] = int32(h3)
|
|
||||||
h[4] = int32(h4)
|
|
||||||
h[5] = int32(h5)
|
|
||||||
h[6] = int32(h6)
|
|
||||||
h[7] = int32(h7)
|
|
||||||
h[8] = int32(h8)
|
|
||||||
h[9] = int32(h9)
|
|
||||||
}
|
|
||||||
|
|
||||||
// feMul121666 calculates h = f * 121666. Can overlap h with f.
|
|
||||||
//
|
|
||||||
// Preconditions:
|
|
||||||
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
|
||||||
//
|
|
||||||
// Postconditions:
|
|
||||||
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|
|
||||||
func feMul121666(h, f *fieldElement) {
|
|
||||||
h0 := int64(f[0]) * 121666
|
|
||||||
h1 := int64(f[1]) * 121666
|
|
||||||
h2 := int64(f[2]) * 121666
|
|
||||||
h3 := int64(f[3]) * 121666
|
|
||||||
h4 := int64(f[4]) * 121666
|
|
||||||
h5 := int64(f[5]) * 121666
|
|
||||||
h6 := int64(f[6]) * 121666
|
|
||||||
h7 := int64(f[7]) * 121666
|
|
||||||
h8 := int64(f[8]) * 121666
|
|
||||||
h9 := int64(f[9]) * 121666
|
|
||||||
var carry [10]int64
|
|
||||||
|
|
||||||
carry[9] = (h9 + (1 << 24)) >> 25
|
|
||||||
h0 += carry[9] * 19
|
|
||||||
h9 -= carry[9] << 25
|
|
||||||
carry[1] = (h1 + (1 << 24)) >> 25
|
|
||||||
h2 += carry[1]
|
|
||||||
h1 -= carry[1] << 25
|
|
||||||
carry[3] = (h3 + (1 << 24)) >> 25
|
|
||||||
h4 += carry[3]
|
|
||||||
h3 -= carry[3] << 25
|
|
||||||
carry[5] = (h5 + (1 << 24)) >> 25
|
|
||||||
h6 += carry[5]
|
|
||||||
h5 -= carry[5] << 25
|
|
||||||
carry[7] = (h7 + (1 << 24)) >> 25
|
|
||||||
h8 += carry[7]
|
|
||||||
h7 -= carry[7] << 25
|
|
||||||
|
|
||||||
carry[0] = (h0 + (1 << 25)) >> 26
|
|
||||||
h1 += carry[0]
|
|
||||||
h0 -= carry[0] << 26
|
|
||||||
carry[2] = (h2 + (1 << 25)) >> 26
|
|
||||||
h3 += carry[2]
|
|
||||||
h2 -= carry[2] << 26
|
|
||||||
carry[4] = (h4 + (1 << 25)) >> 26
|
|
||||||
h5 += carry[4]
|
|
||||||
h4 -= carry[4] << 26
|
|
||||||
carry[6] = (h6 + (1 << 25)) >> 26
|
|
||||||
h7 += carry[6]
|
|
||||||
h6 -= carry[6] << 26
|
|
||||||
carry[8] = (h8 + (1 << 25)) >> 26
|
|
||||||
h9 += carry[8]
|
|
||||||
h8 -= carry[8] << 26
|
|
||||||
|
|
||||||
h[0] = int32(h0)
|
|
||||||
h[1] = int32(h1)
|
|
||||||
h[2] = int32(h2)
|
|
||||||
h[3] = int32(h3)
|
|
||||||
h[4] = int32(h4)
|
|
||||||
h[5] = int32(h5)
|
|
||||||
h[6] = int32(h6)
|
|
||||||
h[7] = int32(h7)
|
|
||||||
h[8] = int32(h8)
|
|
||||||
h[9] = int32(h9)
|
|
||||||
}
|
|
||||||
|
|
||||||
// feInvert sets out = z^-1.
|
|
||||||
func feInvert(out, z *fieldElement) {
|
|
||||||
var t0, t1, t2, t3 fieldElement
|
|
||||||
var i int
|
|
||||||
|
|
||||||
feSquare(&t0, z)
|
|
||||||
for i = 1; i < 1; i++ {
|
|
||||||
feSquare(&t0, &t0)
|
|
||||||
}
|
|
||||||
feSquare(&t1, &t0)
|
|
||||||
for i = 1; i < 2; i++ {
|
|
||||||
feSquare(&t1, &t1)
|
|
||||||
}
|
|
||||||
feMul(&t1, z, &t1)
|
|
||||||
feMul(&t0, &t0, &t1)
|
|
||||||
feSquare(&t2, &t0)
|
|
||||||
for i = 1; i < 1; i++ {
|
|
||||||
feSquare(&t2, &t2)
|
|
||||||
}
|
|
||||||
feMul(&t1, &t1, &t2)
|
|
||||||
feSquare(&t2, &t1)
|
|
||||||
for i = 1; i < 5; i++ {
|
|
||||||
feSquare(&t2, &t2)
|
|
||||||
}
|
|
||||||
feMul(&t1, &t2, &t1)
|
|
||||||
feSquare(&t2, &t1)
|
|
||||||
for i = 1; i < 10; i++ {
|
|
||||||
feSquare(&t2, &t2)
|
|
||||||
}
|
|
||||||
feMul(&t2, &t2, &t1)
|
|
||||||
feSquare(&t3, &t2)
|
|
||||||
for i = 1; i < 20; i++ {
|
|
||||||
feSquare(&t3, &t3)
|
|
||||||
}
|
|
||||||
feMul(&t2, &t3, &t2)
|
|
||||||
feSquare(&t2, &t2)
|
|
||||||
for i = 1; i < 10; i++ {
|
|
||||||
feSquare(&t2, &t2)
|
|
||||||
}
|
|
||||||
feMul(&t1, &t2, &t1)
|
|
||||||
feSquare(&t2, &t1)
|
|
||||||
for i = 1; i < 50; i++ {
|
|
||||||
feSquare(&t2, &t2)
|
|
||||||
}
|
|
||||||
feMul(&t2, &t2, &t1)
|
|
||||||
feSquare(&t3, &t2)
|
|
||||||
for i = 1; i < 100; i++ {
|
|
||||||
feSquare(&t3, &t3)
|
|
||||||
}
|
|
||||||
feMul(&t2, &t3, &t2)
|
|
||||||
feSquare(&t2, &t2)
|
|
||||||
for i = 1; i < 50; i++ {
|
|
||||||
feSquare(&t2, &t2)
|
|
||||||
}
|
|
||||||
feMul(&t1, &t2, &t1)
|
|
||||||
feSquare(&t1, &t1)
|
|
||||||
for i = 1; i < 5; i++ {
|
|
||||||
feSquare(&t1, &t1)
|
|
||||||
}
|
|
||||||
feMul(out, &t1, &t0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func scalarMult(out, in, base *[32]byte) {
|
|
||||||
var e [32]byte
|
|
||||||
|
|
||||||
copy(e[:], in[:])
|
|
||||||
e[0] &= 248
|
|
||||||
e[31] &= 127
|
|
||||||
e[31] |= 64
|
|
||||||
|
|
||||||
var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement
|
|
||||||
feFromBytes(&x1, base)
|
|
||||||
feOne(&x2)
|
|
||||||
feCopy(&x3, &x1)
|
|
||||||
feOne(&z3)
|
|
||||||
|
|
||||||
swap := int32(0)
|
|
||||||
for pos := 254; pos >= 0; pos-- {
|
|
||||||
b := e[pos/8] >> uint(pos&7)
|
|
||||||
b &= 1
|
|
||||||
swap ^= int32(b)
|
|
||||||
feCSwap(&x2, &x3, swap)
|
|
||||||
feCSwap(&z2, &z3, swap)
|
|
||||||
swap = int32(b)
|
|
||||||
|
|
||||||
feSub(&tmp0, &x3, &z3)
|
|
||||||
feSub(&tmp1, &x2, &z2)
|
|
||||||
feAdd(&x2, &x2, &z2)
|
|
||||||
feAdd(&z2, &x3, &z3)
|
|
||||||
feMul(&z3, &tmp0, &x2)
|
|
||||||
feMul(&z2, &z2, &tmp1)
|
|
||||||
feSquare(&tmp0, &tmp1)
|
|
||||||
feSquare(&tmp1, &x2)
|
|
||||||
feAdd(&x3, &z3, &z2)
|
|
||||||
feSub(&z2, &z3, &z2)
|
|
||||||
feMul(&x2, &tmp1, &tmp0)
|
|
||||||
feSub(&tmp1, &tmp1, &tmp0)
|
|
||||||
feSquare(&z2, &z2)
|
|
||||||
feMul121666(&z3, &tmp1)
|
|
||||||
feSquare(&x3, &x3)
|
|
||||||
feAdd(&tmp0, &tmp0, &z3)
|
|
||||||
feMul(&z3, &x1, &z2)
|
|
||||||
feMul(&z2, &tmp1, &tmp0)
|
|
||||||
}
|
|
||||||
|
|
||||||
feCSwap(&x2, &x3, swap)
|
|
||||||
feCSwap(&z2, &z3, swap)
|
|
||||||
|
|
||||||
feInvert(&z2, &z2)
|
|
||||||
feMul(&x2, &x2, &z2)
|
|
||||||
feToBytes(out, &x2)
|
|
||||||
}
|
|
29
vendor/golang.org/x/crypto/curve25519/curve25519_test.go
generated
vendored
29
vendor/golang.org/x/crypto/curve25519/curve25519_test.go
generated
vendored
|
@ -1,29 +0,0 @@
|
||||||
// Copyright 2012 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 curve25519
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
const expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a"
|
|
||||||
|
|
||||||
func TestBaseScalarMult(t *testing.T) {
|
|
||||||
var a, b [32]byte
|
|
||||||
in := &a
|
|
||||||
out := &b
|
|
||||||
a[0] = 1
|
|
||||||
|
|
||||||
for i := 0; i < 200; i++ {
|
|
||||||
ScalarBaseMult(out, in)
|
|
||||||
in, out = out, in
|
|
||||||
}
|
|
||||||
|
|
||||||
result := fmt.Sprintf("%x", in[:])
|
|
||||||
if result != expectedHex {
|
|
||||||
t.Errorf("incorrect result: got %s, want %s", result, expectedHex)
|
|
||||||
}
|
|
||||||
}
|
|
23
vendor/golang.org/x/crypto/curve25519/doc.go
generated
vendored
23
vendor/golang.org/x/crypto/curve25519/doc.go
generated
vendored
|
@ -1,23 +0,0 @@
|
||||||
// Copyright 2012 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 curve25519 provides an implementation of scalar multiplication on
|
|
||||||
// the elliptic curve known as curve25519. See http://cr.yp.to/ecdh.html
|
|
||||||
package curve25519 // import "golang.org/x/crypto/curve25519"
|
|
||||||
|
|
||||||
// basePoint is the x coordinate of the generator of the curve.
|
|
||||||
var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
|
||||||
|
|
||||||
// ScalarMult sets dst to the product in*base where dst and base are the x
|
|
||||||
// coordinates of group points and all values are in little-endian form.
|
|
||||||
func ScalarMult(dst, in, base *[32]byte) {
|
|
||||||
scalarMult(dst, in, base)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScalarBaseMult sets dst to the product in*base where dst and base are the x
|
|
||||||
// coordinates of group points, base is the standard generator and all values
|
|
||||||
// are in little-endian form.
|
|
||||||
func ScalarBaseMult(dst, in *[32]byte) {
|
|
||||||
ScalarMult(dst, in, &basePoint)
|
|
||||||
}
|
|
94
vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
generated
vendored
94
vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
generated
vendored
|
@ -1,94 +0,0 @@
|
||||||
// Copyright 2012 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.
|
|
||||||
|
|
||||||
// This code was translated into a form compatible with 6a from the public
|
|
||||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
|
||||||
|
|
||||||
// func freeze(inout *[5]uint64)
|
|
||||||
TEXT ·freeze(SB),7,$96-8
|
|
||||||
MOVQ inout+0(FP), DI
|
|
||||||
|
|
||||||
MOVQ SP,R11
|
|
||||||
MOVQ $31,CX
|
|
||||||
NOTQ CX
|
|
||||||
ANDQ CX,SP
|
|
||||||
ADDQ $32,SP
|
|
||||||
|
|
||||||
MOVQ R11,0(SP)
|
|
||||||
MOVQ R12,8(SP)
|
|
||||||
MOVQ R13,16(SP)
|
|
||||||
MOVQ R14,24(SP)
|
|
||||||
MOVQ R15,32(SP)
|
|
||||||
MOVQ BX,40(SP)
|
|
||||||
MOVQ BP,48(SP)
|
|
||||||
MOVQ 0(DI),SI
|
|
||||||
MOVQ 8(DI),DX
|
|
||||||
MOVQ 16(DI),CX
|
|
||||||
MOVQ 24(DI),R8
|
|
||||||
MOVQ 32(DI),R9
|
|
||||||
MOVQ ·REDMASK51(SB),AX
|
|
||||||
MOVQ AX,R10
|
|
||||||
SUBQ $18,R10
|
|
||||||
MOVQ $3,R11
|
|
||||||
REDUCELOOP:
|
|
||||||
MOVQ SI,R12
|
|
||||||
SHRQ $51,R12
|
|
||||||
ANDQ AX,SI
|
|
||||||
ADDQ R12,DX
|
|
||||||
MOVQ DX,R12
|
|
||||||
SHRQ $51,R12
|
|
||||||
ANDQ AX,DX
|
|
||||||
ADDQ R12,CX
|
|
||||||
MOVQ CX,R12
|
|
||||||
SHRQ $51,R12
|
|
||||||
ANDQ AX,CX
|
|
||||||
ADDQ R12,R8
|
|
||||||
MOVQ R8,R12
|
|
||||||
SHRQ $51,R12
|
|
||||||
ANDQ AX,R8
|
|
||||||
ADDQ R12,R9
|
|
||||||
MOVQ R9,R12
|
|
||||||
SHRQ $51,R12
|
|
||||||
ANDQ AX,R9
|
|
||||||
IMUL3Q $19,R12,R12
|
|
||||||
ADDQ R12,SI
|
|
||||||
SUBQ $1,R11
|
|
||||||
JA REDUCELOOP
|
|
||||||
MOVQ $1,R12
|
|
||||||
CMPQ R10,SI
|
|
||||||
CMOVQLT R11,R12
|
|
||||||
CMPQ AX,DX
|
|
||||||
CMOVQNE R11,R12
|
|
||||||
CMPQ AX,CX
|
|
||||||
CMOVQNE R11,R12
|
|
||||||
CMPQ AX,R8
|
|
||||||
CMOVQNE R11,R12
|
|
||||||
CMPQ AX,R9
|
|
||||||
CMOVQNE R11,R12
|
|
||||||
NEGQ R12
|
|
||||||
ANDQ R12,AX
|
|
||||||
ANDQ R12,R10
|
|
||||||
SUBQ R10,SI
|
|
||||||
SUBQ AX,DX
|
|
||||||
SUBQ AX,CX
|
|
||||||
SUBQ AX,R8
|
|
||||||
SUBQ AX,R9
|
|
||||||
MOVQ SI,0(DI)
|
|
||||||
MOVQ DX,8(DI)
|
|
||||||
MOVQ CX,16(DI)
|
|
||||||
MOVQ R8,24(DI)
|
|
||||||
MOVQ R9,32(DI)
|
|
||||||
MOVQ 0(SP),R11
|
|
||||||
MOVQ 8(SP),R12
|
|
||||||
MOVQ 16(SP),R13
|
|
||||||
MOVQ 24(SP),R14
|
|
||||||
MOVQ 32(SP),R15
|
|
||||||
MOVQ 40(SP),BX
|
|
||||||
MOVQ 48(SP),BP
|
|
||||||
MOVQ R11,SP
|
|
||||||
MOVQ DI,AX
|
|
||||||
MOVQ SI,DX
|
|
||||||
RET
|
|
1398
vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
generated
vendored
1398
vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
generated
vendored
File diff suppressed because it is too large
Load diff
240
vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go
generated
vendored
240
vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go
generated
vendored
|
@ -1,240 +0,0 @@
|
||||||
// Copyright 2012 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.
|
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
|
||||||
|
|
||||||
package curve25519
|
|
||||||
|
|
||||||
// These functions are implemented in the .s files. The names of the functions
|
|
||||||
// in the rest of the file are also taken from the SUPERCOP sources to help
|
|
||||||
// people following along.
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
|
|
||||||
func cswap(inout *[5]uint64, v uint64)
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
|
|
||||||
func ladderstep(inout *[5][5]uint64)
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
|
|
||||||
func freeze(inout *[5]uint64)
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
|
|
||||||
func mul(dest, a, b *[5]uint64)
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
|
|
||||||
func square(out, in *[5]uint64)
|
|
||||||
|
|
||||||
// mladder uses a Montgomery ladder to calculate (xr/zr) *= s.
|
|
||||||
func mladder(xr, zr *[5]uint64, s *[32]byte) {
|
|
||||||
var work [5][5]uint64
|
|
||||||
|
|
||||||
work[0] = *xr
|
|
||||||
setint(&work[1], 1)
|
|
||||||
setint(&work[2], 0)
|
|
||||||
work[3] = *xr
|
|
||||||
setint(&work[4], 1)
|
|
||||||
|
|
||||||
j := uint(6)
|
|
||||||
var prevbit byte
|
|
||||||
|
|
||||||
for i := 31; i >= 0; i-- {
|
|
||||||
for j < 8 {
|
|
||||||
bit := ((*s)[i] >> j) & 1
|
|
||||||
swap := bit ^ prevbit
|
|
||||||
prevbit = bit
|
|
||||||
cswap(&work[1], uint64(swap))
|
|
||||||
ladderstep(&work)
|
|
||||||
j--
|
|
||||||
}
|
|
||||||
j = 7
|
|
||||||
}
|
|
||||||
|
|
||||||
*xr = work[1]
|
|
||||||
*zr = work[2]
|
|
||||||
}
|
|
||||||
|
|
||||||
func scalarMult(out, in, base *[32]byte) {
|
|
||||||
var e [32]byte
|
|
||||||
copy(e[:], (*in)[:])
|
|
||||||
e[0] &= 248
|
|
||||||
e[31] &= 127
|
|
||||||
e[31] |= 64
|
|
||||||
|
|
||||||
var t, z [5]uint64
|
|
||||||
unpack(&t, base)
|
|
||||||
mladder(&t, &z, &e)
|
|
||||||
invert(&z, &z)
|
|
||||||
mul(&t, &t, &z)
|
|
||||||
pack(out, &t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setint(r *[5]uint64, v uint64) {
|
|
||||||
r[0] = v
|
|
||||||
r[1] = 0
|
|
||||||
r[2] = 0
|
|
||||||
r[3] = 0
|
|
||||||
r[4] = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// unpack sets r = x where r consists of 5, 51-bit limbs in little-endian
|
|
||||||
// order.
|
|
||||||
func unpack(r *[5]uint64, x *[32]byte) {
|
|
||||||
r[0] = uint64(x[0]) |
|
|
||||||
uint64(x[1])<<8 |
|
|
||||||
uint64(x[2])<<16 |
|
|
||||||
uint64(x[3])<<24 |
|
|
||||||
uint64(x[4])<<32 |
|
|
||||||
uint64(x[5])<<40 |
|
|
||||||
uint64(x[6]&7)<<48
|
|
||||||
|
|
||||||
r[1] = uint64(x[6])>>3 |
|
|
||||||
uint64(x[7])<<5 |
|
|
||||||
uint64(x[8])<<13 |
|
|
||||||
uint64(x[9])<<21 |
|
|
||||||
uint64(x[10])<<29 |
|
|
||||||
uint64(x[11])<<37 |
|
|
||||||
uint64(x[12]&63)<<45
|
|
||||||
|
|
||||||
r[2] = uint64(x[12])>>6 |
|
|
||||||
uint64(x[13])<<2 |
|
|
||||||
uint64(x[14])<<10 |
|
|
||||||
uint64(x[15])<<18 |
|
|
||||||
uint64(x[16])<<26 |
|
|
||||||
uint64(x[17])<<34 |
|
|
||||||
uint64(x[18])<<42 |
|
|
||||||
uint64(x[19]&1)<<50
|
|
||||||
|
|
||||||
r[3] = uint64(x[19])>>1 |
|
|
||||||
uint64(x[20])<<7 |
|
|
||||||
uint64(x[21])<<15 |
|
|
||||||
uint64(x[22])<<23 |
|
|
||||||
uint64(x[23])<<31 |
|
|
||||||
uint64(x[24])<<39 |
|
|
||||||
uint64(x[25]&15)<<47
|
|
||||||
|
|
||||||
r[4] = uint64(x[25])>>4 |
|
|
||||||
uint64(x[26])<<4 |
|
|
||||||
uint64(x[27])<<12 |
|
|
||||||
uint64(x[28])<<20 |
|
|
||||||
uint64(x[29])<<28 |
|
|
||||||
uint64(x[30])<<36 |
|
|
||||||
uint64(x[31]&127)<<44
|
|
||||||
}
|
|
||||||
|
|
||||||
// pack sets out = x where out is the usual, little-endian form of the 5,
|
|
||||||
// 51-bit limbs in x.
|
|
||||||
func pack(out *[32]byte, x *[5]uint64) {
|
|
||||||
t := *x
|
|
||||||
freeze(&t)
|
|
||||||
|
|
||||||
out[0] = byte(t[0])
|
|
||||||
out[1] = byte(t[0] >> 8)
|
|
||||||
out[2] = byte(t[0] >> 16)
|
|
||||||
out[3] = byte(t[0] >> 24)
|
|
||||||
out[4] = byte(t[0] >> 32)
|
|
||||||
out[5] = byte(t[0] >> 40)
|
|
||||||
out[6] = byte(t[0] >> 48)
|
|
||||||
|
|
||||||
out[6] ^= byte(t[1]<<3) & 0xf8
|
|
||||||
out[7] = byte(t[1] >> 5)
|
|
||||||
out[8] = byte(t[1] >> 13)
|
|
||||||
out[9] = byte(t[1] >> 21)
|
|
||||||
out[10] = byte(t[1] >> 29)
|
|
||||||
out[11] = byte(t[1] >> 37)
|
|
||||||
out[12] = byte(t[1] >> 45)
|
|
||||||
|
|
||||||
out[12] ^= byte(t[2]<<6) & 0xc0
|
|
||||||
out[13] = byte(t[2] >> 2)
|
|
||||||
out[14] = byte(t[2] >> 10)
|
|
||||||
out[15] = byte(t[2] >> 18)
|
|
||||||
out[16] = byte(t[2] >> 26)
|
|
||||||
out[17] = byte(t[2] >> 34)
|
|
||||||
out[18] = byte(t[2] >> 42)
|
|
||||||
out[19] = byte(t[2] >> 50)
|
|
||||||
|
|
||||||
out[19] ^= byte(t[3]<<1) & 0xfe
|
|
||||||
out[20] = byte(t[3] >> 7)
|
|
||||||
out[21] = byte(t[3] >> 15)
|
|
||||||
out[22] = byte(t[3] >> 23)
|
|
||||||
out[23] = byte(t[3] >> 31)
|
|
||||||
out[24] = byte(t[3] >> 39)
|
|
||||||
out[25] = byte(t[3] >> 47)
|
|
||||||
|
|
||||||
out[25] ^= byte(t[4]<<4) & 0xf0
|
|
||||||
out[26] = byte(t[4] >> 4)
|
|
||||||
out[27] = byte(t[4] >> 12)
|
|
||||||
out[28] = byte(t[4] >> 20)
|
|
||||||
out[29] = byte(t[4] >> 28)
|
|
||||||
out[30] = byte(t[4] >> 36)
|
|
||||||
out[31] = byte(t[4] >> 44)
|
|
||||||
}
|
|
||||||
|
|
||||||
// invert calculates r = x^-1 mod p using Fermat's little theorem.
|
|
||||||
func invert(r *[5]uint64, x *[5]uint64) {
|
|
||||||
var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t [5]uint64
|
|
||||||
|
|
||||||
square(&z2, x) /* 2 */
|
|
||||||
square(&t, &z2) /* 4 */
|
|
||||||
square(&t, &t) /* 8 */
|
|
||||||
mul(&z9, &t, x) /* 9 */
|
|
||||||
mul(&z11, &z9, &z2) /* 11 */
|
|
||||||
square(&t, &z11) /* 22 */
|
|
||||||
mul(&z2_5_0, &t, &z9) /* 2^5 - 2^0 = 31 */
|
|
||||||
|
|
||||||
square(&t, &z2_5_0) /* 2^6 - 2^1 */
|
|
||||||
for i := 1; i < 5; i++ { /* 2^20 - 2^10 */
|
|
||||||
square(&t, &t)
|
|
||||||
}
|
|
||||||
mul(&z2_10_0, &t, &z2_5_0) /* 2^10 - 2^0 */
|
|
||||||
|
|
||||||
square(&t, &z2_10_0) /* 2^11 - 2^1 */
|
|
||||||
for i := 1; i < 10; i++ { /* 2^20 - 2^10 */
|
|
||||||
square(&t, &t)
|
|
||||||
}
|
|
||||||
mul(&z2_20_0, &t, &z2_10_0) /* 2^20 - 2^0 */
|
|
||||||
|
|
||||||
square(&t, &z2_20_0) /* 2^21 - 2^1 */
|
|
||||||
for i := 1; i < 20; i++ { /* 2^40 - 2^20 */
|
|
||||||
square(&t, &t)
|
|
||||||
}
|
|
||||||
mul(&t, &t, &z2_20_0) /* 2^40 - 2^0 */
|
|
||||||
|
|
||||||
square(&t, &t) /* 2^41 - 2^1 */
|
|
||||||
for i := 1; i < 10; i++ { /* 2^50 - 2^10 */
|
|
||||||
square(&t, &t)
|
|
||||||
}
|
|
||||||
mul(&z2_50_0, &t, &z2_10_0) /* 2^50 - 2^0 */
|
|
||||||
|
|
||||||
square(&t, &z2_50_0) /* 2^51 - 2^1 */
|
|
||||||
for i := 1; i < 50; i++ { /* 2^100 - 2^50 */
|
|
||||||
square(&t, &t)
|
|
||||||
}
|
|
||||||
mul(&z2_100_0, &t, &z2_50_0) /* 2^100 - 2^0 */
|
|
||||||
|
|
||||||
square(&t, &z2_100_0) /* 2^101 - 2^1 */
|
|
||||||
for i := 1; i < 100; i++ { /* 2^200 - 2^100 */
|
|
||||||
square(&t, &t)
|
|
||||||
}
|
|
||||||
mul(&t, &t, &z2_100_0) /* 2^200 - 2^0 */
|
|
||||||
|
|
||||||
square(&t, &t) /* 2^201 - 2^1 */
|
|
||||||
for i := 1; i < 50; i++ { /* 2^250 - 2^50 */
|
|
||||||
square(&t, &t)
|
|
||||||
}
|
|
||||||
mul(&t, &t, &z2_50_0) /* 2^250 - 2^0 */
|
|
||||||
|
|
||||||
square(&t, &t) /* 2^251 - 2^1 */
|
|
||||||
square(&t, &t) /* 2^252 - 2^2 */
|
|
||||||
square(&t, &t) /* 2^253 - 2^3 */
|
|
||||||
|
|
||||||
square(&t, &t) /* 2^254 - 2^4 */
|
|
||||||
|
|
||||||
square(&t, &t) /* 2^255 - 2^5 */
|
|
||||||
mul(r, &t, &z11) /* 2^255 - 21 */
|
|
||||||
}
|
|
191
vendor/golang.org/x/crypto/curve25519/mul_amd64.s
generated
vendored
191
vendor/golang.org/x/crypto/curve25519/mul_amd64.s
generated
vendored
|
@ -1,191 +0,0 @@
|
||||||
// Copyright 2012 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.
|
|
||||||
|
|
||||||
// This code was translated into a form compatible with 6a from the public
|
|
||||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
|
||||||
|
|
||||||
// func mul(dest, a, b *[5]uint64)
|
|
||||||
TEXT ·mul(SB),0,$128-24
|
|
||||||
MOVQ dest+0(FP), DI
|
|
||||||
MOVQ a+8(FP), SI
|
|
||||||
MOVQ b+16(FP), DX
|
|
||||||
|
|
||||||
MOVQ SP,R11
|
|
||||||
MOVQ $31,CX
|
|
||||||
NOTQ CX
|
|
||||||
ANDQ CX,SP
|
|
||||||
ADDQ $32,SP
|
|
||||||
|
|
||||||
MOVQ R11,0(SP)
|
|
||||||
MOVQ R12,8(SP)
|
|
||||||
MOVQ R13,16(SP)
|
|
||||||
MOVQ R14,24(SP)
|
|
||||||
MOVQ R15,32(SP)
|
|
||||||
MOVQ BX,40(SP)
|
|
||||||
MOVQ BP,48(SP)
|
|
||||||
MOVQ DI,56(SP)
|
|
||||||
MOVQ DX,CX
|
|
||||||
MOVQ 24(SI),DX
|
|
||||||
IMUL3Q $19,DX,AX
|
|
||||||
MOVQ AX,64(SP)
|
|
||||||
MULQ 16(CX)
|
|
||||||
MOVQ AX,R8
|
|
||||||
MOVQ DX,R9
|
|
||||||
MOVQ 32(SI),DX
|
|
||||||
IMUL3Q $19,DX,AX
|
|
||||||
MOVQ AX,72(SP)
|
|
||||||
MULQ 8(CX)
|
|
||||||
ADDQ AX,R8
|
|
||||||
ADCQ DX,R9
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
MULQ 0(CX)
|
|
||||||
ADDQ AX,R8
|
|
||||||
ADCQ DX,R9
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
MULQ 8(CX)
|
|
||||||
MOVQ AX,R10
|
|
||||||
MOVQ DX,R11
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
MULQ 16(CX)
|
|
||||||
MOVQ AX,R12
|
|
||||||
MOVQ DX,R13
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
MULQ 24(CX)
|
|
||||||
MOVQ AX,R14
|
|
||||||
MOVQ DX,R15
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
MULQ 32(CX)
|
|
||||||
MOVQ AX,BX
|
|
||||||
MOVQ DX,BP
|
|
||||||
MOVQ 8(SI),AX
|
|
||||||
MULQ 0(CX)
|
|
||||||
ADDQ AX,R10
|
|
||||||
ADCQ DX,R11
|
|
||||||
MOVQ 8(SI),AX
|
|
||||||
MULQ 8(CX)
|
|
||||||
ADDQ AX,R12
|
|
||||||
ADCQ DX,R13
|
|
||||||
MOVQ 8(SI),AX
|
|
||||||
MULQ 16(CX)
|
|
||||||
ADDQ AX,R14
|
|
||||||
ADCQ DX,R15
|
|
||||||
MOVQ 8(SI),AX
|
|
||||||
MULQ 24(CX)
|
|
||||||
ADDQ AX,BX
|
|
||||||
ADCQ DX,BP
|
|
||||||
MOVQ 8(SI),DX
|
|
||||||
IMUL3Q $19,DX,AX
|
|
||||||
MULQ 32(CX)
|
|
||||||
ADDQ AX,R8
|
|
||||||
ADCQ DX,R9
|
|
||||||
MOVQ 16(SI),AX
|
|
||||||
MULQ 0(CX)
|
|
||||||
ADDQ AX,R12
|
|
||||||
ADCQ DX,R13
|
|
||||||
MOVQ 16(SI),AX
|
|
||||||
MULQ 8(CX)
|
|
||||||
ADDQ AX,R14
|
|
||||||
ADCQ DX,R15
|
|
||||||
MOVQ 16(SI),AX
|
|
||||||
MULQ 16(CX)
|
|
||||||
ADDQ AX,BX
|
|
||||||
ADCQ DX,BP
|
|
||||||
MOVQ 16(SI),DX
|
|
||||||
IMUL3Q $19,DX,AX
|
|
||||||
MULQ 24(CX)
|
|
||||||
ADDQ AX,R8
|
|
||||||
ADCQ DX,R9
|
|
||||||
MOVQ 16(SI),DX
|
|
||||||
IMUL3Q $19,DX,AX
|
|
||||||
MULQ 32(CX)
|
|
||||||
ADDQ AX,R10
|
|
||||||
ADCQ DX,R11
|
|
||||||
MOVQ 24(SI),AX
|
|
||||||
MULQ 0(CX)
|
|
||||||
ADDQ AX,R14
|
|
||||||
ADCQ DX,R15
|
|
||||||
MOVQ 24(SI),AX
|
|
||||||
MULQ 8(CX)
|
|
||||||
ADDQ AX,BX
|
|
||||||
ADCQ DX,BP
|
|
||||||
MOVQ 64(SP),AX
|
|
||||||
MULQ 24(CX)
|
|
||||||
ADDQ AX,R10
|
|
||||||
ADCQ DX,R11
|
|
||||||
MOVQ 64(SP),AX
|
|
||||||
MULQ 32(CX)
|
|
||||||
ADDQ AX,R12
|
|
||||||
ADCQ DX,R13
|
|
||||||
MOVQ 32(SI),AX
|
|
||||||
MULQ 0(CX)
|
|
||||||
ADDQ AX,BX
|
|
||||||
ADCQ DX,BP
|
|
||||||
MOVQ 72(SP),AX
|
|
||||||
MULQ 16(CX)
|
|
||||||
ADDQ AX,R10
|
|
||||||
ADCQ DX,R11
|
|
||||||
MOVQ 72(SP),AX
|
|
||||||
MULQ 24(CX)
|
|
||||||
ADDQ AX,R12
|
|
||||||
ADCQ DX,R13
|
|
||||||
MOVQ 72(SP),AX
|
|
||||||
MULQ 32(CX)
|
|
||||||
ADDQ AX,R14
|
|
||||||
ADCQ DX,R15
|
|
||||||
MOVQ ·REDMASK51(SB),SI
|
|
||||||
SHLQ $13,R9:R8
|
|
||||||
ANDQ SI,R8
|
|
||||||
SHLQ $13,R11:R10
|
|
||||||
ANDQ SI,R10
|
|
||||||
ADDQ R9,R10
|
|
||||||
SHLQ $13,R13:R12
|
|
||||||
ANDQ SI,R12
|
|
||||||
ADDQ R11,R12
|
|
||||||
SHLQ $13,R15:R14
|
|
||||||
ANDQ SI,R14
|
|
||||||
ADDQ R13,R14
|
|
||||||
SHLQ $13,BP:BX
|
|
||||||
ANDQ SI,BX
|
|
||||||
ADDQ R15,BX
|
|
||||||
IMUL3Q $19,BP,DX
|
|
||||||
ADDQ DX,R8
|
|
||||||
MOVQ R8,DX
|
|
||||||
SHRQ $51,DX
|
|
||||||
ADDQ R10,DX
|
|
||||||
MOVQ DX,CX
|
|
||||||
SHRQ $51,DX
|
|
||||||
ANDQ SI,R8
|
|
||||||
ADDQ R12,DX
|
|
||||||
MOVQ DX,R9
|
|
||||||
SHRQ $51,DX
|
|
||||||
ANDQ SI,CX
|
|
||||||
ADDQ R14,DX
|
|
||||||
MOVQ DX,AX
|
|
||||||
SHRQ $51,DX
|
|
||||||
ANDQ SI,R9
|
|
||||||
ADDQ BX,DX
|
|
||||||
MOVQ DX,R10
|
|
||||||
SHRQ $51,DX
|
|
||||||
ANDQ SI,AX
|
|
||||||
IMUL3Q $19,DX,DX
|
|
||||||
ADDQ DX,R8
|
|
||||||
ANDQ SI,R10
|
|
||||||
MOVQ R8,0(DI)
|
|
||||||
MOVQ CX,8(DI)
|
|
||||||
MOVQ R9,16(DI)
|
|
||||||
MOVQ AX,24(DI)
|
|
||||||
MOVQ R10,32(DI)
|
|
||||||
MOVQ 0(SP),R11
|
|
||||||
MOVQ 8(SP),R12
|
|
||||||
MOVQ 16(SP),R13
|
|
||||||
MOVQ 24(SP),R14
|
|
||||||
MOVQ 32(SP),R15
|
|
||||||
MOVQ 40(SP),BX
|
|
||||||
MOVQ 48(SP),BP
|
|
||||||
MOVQ R11,SP
|
|
||||||
MOVQ DI,AX
|
|
||||||
MOVQ SI,DX
|
|
||||||
RET
|
|
153
vendor/golang.org/x/crypto/curve25519/square_amd64.s
generated
vendored
153
vendor/golang.org/x/crypto/curve25519/square_amd64.s
generated
vendored
|
@ -1,153 +0,0 @@
|
||||||
// Copyright 2012 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.
|
|
||||||
|
|
||||||
// This code was translated into a form compatible with 6a from the public
|
|
||||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
|
||||||
|
|
||||||
// func square(out, in *[5]uint64)
|
|
||||||
TEXT ·square(SB),7,$96-16
|
|
||||||
MOVQ out+0(FP), DI
|
|
||||||
MOVQ in+8(FP), SI
|
|
||||||
|
|
||||||
MOVQ SP,R11
|
|
||||||
MOVQ $31,CX
|
|
||||||
NOTQ CX
|
|
||||||
ANDQ CX,SP
|
|
||||||
ADDQ $32, SP
|
|
||||||
|
|
||||||
MOVQ R11,0(SP)
|
|
||||||
MOVQ R12,8(SP)
|
|
||||||
MOVQ R13,16(SP)
|
|
||||||
MOVQ R14,24(SP)
|
|
||||||
MOVQ R15,32(SP)
|
|
||||||
MOVQ BX,40(SP)
|
|
||||||
MOVQ BP,48(SP)
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
MULQ 0(SI)
|
|
||||||
MOVQ AX,CX
|
|
||||||
MOVQ DX,R8
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
SHLQ $1,AX
|
|
||||||
MULQ 8(SI)
|
|
||||||
MOVQ AX,R9
|
|
||||||
MOVQ DX,R10
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
SHLQ $1,AX
|
|
||||||
MULQ 16(SI)
|
|
||||||
MOVQ AX,R11
|
|
||||||
MOVQ DX,R12
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
SHLQ $1,AX
|
|
||||||
MULQ 24(SI)
|
|
||||||
MOVQ AX,R13
|
|
||||||
MOVQ DX,R14
|
|
||||||
MOVQ 0(SI),AX
|
|
||||||
SHLQ $1,AX
|
|
||||||
MULQ 32(SI)
|
|
||||||
MOVQ AX,R15
|
|
||||||
MOVQ DX,BX
|
|
||||||
MOVQ 8(SI),AX
|
|
||||||
MULQ 8(SI)
|
|
||||||
ADDQ AX,R11
|
|
||||||
ADCQ DX,R12
|
|
||||||
MOVQ 8(SI),AX
|
|
||||||
SHLQ $1,AX
|
|
||||||
MULQ 16(SI)
|
|
||||||
ADDQ AX,R13
|
|
||||||
ADCQ DX,R14
|
|
||||||
MOVQ 8(SI),AX
|
|
||||||
SHLQ $1,AX
|
|
||||||
MULQ 24(SI)
|
|
||||||
ADDQ AX,R15
|
|
||||||
ADCQ DX,BX
|
|
||||||
MOVQ 8(SI),DX
|
|
||||||
IMUL3Q $38,DX,AX
|
|
||||||
MULQ 32(SI)
|
|
||||||
ADDQ AX,CX
|
|
||||||
ADCQ DX,R8
|
|
||||||
MOVQ 16(SI),AX
|
|
||||||
MULQ 16(SI)
|
|
||||||
ADDQ AX,R15
|
|
||||||
ADCQ DX,BX
|
|
||||||
MOVQ 16(SI),DX
|
|
||||||
IMUL3Q $38,DX,AX
|
|
||||||
MULQ 24(SI)
|
|
||||||
ADDQ AX,CX
|
|
||||||
ADCQ DX,R8
|
|
||||||
MOVQ 16(SI),DX
|
|
||||||
IMUL3Q $38,DX,AX
|
|
||||||
MULQ 32(SI)
|
|
||||||
ADDQ AX,R9
|
|
||||||
ADCQ DX,R10
|
|
||||||
MOVQ 24(SI),DX
|
|
||||||
IMUL3Q $19,DX,AX
|
|
||||||
MULQ 24(SI)
|
|
||||||
ADDQ AX,R9
|
|
||||||
ADCQ DX,R10
|
|
||||||
MOVQ 24(SI),DX
|
|
||||||
IMUL3Q $38,DX,AX
|
|
||||||
MULQ 32(SI)
|
|
||||||
ADDQ AX,R11
|
|
||||||
ADCQ DX,R12
|
|
||||||
MOVQ 32(SI),DX
|
|
||||||
IMUL3Q $19,DX,AX
|
|
||||||
MULQ 32(SI)
|
|
||||||
ADDQ AX,R13
|
|
||||||
ADCQ DX,R14
|
|
||||||
MOVQ ·REDMASK51(SB),SI
|
|
||||||
SHLQ $13,R8:CX
|
|
||||||
ANDQ SI,CX
|
|
||||||
SHLQ $13,R10:R9
|
|
||||||
ANDQ SI,R9
|
|
||||||
ADDQ R8,R9
|
|
||||||
SHLQ $13,R12:R11
|
|
||||||
ANDQ SI,R11
|
|
||||||
ADDQ R10,R11
|
|
||||||
SHLQ $13,R14:R13
|
|
||||||
ANDQ SI,R13
|
|
||||||
ADDQ R12,R13
|
|
||||||
SHLQ $13,BX:R15
|
|
||||||
ANDQ SI,R15
|
|
||||||
ADDQ R14,R15
|
|
||||||
IMUL3Q $19,BX,DX
|
|
||||||
ADDQ DX,CX
|
|
||||||
MOVQ CX,DX
|
|
||||||
SHRQ $51,DX
|
|
||||||
ADDQ R9,DX
|
|
||||||
ANDQ SI,CX
|
|
||||||
MOVQ DX,R8
|
|
||||||
SHRQ $51,DX
|
|
||||||
ADDQ R11,DX
|
|
||||||
ANDQ SI,R8
|
|
||||||
MOVQ DX,R9
|
|
||||||
SHRQ $51,DX
|
|
||||||
ADDQ R13,DX
|
|
||||||
ANDQ SI,R9
|
|
||||||
MOVQ DX,AX
|
|
||||||
SHRQ $51,DX
|
|
||||||
ADDQ R15,DX
|
|
||||||
ANDQ SI,AX
|
|
||||||
MOVQ DX,R10
|
|
||||||
SHRQ $51,DX
|
|
||||||
IMUL3Q $19,DX,DX
|
|
||||||
ADDQ DX,CX
|
|
||||||
ANDQ SI,R10
|
|
||||||
MOVQ CX,0(DI)
|
|
||||||
MOVQ R8,8(DI)
|
|
||||||
MOVQ R9,16(DI)
|
|
||||||
MOVQ AX,24(DI)
|
|
||||||
MOVQ R10,32(DI)
|
|
||||||
MOVQ 0(SP),R11
|
|
||||||
MOVQ 8(SP),R12
|
|
||||||
MOVQ 16(SP),R13
|
|
||||||
MOVQ 24(SP),R14
|
|
||||||
MOVQ 32(SP),R15
|
|
||||||
MOVQ 40(SP),BX
|
|
||||||
MOVQ 48(SP),BP
|
|
||||||
MOVQ R11,SP
|
|
||||||
MOVQ DI,AX
|
|
||||||
MOVQ SI,DX
|
|
||||||
RET
|
|
181
vendor/golang.org/x/crypto/ed25519/ed25519.go
generated
vendored
181
vendor/golang.org/x/crypto/ed25519/ed25519.go
generated
vendored
|
@ -1,181 +0,0 @@
|
||||||
// Copyright 2016 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 ed25519 implements the Ed25519 signature algorithm. See
|
|
||||||
// http://ed25519.cr.yp.to/.
|
|
||||||
//
|
|
||||||
// These functions are also compatible with the “Ed25519” function defined in
|
|
||||||
// https://tools.ietf.org/html/draft-irtf-cfrg-eddsa-05.
|
|
||||||
package ed25519
|
|
||||||
|
|
||||||
// This code is a port of the public domain, “ref10” implementation of ed25519
|
|
||||||
// from SUPERCOP.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto"
|
|
||||||
cryptorand "crypto/rand"
|
|
||||||
"crypto/sha512"
|
|
||||||
"crypto/subtle"
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/ed25519/internal/edwards25519"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// PublicKeySize is the size, in bytes, of public keys as used in this package.
|
|
||||||
PublicKeySize = 32
|
|
||||||
// PrivateKeySize is the size, in bytes, of private keys as used in this package.
|
|
||||||
PrivateKeySize = 64
|
|
||||||
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
|
|
||||||
SignatureSize = 64
|
|
||||||
)
|
|
||||||
|
|
||||||
// PublicKey is the type of Ed25519 public keys.
|
|
||||||
type PublicKey []byte
|
|
||||||
|
|
||||||
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
|
|
||||||
type PrivateKey []byte
|
|
||||||
|
|
||||||
// Public returns the PublicKey corresponding to priv.
|
|
||||||
func (priv PrivateKey) Public() crypto.PublicKey {
|
|
||||||
publicKey := make([]byte, PublicKeySize)
|
|
||||||
copy(publicKey, priv[32:])
|
|
||||||
return PublicKey(publicKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sign signs the given message with priv.
|
|
||||||
// Ed25519 performs two passes over messages to be signed and therefore cannot
|
|
||||||
// handle pre-hashed messages. Thus opts.HashFunc() must return zero to
|
|
||||||
// indicate the message hasn't been hashed. This can be achieved by passing
|
|
||||||
// crypto.Hash(0) as the value for opts.
|
|
||||||
func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) {
|
|
||||||
if opts.HashFunc() != crypto.Hash(0) {
|
|
||||||
return nil, errors.New("ed25519: cannot sign hashed message")
|
|
||||||
}
|
|
||||||
|
|
||||||
return Sign(priv, message), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenerateKey generates a public/private key pair using entropy from rand.
|
|
||||||
// If rand is nil, crypto/rand.Reader will be used.
|
|
||||||
func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, err error) {
|
|
||||||
if rand == nil {
|
|
||||||
rand = cryptorand.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
privateKey = make([]byte, PrivateKeySize)
|
|
||||||
publicKey = make([]byte, PublicKeySize)
|
|
||||||
_, err = io.ReadFull(rand, privateKey[:32])
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
digest := sha512.Sum512(privateKey[:32])
|
|
||||||
digest[0] &= 248
|
|
||||||
digest[31] &= 127
|
|
||||||
digest[31] |= 64
|
|
||||||
|
|
||||||
var A edwards25519.ExtendedGroupElement
|
|
||||||
var hBytes [32]byte
|
|
||||||
copy(hBytes[:], digest[:])
|
|
||||||
edwards25519.GeScalarMultBase(&A, &hBytes)
|
|
||||||
var publicKeyBytes [32]byte
|
|
||||||
A.ToBytes(&publicKeyBytes)
|
|
||||||
|
|
||||||
copy(privateKey[32:], publicKeyBytes[:])
|
|
||||||
copy(publicKey, publicKeyBytes[:])
|
|
||||||
|
|
||||||
return publicKey, privateKey, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sign signs the message with privateKey and returns a signature. It will
|
|
||||||
// panic if len(privateKey) is not PrivateKeySize.
|
|
||||||
func Sign(privateKey PrivateKey, message []byte) []byte {
|
|
||||||
if l := len(privateKey); l != PrivateKeySize {
|
|
||||||
panic("ed25519: bad private key length: " + strconv.Itoa(l))
|
|
||||||
}
|
|
||||||
|
|
||||||
h := sha512.New()
|
|
||||||
h.Write(privateKey[:32])
|
|
||||||
|
|
||||||
var digest1, messageDigest, hramDigest [64]byte
|
|
||||||
var expandedSecretKey [32]byte
|
|
||||||
h.Sum(digest1[:0])
|
|
||||||
copy(expandedSecretKey[:], digest1[:])
|
|
||||||
expandedSecretKey[0] &= 248
|
|
||||||
expandedSecretKey[31] &= 63
|
|
||||||
expandedSecretKey[31] |= 64
|
|
||||||
|
|
||||||
h.Reset()
|
|
||||||
h.Write(digest1[32:])
|
|
||||||
h.Write(message)
|
|
||||||
h.Sum(messageDigest[:0])
|
|
||||||
|
|
||||||
var messageDigestReduced [32]byte
|
|
||||||
edwards25519.ScReduce(&messageDigestReduced, &messageDigest)
|
|
||||||
var R edwards25519.ExtendedGroupElement
|
|
||||||
edwards25519.GeScalarMultBase(&R, &messageDigestReduced)
|
|
||||||
|
|
||||||
var encodedR [32]byte
|
|
||||||
R.ToBytes(&encodedR)
|
|
||||||
|
|
||||||
h.Reset()
|
|
||||||
h.Write(encodedR[:])
|
|
||||||
h.Write(privateKey[32:])
|
|
||||||
h.Write(message)
|
|
||||||
h.Sum(hramDigest[:0])
|
|
||||||
var hramDigestReduced [32]byte
|
|
||||||
edwards25519.ScReduce(&hramDigestReduced, &hramDigest)
|
|
||||||
|
|
||||||
var s [32]byte
|
|
||||||
edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)
|
|
||||||
|
|
||||||
signature := make([]byte, SignatureSize)
|
|
||||||
copy(signature[:], encodedR[:])
|
|
||||||
copy(signature[32:], s[:])
|
|
||||||
|
|
||||||
return signature
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify reports whether sig is a valid signature of message by publicKey. It
|
|
||||||
// will panic if len(publicKey) is not PublicKeySize.
|
|
||||||
func Verify(publicKey PublicKey, message, sig []byte) bool {
|
|
||||||
if l := len(publicKey); l != PublicKeySize {
|
|
||||||
panic("ed25519: bad public key length: " + strconv.Itoa(l))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(sig) != SignatureSize || sig[63]&224 != 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var A edwards25519.ExtendedGroupElement
|
|
||||||
var publicKeyBytes [32]byte
|
|
||||||
copy(publicKeyBytes[:], publicKey)
|
|
||||||
if !A.FromBytes(&publicKeyBytes) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
edwards25519.FeNeg(&A.X, &A.X)
|
|
||||||
edwards25519.FeNeg(&A.T, &A.T)
|
|
||||||
|
|
||||||
h := sha512.New()
|
|
||||||
h.Write(sig[:32])
|
|
||||||
h.Write(publicKey[:])
|
|
||||||
h.Write(message)
|
|
||||||
var digest [64]byte
|
|
||||||
h.Sum(digest[:0])
|
|
||||||
|
|
||||||
var hReduced [32]byte
|
|
||||||
edwards25519.ScReduce(&hReduced, &digest)
|
|
||||||
|
|
||||||
var R edwards25519.ProjectiveGroupElement
|
|
||||||
var b [32]byte
|
|
||||||
copy(b[:], sig[32:])
|
|
||||||
edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b)
|
|
||||||
|
|
||||||
var checkR [32]byte
|
|
||||||
R.ToBytes(&checkR)
|
|
||||||
return subtle.ConstantTimeCompare(sig[:32], checkR[:]) == 1
|
|
||||||
}
|
|
183
vendor/golang.org/x/crypto/ed25519/ed25519_test.go
generated
vendored
183
vendor/golang.org/x/crypto/ed25519/ed25519_test.go
generated
vendored
|
@ -1,183 +0,0 @@
|
||||||
// Copyright 2016 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 ed25519
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"compress/gzip"
|
|
||||||
"crypto"
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/hex"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/ed25519/internal/edwards25519"
|
|
||||||
)
|
|
||||||
|
|
||||||
type zeroReader struct{}
|
|
||||||
|
|
||||||
func (zeroReader) Read(buf []byte) (int, error) {
|
|
||||||
for i := range buf {
|
|
||||||
buf[i] = 0
|
|
||||||
}
|
|
||||||
return len(buf), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnmarshalMarshal(t *testing.T) {
|
|
||||||
pub, _, _ := GenerateKey(rand.Reader)
|
|
||||||
|
|
||||||
var A edwards25519.ExtendedGroupElement
|
|
||||||
var pubBytes [32]byte
|
|
||||||
copy(pubBytes[:], pub)
|
|
||||||
if !A.FromBytes(&pubBytes) {
|
|
||||||
t.Fatalf("ExtendedGroupElement.FromBytes failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
var pub2 [32]byte
|
|
||||||
A.ToBytes(&pub2)
|
|
||||||
|
|
||||||
if pubBytes != pub2 {
|
|
||||||
t.Errorf("FromBytes(%v)->ToBytes does not round-trip, got %x\n", pubBytes, pub2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSignVerify(t *testing.T) {
|
|
||||||
var zero zeroReader
|
|
||||||
public, private, _ := GenerateKey(zero)
|
|
||||||
|
|
||||||
message := []byte("test message")
|
|
||||||
sig := Sign(private, message)
|
|
||||||
if !Verify(public, message, sig) {
|
|
||||||
t.Errorf("valid signature rejected")
|
|
||||||
}
|
|
||||||
|
|
||||||
wrongMessage := []byte("wrong message")
|
|
||||||
if Verify(public, wrongMessage, sig) {
|
|
||||||
t.Errorf("signature of different message accepted")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCryptoSigner(t *testing.T) {
|
|
||||||
var zero zeroReader
|
|
||||||
public, private, _ := GenerateKey(zero)
|
|
||||||
|
|
||||||
signer := crypto.Signer(private)
|
|
||||||
|
|
||||||
publicInterface := signer.Public()
|
|
||||||
public2, ok := publicInterface.(PublicKey)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("expected PublicKey from Public() but got %T", publicInterface)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(public, public2) {
|
|
||||||
t.Errorf("public keys do not match: original:%x vs Public():%x", public, public2)
|
|
||||||
}
|
|
||||||
|
|
||||||
message := []byte("message")
|
|
||||||
var noHash crypto.Hash
|
|
||||||
signature, err := signer.Sign(zero, message, noHash)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("error from Sign(): %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !Verify(public, message, signature) {
|
|
||||||
t.Errorf("Verify failed on signature from Sign()")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGolden(t *testing.T) {
|
|
||||||
// sign.input.gz is a selection of test cases from
|
|
||||||
// http://ed25519.cr.yp.to/python/sign.input
|
|
||||||
testDataZ, err := os.Open("testdata/sign.input.gz")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer testDataZ.Close()
|
|
||||||
testData, err := gzip.NewReader(testDataZ)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer testData.Close()
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(testData)
|
|
||||||
lineNo := 0
|
|
||||||
|
|
||||||
for scanner.Scan() {
|
|
||||||
lineNo++
|
|
||||||
|
|
||||||
line := scanner.Text()
|
|
||||||
parts := strings.Split(line, ":")
|
|
||||||
if len(parts) != 5 {
|
|
||||||
t.Fatalf("bad number of parts on line %d", lineNo)
|
|
||||||
}
|
|
||||||
|
|
||||||
privBytes, _ := hex.DecodeString(parts[0])
|
|
||||||
pubKey, _ := hex.DecodeString(parts[1])
|
|
||||||
msg, _ := hex.DecodeString(parts[2])
|
|
||||||
sig, _ := hex.DecodeString(parts[3])
|
|
||||||
// The signatures in the test vectors also include the message
|
|
||||||
// at the end, but we just want R and S.
|
|
||||||
sig = sig[:SignatureSize]
|
|
||||||
|
|
||||||
if l := len(pubKey); l != PublicKeySize {
|
|
||||||
t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l)
|
|
||||||
}
|
|
||||||
|
|
||||||
var priv [PrivateKeySize]byte
|
|
||||||
copy(priv[:], privBytes)
|
|
||||||
copy(priv[32:], pubKey)
|
|
||||||
|
|
||||||
sig2 := Sign(priv[:], msg)
|
|
||||||
if !bytes.Equal(sig, sig2[:]) {
|
|
||||||
t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !Verify(pubKey, msg, sig2) {
|
|
||||||
t.Errorf("signature failed to verify on line %d", lineNo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
t.Fatalf("error reading test data: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkKeyGeneration(b *testing.B) {
|
|
||||||
var zero zeroReader
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if _, _, err := GenerateKey(zero); err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkSigning(b *testing.B) {
|
|
||||||
var zero zeroReader
|
|
||||||
_, priv, err := GenerateKey(zero)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
message := []byte("Hello, world!")
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
Sign(priv, message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkVerification(b *testing.B) {
|
|
||||||
var zero zeroReader
|
|
||||||
pub, priv, err := GenerateKey(zero)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
message := []byte("Hello, world!")
|
|
||||||
signature := Sign(priv, message)
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
Verify(pub, message, signature)
|
|
||||||
}
|
|
||||||
}
|
|
1422
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
generated
vendored
1422
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
generated
vendored
File diff suppressed because it is too large
Load diff
1771
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
generated
vendored
1771
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
generated
vendored
File diff suppressed because it is too large
Load diff
BIN
vendor/golang.org/x/crypto/ed25519/testdata/sign.input.gz
generated
vendored
BIN
vendor/golang.org/x/crypto/ed25519/testdata/sign.input.gz
generated
vendored
Binary file not shown.
61
vendor/golang.org/x/crypto/hkdf/example_test.go
generated
vendored
61
vendor/golang.org/x/crypto/hkdf/example_test.go
generated
vendored
|
@ -1,61 +0,0 @@
|
||||||
// Copyright 2014 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 hkdf_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/sha256"
|
|
||||||
"fmt"
|
|
||||||
"golang.org/x/crypto/hkdf"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Usage example that expands one master key into three other cryptographically
|
|
||||||
// secure keys.
|
|
||||||
func Example_usage() {
|
|
||||||
// Underlying hash function to use
|
|
||||||
hash := sha256.New
|
|
||||||
|
|
||||||
// Cryptographically secure master key.
|
|
||||||
master := []byte{0x00, 0x01, 0x02, 0x03} // i.e. NOT this.
|
|
||||||
|
|
||||||
// Non secret salt, optional (can be nil)
|
|
||||||
// Recommended: hash-length sized random
|
|
||||||
salt := make([]byte, hash().Size())
|
|
||||||
n, err := io.ReadFull(rand.Reader, salt)
|
|
||||||
if n != len(salt) || err != nil {
|
|
||||||
fmt.Println("error:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Non secret context specific info, optional (can be nil).
|
|
||||||
// Note, independent from the master key.
|
|
||||||
info := []byte{0x03, 0x14, 0x15, 0x92, 0x65}
|
|
||||||
|
|
||||||
// Create the key derivation function
|
|
||||||
hkdf := hkdf.New(hash, master, salt, info)
|
|
||||||
|
|
||||||
// Generate the required keys
|
|
||||||
keys := make([][]byte, 3)
|
|
||||||
for i := 0; i < len(keys); i++ {
|
|
||||||
keys[i] = make([]byte, 24)
|
|
||||||
n, err := io.ReadFull(hkdf, keys[i])
|
|
||||||
if n != len(keys[i]) || err != nil {
|
|
||||||
fmt.Println("error:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keys should contain 192 bit random keys
|
|
||||||
for i := 1; i <= len(keys); i++ {
|
|
||||||
fmt.Printf("Key #%d: %v\n", i, !bytes.Equal(keys[i-1], make([]byte, 24)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// Key #1: true
|
|
||||||
// Key #2: true
|
|
||||||
// Key #3: true
|
|
||||||
}
|
|
75
vendor/golang.org/x/crypto/hkdf/hkdf.go
generated
vendored
75
vendor/golang.org/x/crypto/hkdf/hkdf.go
generated
vendored
|
@ -1,75 +0,0 @@
|
||||||
// Copyright 2014 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 hkdf implements the HMAC-based Extract-and-Expand Key Derivation
|
|
||||||
// Function (HKDF) as defined in RFC 5869.
|
|
||||||
//
|
|
||||||
// HKDF is a cryptographic key derivation function (KDF) with the goal of
|
|
||||||
// expanding limited input keying material into one or more cryptographically
|
|
||||||
// strong secret keys.
|
|
||||||
//
|
|
||||||
// RFC 5869: https://tools.ietf.org/html/rfc5869
|
|
||||||
package hkdf // import "golang.org/x/crypto/hkdf"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/hmac"
|
|
||||||
"errors"
|
|
||||||
"hash"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
type hkdf struct {
|
|
||||||
expander hash.Hash
|
|
||||||
size int
|
|
||||||
|
|
||||||
info []byte
|
|
||||||
counter byte
|
|
||||||
|
|
||||||
prev []byte
|
|
||||||
cache []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *hkdf) Read(p []byte) (int, error) {
|
|
||||||
// Check whether enough data can be generated
|
|
||||||
need := len(p)
|
|
||||||
remains := len(f.cache) + int(255-f.counter+1)*f.size
|
|
||||||
if remains < need {
|
|
||||||
return 0, errors.New("hkdf: entropy limit reached")
|
|
||||||
}
|
|
||||||
// Read from the cache, if enough data is present
|
|
||||||
n := copy(p, f.cache)
|
|
||||||
p = p[n:]
|
|
||||||
|
|
||||||
// Fill the buffer
|
|
||||||
for len(p) > 0 {
|
|
||||||
f.expander.Reset()
|
|
||||||
f.expander.Write(f.prev)
|
|
||||||
f.expander.Write(f.info)
|
|
||||||
f.expander.Write([]byte{f.counter})
|
|
||||||
f.prev = f.expander.Sum(f.prev[:0])
|
|
||||||
f.counter++
|
|
||||||
|
|
||||||
// Copy the new batch into p
|
|
||||||
f.cache = f.prev
|
|
||||||
n = copy(p, f.cache)
|
|
||||||
p = p[n:]
|
|
||||||
}
|
|
||||||
// Save leftovers for next run
|
|
||||||
f.cache = f.cache[n:]
|
|
||||||
|
|
||||||
return need, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// New returns a new HKDF using the given hash, the secret keying material to expand
|
|
||||||
// and optional salt and info fields.
|
|
||||||
func New(hash func() hash.Hash, secret, salt, info []byte) io.Reader {
|
|
||||||
if salt == nil {
|
|
||||||
salt = make([]byte, hash().Size())
|
|
||||||
}
|
|
||||||
extractor := hmac.New(hash, salt)
|
|
||||||
extractor.Write(secret)
|
|
||||||
prk := extractor.Sum(nil)
|
|
||||||
|
|
||||||
return &hkdf{hmac.New(hash, prk), extractor.Size(), info, 1, nil, nil}
|
|
||||||
}
|
|
370
vendor/golang.org/x/crypto/hkdf/hkdf_test.go
generated
vendored
370
vendor/golang.org/x/crypto/hkdf/hkdf_test.go
generated
vendored
|
@ -1,370 +0,0 @@
|
||||||
// Copyright 2014 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 hkdf
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/md5"
|
|
||||||
"crypto/sha1"
|
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/sha512"
|
|
||||||
"hash"
|
|
||||||
"io"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
type hkdfTest struct {
|
|
||||||
hash func() hash.Hash
|
|
||||||
master []byte
|
|
||||||
salt []byte
|
|
||||||
info []byte
|
|
||||||
out []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
var hkdfTests = []hkdfTest{
|
|
||||||
// Tests from RFC 5869
|
|
||||||
{
|
|
||||||
sha256.New,
|
|
||||||
[]byte{
|
|
||||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
|
||||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
|
||||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
|
||||||
},
|
|
||||||
[]byte{
|
|
||||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
||||||
0x08, 0x09, 0x0a, 0x0b, 0x0c,
|
|
||||||
},
|
|
||||||
[]byte{
|
|
||||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
|
||||||
0xf8, 0xf9,
|
|
||||||
},
|
|
||||||
[]byte{
|
|
||||||
0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a,
|
|
||||||
0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a,
|
|
||||||
0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,
|
|
||||||
0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf,
|
|
||||||
0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18,
|
|
||||||
0x58, 0x65,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
sha256.New,
|
|
||||||
[]byte{
|
|
||||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
||||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
|
||||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
|
||||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
|
||||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
|
||||||
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
|
||||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
|
||||||
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
|
||||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
|
||||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
|
||||||
},
|
|
||||||
[]byte{
|
|
||||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
|
||||||
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
|
||||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
|
||||||
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
|
|
||||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
|
||||||
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
|
||||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
|
||||||
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
|
||||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
|
||||||
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
|
||||||
},
|
|
||||||
[]byte{
|
|
||||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
|
||||||
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
|
||||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
|
||||||
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
|
||||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
|
||||||
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
|
||||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
|
||||||
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
|
||||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
|
||||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
|
|
||||||
},
|
|
||||||
[]byte{
|
|
||||||
0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1,
|
|
||||||
0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34,
|
|
||||||
0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8,
|
|
||||||
0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c,
|
|
||||||
0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72,
|
|
||||||
0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09,
|
|
||||||
0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8,
|
|
||||||
0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71,
|
|
||||||
0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87,
|
|
||||||
0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f,
|
|
||||||
0x1d, 0x87,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
sha256.New,
|
|
||||||
[]byte{
|
|
||||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
|
||||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
|
||||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
|
||||||
},
|
|
||||||
[]byte{},
|
|
||||||
[]byte{},
|
|
||||||
[]byte{
|
|
||||||
0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f,
|
|
||||||
0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31,
|
|
||||||
0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e,
|
|
||||||
0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d,
|
|
||||||
0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a,
|
|
||||||
0x96, 0xc8,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
sha1.New,
|
|
||||||
[]byte{
|
|
||||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
|
||||||
0x0b, 0x0b, 0x0b,
|
|
||||||
},
|
|
||||||
[]byte{
|
|
||||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
||||||
0x08, 0x09, 0x0a, 0x0b, 0x0c,
|
|
||||||
},
|
|
||||||
[]byte{
|
|
||||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
|
||||||
0xf8, 0xf9,
|
|
||||||
},
|
|
||||||
[]byte{
|
|
||||||
0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69,
|
|
||||||
0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81,
|
|
||||||
0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15,
|
|
||||||
0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2,
|
|
||||||
0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3,
|
|
||||||
0xf8, 0x96,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
sha1.New,
|
|
||||||
[]byte{
|
|
||||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
||||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
|
||||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
|
||||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
|
||||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
|
||||||
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
|
||||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
|
||||||
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
|
||||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
|
||||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
|
||||||
},
|
|
||||||
[]byte{
|
|
||||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
|
||||||
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
|
||||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
|
||||||
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
|
|
||||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
|
||||||
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
|
||||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
|
||||||
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
|
||||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
|
||||||
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
|
||||||
},
|
|
||||||
[]byte{
|
|
||||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
|
||||||
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
|
||||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
|
||||||
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
|
||||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
|
||||||
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
|
||||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
|
||||||
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
|
||||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
|
||||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
|
|
||||||
},
|
|
||||||
[]byte{
|
|
||||||
0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7,
|
|
||||||
0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb,
|
|
||||||
0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19,
|
|
||||||
0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe,
|
|
||||||
0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3,
|
|
||||||
0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c,
|
|
||||||
0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed,
|
|
||||||
0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e,
|
|
||||||
0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43,
|
|
||||||
0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52,
|
|
||||||
0xd3, 0xb4,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
sha1.New,
|
|
||||||
[]byte{
|
|
||||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
|
||||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
|
||||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
|
||||||
},
|
|
||||||
[]byte{},
|
|
||||||
[]byte{},
|
|
||||||
[]byte{
|
|
||||||
0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61,
|
|
||||||
0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06,
|
|
||||||
0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06,
|
|
||||||
0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0,
|
|
||||||
0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3,
|
|
||||||
0x49, 0x18,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
sha1.New,
|
|
||||||
[]byte{
|
|
||||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
|
||||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
|
||||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
|
||||||
},
|
|
||||||
nil,
|
|
||||||
[]byte{},
|
|
||||||
[]byte{
|
|
||||||
0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3,
|
|
||||||
0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a,
|
|
||||||
0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23,
|
|
||||||
0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5,
|
|
||||||
0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac,
|
|
||||||
0xfc, 0x48,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHKDF(t *testing.T) {
|
|
||||||
for i, tt := range hkdfTests {
|
|
||||||
hkdf := New(tt.hash, tt.master, tt.salt, tt.info)
|
|
||||||
out := make([]byte, len(tt.out))
|
|
||||||
|
|
||||||
n, err := io.ReadFull(hkdf, out)
|
|
||||||
if n != len(tt.out) || err != nil {
|
|
||||||
t.Errorf("test %d: not enough output bytes: %d.", i, n)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(out, tt.out) {
|
|
||||||
t.Errorf("test %d: incorrect output: have %v, need %v.", i, out, tt.out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHKDFMultiRead(t *testing.T) {
|
|
||||||
for i, tt := range hkdfTests {
|
|
||||||
hkdf := New(tt.hash, tt.master, tt.salt, tt.info)
|
|
||||||
out := make([]byte, len(tt.out))
|
|
||||||
|
|
||||||
for b := 0; b < len(tt.out); b++ {
|
|
||||||
n, err := io.ReadFull(hkdf, out[b:b+1])
|
|
||||||
if n != 1 || err != nil {
|
|
||||||
t.Errorf("test %d.%d: not enough output bytes: have %d, need %d .", i, b, n, len(tt.out))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(out, tt.out) {
|
|
||||||
t.Errorf("test %d: incorrect output: have %v, need %v.", i, out, tt.out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHKDFLimit(t *testing.T) {
|
|
||||||
hash := sha1.New
|
|
||||||
master := []byte{0x00, 0x01, 0x02, 0x03}
|
|
||||||
info := []byte{}
|
|
||||||
|
|
||||||
hkdf := New(hash, master, nil, info)
|
|
||||||
limit := hash().Size() * 255
|
|
||||||
out := make([]byte, limit)
|
|
||||||
|
|
||||||
// The maximum output bytes should be extractable
|
|
||||||
n, err := io.ReadFull(hkdf, out)
|
|
||||||
if n != limit || err != nil {
|
|
||||||
t.Errorf("not enough output bytes: %d, %v.", n, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reading one more should fail
|
|
||||||
n, err = io.ReadFull(hkdf, make([]byte, 1))
|
|
||||||
if n > 0 || err == nil {
|
|
||||||
t.Errorf("key expansion overflowed: n = %d, err = %v", n, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Benchmark16ByteMD5Single(b *testing.B) {
|
|
||||||
benchmarkHKDFSingle(md5.New, 16, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Benchmark20ByteSHA1Single(b *testing.B) {
|
|
||||||
benchmarkHKDFSingle(sha1.New, 20, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Benchmark32ByteSHA256Single(b *testing.B) {
|
|
||||||
benchmarkHKDFSingle(sha256.New, 32, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Benchmark64ByteSHA512Single(b *testing.B) {
|
|
||||||
benchmarkHKDFSingle(sha512.New, 64, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Benchmark8ByteMD5Stream(b *testing.B) {
|
|
||||||
benchmarkHKDFStream(md5.New, 8, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Benchmark16ByteMD5Stream(b *testing.B) {
|
|
||||||
benchmarkHKDFStream(md5.New, 16, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Benchmark8ByteSHA1Stream(b *testing.B) {
|
|
||||||
benchmarkHKDFStream(sha1.New, 8, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Benchmark20ByteSHA1Stream(b *testing.B) {
|
|
||||||
benchmarkHKDFStream(sha1.New, 20, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Benchmark8ByteSHA256Stream(b *testing.B) {
|
|
||||||
benchmarkHKDFStream(sha256.New, 8, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Benchmark32ByteSHA256Stream(b *testing.B) {
|
|
||||||
benchmarkHKDFStream(sha256.New, 32, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Benchmark8ByteSHA512Stream(b *testing.B) {
|
|
||||||
benchmarkHKDFStream(sha512.New, 8, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Benchmark64ByteSHA512Stream(b *testing.B) {
|
|
||||||
benchmarkHKDFStream(sha512.New, 64, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchmarkHKDFSingle(hasher func() hash.Hash, block int, b *testing.B) {
|
|
||||||
master := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}
|
|
||||||
salt := []byte{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17}
|
|
||||||
info := []byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27}
|
|
||||||
out := make([]byte, block)
|
|
||||||
|
|
||||||
b.SetBytes(int64(block))
|
|
||||||
b.ResetTimer()
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
hkdf := New(hasher, master, salt, info)
|
|
||||||
io.ReadFull(hkdf, out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchmarkHKDFStream(hasher func() hash.Hash, block int, b *testing.B) {
|
|
||||||
master := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}
|
|
||||||
salt := []byte{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17}
|
|
||||||
info := []byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27}
|
|
||||||
out := make([]byte, block)
|
|
||||||
|
|
||||||
b.SetBytes(int64(block))
|
|
||||||
b.ResetTimer()
|
|
||||||
|
|
||||||
hkdf := New(hasher, master, salt, info)
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_, err := io.ReadFull(hkdf, out)
|
|
||||||
if err != nil {
|
|
||||||
hkdf = New(hasher, master, salt, info)
|
|
||||||
i--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
118
vendor/golang.org/x/crypto/md4/md4.go
generated
vendored
118
vendor/golang.org/x/crypto/md4/md4.go
generated
vendored
|
@ -1,118 +0,0 @@
|
||||||
// Copyright 2009 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 md4 implements the MD4 hash algorithm as defined in RFC 1320.
|
|
||||||
package md4 // import "golang.org/x/crypto/md4"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto"
|
|
||||||
"hash"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
crypto.RegisterHash(crypto.MD4, New)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The size of an MD4 checksum in bytes.
|
|
||||||
const Size = 16
|
|
||||||
|
|
||||||
// The blocksize of MD4 in bytes.
|
|
||||||
const BlockSize = 64
|
|
||||||
|
|
||||||
const (
|
|
||||||
_Chunk = 64
|
|
||||||
_Init0 = 0x67452301
|
|
||||||
_Init1 = 0xEFCDAB89
|
|
||||||
_Init2 = 0x98BADCFE
|
|
||||||
_Init3 = 0x10325476
|
|
||||||
)
|
|
||||||
|
|
||||||
// digest represents the partial evaluation of a checksum.
|
|
||||||
type digest struct {
|
|
||||||
s [4]uint32
|
|
||||||
x [_Chunk]byte
|
|
||||||
nx int
|
|
||||||
len uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *digest) Reset() {
|
|
||||||
d.s[0] = _Init0
|
|
||||||
d.s[1] = _Init1
|
|
||||||
d.s[2] = _Init2
|
|
||||||
d.s[3] = _Init3
|
|
||||||
d.nx = 0
|
|
||||||
d.len = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// New returns a new hash.Hash computing the MD4 checksum.
|
|
||||||
func New() hash.Hash {
|
|
||||||
d := new(digest)
|
|
||||||
d.Reset()
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *digest) Size() int { return Size }
|
|
||||||
|
|
||||||
func (d *digest) BlockSize() int { return BlockSize }
|
|
||||||
|
|
||||||
func (d *digest) Write(p []byte) (nn int, err error) {
|
|
||||||
nn = len(p)
|
|
||||||
d.len += uint64(nn)
|
|
||||||
if d.nx > 0 {
|
|
||||||
n := len(p)
|
|
||||||
if n > _Chunk-d.nx {
|
|
||||||
n = _Chunk - d.nx
|
|
||||||
}
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
d.x[d.nx+i] = p[i]
|
|
||||||
}
|
|
||||||
d.nx += n
|
|
||||||
if d.nx == _Chunk {
|
|
||||||
_Block(d, d.x[0:])
|
|
||||||
d.nx = 0
|
|
||||||
}
|
|
||||||
p = p[n:]
|
|
||||||
}
|
|
||||||
n := _Block(d, p)
|
|
||||||
p = p[n:]
|
|
||||||
if len(p) > 0 {
|
|
||||||
d.nx = copy(d.x[:], p)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d0 *digest) Sum(in []byte) []byte {
|
|
||||||
// Make a copy of d0, so that caller can keep writing and summing.
|
|
||||||
d := new(digest)
|
|
||||||
*d = *d0
|
|
||||||
|
|
||||||
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
|
|
||||||
len := d.len
|
|
||||||
var tmp [64]byte
|
|
||||||
tmp[0] = 0x80
|
|
||||||
if len%64 < 56 {
|
|
||||||
d.Write(tmp[0 : 56-len%64])
|
|
||||||
} else {
|
|
||||||
d.Write(tmp[0 : 64+56-len%64])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Length in bits.
|
|
||||||
len <<= 3
|
|
||||||
for i := uint(0); i < 8; i++ {
|
|
||||||
tmp[i] = byte(len >> (8 * i))
|
|
||||||
}
|
|
||||||
d.Write(tmp[0:8])
|
|
||||||
|
|
||||||
if d.nx != 0 {
|
|
||||||
panic("d.nx != 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range d.s {
|
|
||||||
in = append(in, byte(s>>0))
|
|
||||||
in = append(in, byte(s>>8))
|
|
||||||
in = append(in, byte(s>>16))
|
|
||||||
in = append(in, byte(s>>24))
|
|
||||||
}
|
|
||||||
return in
|
|
||||||
}
|
|
71
vendor/golang.org/x/crypto/md4/md4_test.go
generated
vendored
71
vendor/golang.org/x/crypto/md4/md4_test.go
generated
vendored
|
@ -1,71 +0,0 @@
|
||||||
// Copyright 2009 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 md4
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
type md4Test struct {
|
|
||||||
out string
|
|
||||||
in string
|
|
||||||
}
|
|
||||||
|
|
||||||
var golden = []md4Test{
|
|
||||||
{"31d6cfe0d16ae931b73c59d7e0c089c0", ""},
|
|
||||||
{"bde52cb31de33e46245e05fbdbd6fb24", "a"},
|
|
||||||
{"ec388dd78999dfc7cf4632465693b6bf", "ab"},
|
|
||||||
{"a448017aaf21d8525fc10ae87aa6729d", "abc"},
|
|
||||||
{"41decd8f579255c5200f86a4bb3ba740", "abcd"},
|
|
||||||
{"9803f4a34e8eb14f96adba49064a0c41", "abcde"},
|
|
||||||
{"804e7f1c2586e50b49ac65db5b645131", "abcdef"},
|
|
||||||
{"752f4adfe53d1da0241b5bc216d098fc", "abcdefg"},
|
|
||||||
{"ad9daf8d49d81988590a6f0e745d15dd", "abcdefgh"},
|
|
||||||
{"1e4e28b05464316b56402b3815ed2dfd", "abcdefghi"},
|
|
||||||
{"dc959c6f5d6f9e04e4380777cc964b3d", "abcdefghij"},
|
|
||||||
{"1b5701e265778898ef7de5623bbe7cc0", "Discard medicine more than two years old."},
|
|
||||||
{"d7f087e090fe7ad4a01cb59dacc9a572", "He who has a shady past knows that nice guys finish last."},
|
|
||||||
{"a6f8fd6df617c72837592fc3570595c9", "I wouldn't marry him with a ten foot pole."},
|
|
||||||
{"c92a84a9526da8abc240c05d6b1a1ce0", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
|
|
||||||
{"f6013160c4dcb00847069fee3bb09803", "The days of the digital watch are numbered. -Tom Stoppard"},
|
|
||||||
{"2c3bb64f50b9107ed57640fe94bec09f", "Nepal premier won't resign."},
|
|
||||||
{"45b7d8a32c7806f2f7f897332774d6e4", "For every action there is an equal and opposite government program."},
|
|
||||||
{"b5b4f9026b175c62d7654bdc3a1cd438", "His money is twice tainted: 'taint yours and 'taint mine."},
|
|
||||||
{"caf44e80f2c20ce19b5ba1cab766e7bd", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
|
|
||||||
{"191fae6707f496aa54a6bce9f2ecf74d", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
|
|
||||||
{"9ddc753e7a4ccee6081cd1b45b23a834", "size: a.out: bad magic"},
|
|
||||||
{"8d050f55b1cadb9323474564be08a521", "The major problem is with sendmail. -Mark Horton"},
|
|
||||||
{"ad6e2587f74c3e3cc19146f6127fa2e3", "Give me a rock, paper and scissors and I will move the world. CCFestoon"},
|
|
||||||
{"1d616d60a5fabe85589c3f1566ca7fca", "If the enemy is within range, then so are you."},
|
|
||||||
{"aec3326a4f496a2ced65a1963f84577f", "It's well we cannot hear the screams/That we create in others' dreams."},
|
|
||||||
{"77b4fd762d6b9245e61c50bf6ebf118b", "You remind me of a TV show, but that's all right: I watch it anyway."},
|
|
||||||
{"e8f48c726bae5e516f6ddb1a4fe62438", "C is as portable as Stonehedge!!"},
|
|
||||||
{"a3a84366e7219e887423b01f9be7166e", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
|
|
||||||
{"a6b7aa35157e984ef5d9b7f32e5fbb52", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule"},
|
|
||||||
{"75661f0545955f8f9abeeb17845f3fd6", "How can you write a big system without C++? -Paul Glick"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGolden(t *testing.T) {
|
|
||||||
for i := 0; i < len(golden); i++ {
|
|
||||||
g := golden[i]
|
|
||||||
c := New()
|
|
||||||
for j := 0; j < 3; j++ {
|
|
||||||
if j < 2 {
|
|
||||||
io.WriteString(c, g.in)
|
|
||||||
} else {
|
|
||||||
io.WriteString(c, g.in[0:len(g.in)/2])
|
|
||||||
c.Sum(nil)
|
|
||||||
io.WriteString(c, g.in[len(g.in)/2:])
|
|
||||||
}
|
|
||||||
s := fmt.Sprintf("%x", c.Sum(nil))
|
|
||||||
if s != g.out {
|
|
||||||
t.Fatalf("md4[%d](%s) = %s want %s", j, g.in, s, g.out)
|
|
||||||
}
|
|
||||||
c.Reset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
89
vendor/golang.org/x/crypto/md4/md4block.go
generated
vendored
89
vendor/golang.org/x/crypto/md4/md4block.go
generated
vendored
|
@ -1,89 +0,0 @@
|
||||||
// Copyright 2009 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.
|
|
||||||
|
|
||||||
// MD4 block step.
|
|
||||||
// In its own file so that a faster assembly or C version
|
|
||||||
// can be substituted easily.
|
|
||||||
|
|
||||||
package md4
|
|
||||||
|
|
||||||
var shift1 = []uint{3, 7, 11, 19}
|
|
||||||
var shift2 = []uint{3, 5, 9, 13}
|
|
||||||
var shift3 = []uint{3, 9, 11, 15}
|
|
||||||
|
|
||||||
var xIndex2 = []uint{0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15}
|
|
||||||
var xIndex3 = []uint{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}
|
|
||||||
|
|
||||||
func _Block(dig *digest, p []byte) int {
|
|
||||||
a := dig.s[0]
|
|
||||||
b := dig.s[1]
|
|
||||||
c := dig.s[2]
|
|
||||||
d := dig.s[3]
|
|
||||||
n := 0
|
|
||||||
var X [16]uint32
|
|
||||||
for len(p) >= _Chunk {
|
|
||||||
aa, bb, cc, dd := a, b, c, d
|
|
||||||
|
|
||||||
j := 0
|
|
||||||
for i := 0; i < 16; i++ {
|
|
||||||
X[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
|
|
||||||
j += 4
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this needs to be made faster in the future,
|
|
||||||
// the usual trick is to unroll each of these
|
|
||||||
// loops by a factor of 4; that lets you replace
|
|
||||||
// the shift[] lookups with constants and,
|
|
||||||
// with suitable variable renaming in each
|
|
||||||
// unrolled body, delete the a, b, c, d = d, a, b, c
|
|
||||||
// (or you can let the optimizer do the renaming).
|
|
||||||
//
|
|
||||||
// The index variables are uint so that % by a power
|
|
||||||
// of two can be optimized easily by a compiler.
|
|
||||||
|
|
||||||
// Round 1.
|
|
||||||
for i := uint(0); i < 16; i++ {
|
|
||||||
x := i
|
|
||||||
s := shift1[i%4]
|
|
||||||
f := ((c ^ d) & b) ^ d
|
|
||||||
a += f + X[x]
|
|
||||||
a = a<<s | a>>(32-s)
|
|
||||||
a, b, c, d = d, a, b, c
|
|
||||||
}
|
|
||||||
|
|
||||||
// Round 2.
|
|
||||||
for i := uint(0); i < 16; i++ {
|
|
||||||
x := xIndex2[i]
|
|
||||||
s := shift2[i%4]
|
|
||||||
g := (b & c) | (b & d) | (c & d)
|
|
||||||
a += g + X[x] + 0x5a827999
|
|
||||||
a = a<<s | a>>(32-s)
|
|
||||||
a, b, c, d = d, a, b, c
|
|
||||||
}
|
|
||||||
|
|
||||||
// Round 3.
|
|
||||||
for i := uint(0); i < 16; i++ {
|
|
||||||
x := xIndex3[i]
|
|
||||||
s := shift3[i%4]
|
|
||||||
h := b ^ c ^ d
|
|
||||||
a += h + X[x] + 0x6ed9eba1
|
|
||||||
a = a<<s | a>>(32-s)
|
|
||||||
a, b, c, d = d, a, b, c
|
|
||||||
}
|
|
||||||
|
|
||||||
a += aa
|
|
||||||
b += bb
|
|
||||||
c += cc
|
|
||||||
d += dd
|
|
||||||
|
|
||||||
p = p[_Chunk:]
|
|
||||||
n += _Chunk
|
|
||||||
}
|
|
||||||
|
|
||||||
dig.s[0] = a
|
|
||||||
dig.s[1] = b
|
|
||||||
dig.s[2] = c
|
|
||||||
dig.s[3] = d
|
|
||||||
return n
|
|
||||||
}
|
|
85
vendor/golang.org/x/crypto/nacl/box/box.go
generated
vendored
85
vendor/golang.org/x/crypto/nacl/box/box.go
generated
vendored
|
@ -1,85 +0,0 @@
|
||||||
// Copyright 2012 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 box authenticates and encrypts messages using public-key cryptography.
|
|
||||||
|
|
||||||
Box uses Curve25519, XSalsa20 and Poly1305 to encrypt and authenticate
|
|
||||||
messages. The length of messages is not hidden.
|
|
||||||
|
|
||||||
It is the caller's responsibility to ensure the uniqueness of nonces—for
|
|
||||||
example, by using nonce 1 for the first message, nonce 2 for the second
|
|
||||||
message, etc. Nonces are long enough that randomly generated nonces have
|
|
||||||
negligible risk of collision.
|
|
||||||
|
|
||||||
This package is interoperable with NaCl: http://nacl.cr.yp.to/box.html.
|
|
||||||
*/
|
|
||||||
package box // import "golang.org/x/crypto/nacl/box"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"golang.org/x/crypto/curve25519"
|
|
||||||
"golang.org/x/crypto/nacl/secretbox"
|
|
||||||
"golang.org/x/crypto/salsa20/salsa"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Overhead is the number of bytes of overhead when boxing a message.
|
|
||||||
const Overhead = secretbox.Overhead
|
|
||||||
|
|
||||||
// GenerateKey generates a new public/private key pair suitable for use with
|
|
||||||
// Seal and Open.
|
|
||||||
func GenerateKey(rand io.Reader) (publicKey, privateKey *[32]byte, err error) {
|
|
||||||
publicKey = new([32]byte)
|
|
||||||
privateKey = new([32]byte)
|
|
||||||
_, err = io.ReadFull(rand, privateKey[:])
|
|
||||||
if err != nil {
|
|
||||||
publicKey = nil
|
|
||||||
privateKey = nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
curve25519.ScalarBaseMult(publicKey, privateKey)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var zeros [16]byte
|
|
||||||
|
|
||||||
// Precompute calculates the shared key between peersPublicKey and privateKey
|
|
||||||
// and writes it to sharedKey. The shared key can be used with
|
|
||||||
// OpenAfterPrecomputation and SealAfterPrecomputation to speed up processing
|
|
||||||
// when using the same pair of keys repeatedly.
|
|
||||||
func Precompute(sharedKey, peersPublicKey, privateKey *[32]byte) {
|
|
||||||
curve25519.ScalarMult(sharedKey, privateKey, peersPublicKey)
|
|
||||||
salsa.HSalsa20(sharedKey, &zeros, sharedKey, &salsa.Sigma)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Seal appends an encrypted and authenticated copy of message to out, which
|
|
||||||
// will be Overhead bytes longer than the original and must not overlap. The
|
|
||||||
// nonce must be unique for each distinct message for a given pair of keys.
|
|
||||||
func Seal(out, message []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) []byte {
|
|
||||||
var sharedKey [32]byte
|
|
||||||
Precompute(&sharedKey, peersPublicKey, privateKey)
|
|
||||||
return secretbox.Seal(out, message, nonce, &sharedKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SealAfterPrecomputation performs the same actions as Seal, but takes a
|
|
||||||
// shared key as generated by Precompute.
|
|
||||||
func SealAfterPrecomputation(out, message []byte, nonce *[24]byte, sharedKey *[32]byte) []byte {
|
|
||||||
return secretbox.Seal(out, message, nonce, sharedKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open authenticates and decrypts a box produced by Seal and appends the
|
|
||||||
// message to out, which must not overlap box. The output will be Overhead
|
|
||||||
// bytes smaller than box.
|
|
||||||
func Open(out, box []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) ([]byte, bool) {
|
|
||||||
var sharedKey [32]byte
|
|
||||||
Precompute(&sharedKey, peersPublicKey, privateKey)
|
|
||||||
return secretbox.Open(out, box, nonce, &sharedKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpenAfterPrecomputation performs the same actions as Open, but takes a
|
|
||||||
// shared key as generated by Precompute.
|
|
||||||
func OpenAfterPrecomputation(out, box []byte, nonce *[24]byte, sharedKey *[32]byte) ([]byte, bool) {
|
|
||||||
return secretbox.Open(out, box, nonce, sharedKey)
|
|
||||||
}
|
|
78
vendor/golang.org/x/crypto/nacl/box/box_test.go
generated
vendored
78
vendor/golang.org/x/crypto/nacl/box/box_test.go
generated
vendored
|
@ -1,78 +0,0 @@
|
||||||
// Copyright 2012 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 box
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/hex"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/curve25519"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSealOpen(t *testing.T) {
|
|
||||||
publicKey1, privateKey1, _ := GenerateKey(rand.Reader)
|
|
||||||
publicKey2, privateKey2, _ := GenerateKey(rand.Reader)
|
|
||||||
|
|
||||||
if *privateKey1 == *privateKey2 {
|
|
||||||
t.Fatalf("private keys are equal!")
|
|
||||||
}
|
|
||||||
if *publicKey1 == *publicKey2 {
|
|
||||||
t.Fatalf("public keys are equal!")
|
|
||||||
}
|
|
||||||
message := []byte("test message")
|
|
||||||
var nonce [24]byte
|
|
||||||
|
|
||||||
box := Seal(nil, message, &nonce, publicKey1, privateKey2)
|
|
||||||
opened, ok := Open(nil, box, &nonce, publicKey2, privateKey1)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("failed to open box")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(opened, message) {
|
|
||||||
t.Fatalf("got %x, want %x", opened, message)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range box {
|
|
||||||
box[i] ^= 0x40
|
|
||||||
_, ok := Open(nil, box, &nonce, publicKey2, privateKey1)
|
|
||||||
if ok {
|
|
||||||
t.Fatalf("opened box with byte %d corrupted", i)
|
|
||||||
}
|
|
||||||
box[i] ^= 0x40
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBox(t *testing.T) {
|
|
||||||
var privateKey1, privateKey2 [32]byte
|
|
||||||
for i := range privateKey1[:] {
|
|
||||||
privateKey1[i] = 1
|
|
||||||
}
|
|
||||||
for i := range privateKey2[:] {
|
|
||||||
privateKey2[i] = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
var publicKey1 [32]byte
|
|
||||||
curve25519.ScalarBaseMult(&publicKey1, &privateKey1)
|
|
||||||
var message [64]byte
|
|
||||||
for i := range message[:] {
|
|
||||||
message[i] = 3
|
|
||||||
}
|
|
||||||
|
|
||||||
var nonce [24]byte
|
|
||||||
for i := range nonce[:] {
|
|
||||||
nonce[i] = 4
|
|
||||||
}
|
|
||||||
|
|
||||||
box := Seal(nil, message[:], &nonce, &publicKey1, &privateKey2)
|
|
||||||
|
|
||||||
// expected was generated using the C implementation of NaCl.
|
|
||||||
expected, _ := hex.DecodeString("78ea30b19d2341ebbdba54180f821eec265cf86312549bea8a37652a8bb94f07b78a73ed1708085e6ddd0e943bbdeb8755079a37eb31d86163ce241164a47629c0539f330b4914cd135b3855bc2a2dfc")
|
|
||||||
|
|
||||||
if !bytes.Equal(box, expected) {
|
|
||||||
t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected)
|
|
||||||
}
|
|
||||||
}
|
|
149
vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go
generated
vendored
149
vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go
generated
vendored
|
@ -1,149 +0,0 @@
|
||||||
// Copyright 2012 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 secretbox encrypts and authenticates small messages.
|
|
||||||
|
|
||||||
Secretbox uses XSalsa20 and Poly1305 to encrypt and authenticate messages with
|
|
||||||
secret-key cryptography. The length of messages is not hidden.
|
|
||||||
|
|
||||||
It is the caller's responsibility to ensure the uniqueness of nonces—for
|
|
||||||
example, by using nonce 1 for the first message, nonce 2 for the second
|
|
||||||
message, etc. Nonces are long enough that randomly generated nonces have
|
|
||||||
negligible risk of collision.
|
|
||||||
|
|
||||||
This package is interoperable with NaCl: http://nacl.cr.yp.to/secretbox.html.
|
|
||||||
*/
|
|
||||||
package secretbox // import "golang.org/x/crypto/nacl/secretbox"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"golang.org/x/crypto/poly1305"
|
|
||||||
"golang.org/x/crypto/salsa20/salsa"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Overhead is the number of bytes of overhead when boxing a message.
|
|
||||||
const Overhead = poly1305.TagSize
|
|
||||||
|
|
||||||
// setup produces a sub-key and Salsa20 counter given a nonce and key.
|
|
||||||
func setup(subKey *[32]byte, counter *[16]byte, nonce *[24]byte, key *[32]byte) {
|
|
||||||
// We use XSalsa20 for encryption so first we need to generate a
|
|
||||||
// key and nonce with HSalsa20.
|
|
||||||
var hNonce [16]byte
|
|
||||||
copy(hNonce[:], nonce[:])
|
|
||||||
salsa.HSalsa20(subKey, &hNonce, key, &salsa.Sigma)
|
|
||||||
|
|
||||||
// The final 8 bytes of the original nonce form the new nonce.
|
|
||||||
copy(counter[:], nonce[16:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// sliceForAppend takes a slice and a requested number of bytes. It returns a
|
|
||||||
// slice with the contents of the given slice followed by that many bytes and a
|
|
||||||
// second slice that aliases into it and contains only the extra bytes. If the
|
|
||||||
// original slice has sufficient capacity then no allocation is performed.
|
|
||||||
func sliceForAppend(in []byte, n int) (head, tail []byte) {
|
|
||||||
if total := len(in) + n; cap(in) >= total {
|
|
||||||
head = in[:total]
|
|
||||||
} else {
|
|
||||||
head = make([]byte, total)
|
|
||||||
copy(head, in)
|
|
||||||
}
|
|
||||||
tail = head[len(in):]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Seal appends an encrypted and authenticated copy of message to out, which
|
|
||||||
// must not overlap message. The key and nonce pair must be unique for each
|
|
||||||
// distinct message and the output will be Overhead bytes longer than message.
|
|
||||||
func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte {
|
|
||||||
var subKey [32]byte
|
|
||||||
var counter [16]byte
|
|
||||||
setup(&subKey, &counter, nonce, key)
|
|
||||||
|
|
||||||
// The Poly1305 key is generated by encrypting 32 bytes of zeros. Since
|
|
||||||
// Salsa20 works with 64-byte blocks, we also generate 32 bytes of
|
|
||||||
// keystream as a side effect.
|
|
||||||
var firstBlock [64]byte
|
|
||||||
salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey)
|
|
||||||
|
|
||||||
var poly1305Key [32]byte
|
|
||||||
copy(poly1305Key[:], firstBlock[:])
|
|
||||||
|
|
||||||
ret, out := sliceForAppend(out, len(message)+poly1305.TagSize)
|
|
||||||
|
|
||||||
// We XOR up to 32 bytes of message with the keystream generated from
|
|
||||||
// the first block.
|
|
||||||
firstMessageBlock := message
|
|
||||||
if len(firstMessageBlock) > 32 {
|
|
||||||
firstMessageBlock = firstMessageBlock[:32]
|
|
||||||
}
|
|
||||||
|
|
||||||
tagOut := out
|
|
||||||
out = out[poly1305.TagSize:]
|
|
||||||
for i, x := range firstMessageBlock {
|
|
||||||
out[i] = firstBlock[32+i] ^ x
|
|
||||||
}
|
|
||||||
message = message[len(firstMessageBlock):]
|
|
||||||
ciphertext := out
|
|
||||||
out = out[len(firstMessageBlock):]
|
|
||||||
|
|
||||||
// Now encrypt the rest.
|
|
||||||
counter[8] = 1
|
|
||||||
salsa.XORKeyStream(out, message, &counter, &subKey)
|
|
||||||
|
|
||||||
var tag [poly1305.TagSize]byte
|
|
||||||
poly1305.Sum(&tag, ciphertext, &poly1305Key)
|
|
||||||
copy(tagOut, tag[:])
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open authenticates and decrypts a box produced by Seal and appends the
|
|
||||||
// message to out, which must not overlap box. The output will be Overhead
|
|
||||||
// bytes smaller than box.
|
|
||||||
func Open(out []byte, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) {
|
|
||||||
if len(box) < Overhead {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
var subKey [32]byte
|
|
||||||
var counter [16]byte
|
|
||||||
setup(&subKey, &counter, nonce, key)
|
|
||||||
|
|
||||||
// The Poly1305 key is generated by encrypting 32 bytes of zeros. Since
|
|
||||||
// Salsa20 works with 64-byte blocks, we also generate 32 bytes of
|
|
||||||
// keystream as a side effect.
|
|
||||||
var firstBlock [64]byte
|
|
||||||
salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey)
|
|
||||||
|
|
||||||
var poly1305Key [32]byte
|
|
||||||
copy(poly1305Key[:], firstBlock[:])
|
|
||||||
var tag [poly1305.TagSize]byte
|
|
||||||
copy(tag[:], box)
|
|
||||||
|
|
||||||
if !poly1305.Verify(&tag, box[poly1305.TagSize:], &poly1305Key) {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
ret, out := sliceForAppend(out, len(box)-Overhead)
|
|
||||||
|
|
||||||
// We XOR up to 32 bytes of box with the keystream generated from
|
|
||||||
// the first block.
|
|
||||||
box = box[Overhead:]
|
|
||||||
firstMessageBlock := box
|
|
||||||
if len(firstMessageBlock) > 32 {
|
|
||||||
firstMessageBlock = firstMessageBlock[:32]
|
|
||||||
}
|
|
||||||
for i, x := range firstMessageBlock {
|
|
||||||
out[i] = firstBlock[32+i] ^ x
|
|
||||||
}
|
|
||||||
|
|
||||||
box = box[len(firstMessageBlock):]
|
|
||||||
out = out[len(firstMessageBlock):]
|
|
||||||
|
|
||||||
// Now decrypt the rest.
|
|
||||||
counter[8] = 1
|
|
||||||
salsa.XORKeyStream(out, box, &counter, &subKey)
|
|
||||||
|
|
||||||
return ret, true
|
|
||||||
}
|
|
91
vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go
generated
vendored
91
vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go
generated
vendored
|
@ -1,91 +0,0 @@
|
||||||
// Copyright 2012 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 secretbox
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/hex"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSealOpen(t *testing.T) {
|
|
||||||
var key [32]byte
|
|
||||||
var nonce [24]byte
|
|
||||||
|
|
||||||
rand.Reader.Read(key[:])
|
|
||||||
rand.Reader.Read(nonce[:])
|
|
||||||
|
|
||||||
var box, opened []byte
|
|
||||||
|
|
||||||
for msgLen := 0; msgLen < 128; msgLen += 17 {
|
|
||||||
message := make([]byte, msgLen)
|
|
||||||
rand.Reader.Read(message)
|
|
||||||
|
|
||||||
box = Seal(box[:0], message, &nonce, &key)
|
|
||||||
var ok bool
|
|
||||||
opened, ok = Open(opened[:0], box, &nonce, &key)
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("%d: failed to open box", msgLen)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(opened, message) {
|
|
||||||
t.Errorf("%d: got %x, expected %x", msgLen, opened, message)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range box {
|
|
||||||
box[i] ^= 0x20
|
|
||||||
_, ok := Open(opened[:0], box, &nonce, &key)
|
|
||||||
if ok {
|
|
||||||
t.Errorf("box was opened after corrupting byte %d", i)
|
|
||||||
}
|
|
||||||
box[i] ^= 0x20
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSecretBox(t *testing.T) {
|
|
||||||
var key [32]byte
|
|
||||||
var nonce [24]byte
|
|
||||||
var message [64]byte
|
|
||||||
|
|
||||||
for i := range key[:] {
|
|
||||||
key[i] = 1
|
|
||||||
}
|
|
||||||
for i := range nonce[:] {
|
|
||||||
nonce[i] = 2
|
|
||||||
}
|
|
||||||
for i := range message[:] {
|
|
||||||
message[i] = 3
|
|
||||||
}
|
|
||||||
|
|
||||||
box := Seal(nil, message[:], &nonce, &key)
|
|
||||||
// expected was generated using the C implementation of NaCl.
|
|
||||||
expected, _ := hex.DecodeString("8442bc313f4626f1359e3b50122b6ce6fe66ddfe7d39d14e637eb4fd5b45beadab55198df6ab5368439792a23c87db70acb6156dc5ef957ac04f6276cf6093b84be77ff0849cc33e34b7254d5a8f65ad")
|
|
||||||
|
|
||||||
if !bytes.Equal(box, expected) {
|
|
||||||
t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAppend(t *testing.T) {
|
|
||||||
var key [32]byte
|
|
||||||
var nonce [24]byte
|
|
||||||
var message [8]byte
|
|
||||||
|
|
||||||
out := make([]byte, 4)
|
|
||||||
box := Seal(out, message[:], &nonce, &key)
|
|
||||||
if !bytes.Equal(box[:4], out[:4]) {
|
|
||||||
t.Fatalf("Seal didn't correctly append")
|
|
||||||
}
|
|
||||||
|
|
||||||
out = make([]byte, 4, 100)
|
|
||||||
box = Seal(out, message[:], &nonce, &key)
|
|
||||||
if !bytes.Equal(box[:4], out[:4]) {
|
|
||||||
t.Fatalf("Seal didn't correctly append with sufficient capacity.")
|
|
||||||
}
|
|
||||||
}
|
|
673
vendor/golang.org/x/crypto/ocsp/ocsp.go
generated
vendored
673
vendor/golang.org/x/crypto/ocsp/ocsp.go
generated
vendored
|
@ -1,673 +0,0 @@
|
||||||
// Copyright 2013 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 ocsp parses OCSP responses as specified in RFC 2560. OCSP responses
|
|
||||||
// are signed messages attesting to the validity of a certificate for a small
|
|
||||||
// period of time. This is used to manage revocation for X.509 certificates.
|
|
||||||
package ocsp // import "golang.org/x/crypto/ocsp"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto"
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/elliptic"
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/rsa"
|
|
||||||
"crypto/sha1"
|
|
||||||
"crypto/x509"
|
|
||||||
"crypto/x509/pkix"
|
|
||||||
"encoding/asn1"
|
|
||||||
"errors"
|
|
||||||
"math/big"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1})
|
|
||||||
|
|
||||||
// ResponseStatus contains the result of an OCSP request. See
|
|
||||||
// https://tools.ietf.org/html/rfc6960#section-2.3
|
|
||||||
type ResponseStatus int
|
|
||||||
|
|
||||||
const (
|
|
||||||
Success ResponseStatus = 0
|
|
||||||
Malformed ResponseStatus = 1
|
|
||||||
InternalError ResponseStatus = 2
|
|
||||||
TryLater ResponseStatus = 3
|
|
||||||
// Status code four is ununsed in OCSP. See
|
|
||||||
// https://tools.ietf.org/html/rfc6960#section-4.2.1
|
|
||||||
SignatureRequired ResponseStatus = 5
|
|
||||||
Unauthorized ResponseStatus = 6
|
|
||||||
)
|
|
||||||
|
|
||||||
func (r ResponseStatus) String() string {
|
|
||||||
switch r {
|
|
||||||
case Success:
|
|
||||||
return "success"
|
|
||||||
case Malformed:
|
|
||||||
return "malformed"
|
|
||||||
case InternalError:
|
|
||||||
return "internal error"
|
|
||||||
case TryLater:
|
|
||||||
return "try later"
|
|
||||||
case SignatureRequired:
|
|
||||||
return "signature required"
|
|
||||||
case Unauthorized:
|
|
||||||
return "unauthorized"
|
|
||||||
default:
|
|
||||||
return "unknown OCSP status: " + strconv.Itoa(int(r))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResponseError is an error that may be returned by ParseResponse to indicate
|
|
||||||
// that the response itself is an error, not just that its indicating that a
|
|
||||||
// certificate is revoked, unknown, etc.
|
|
||||||
type ResponseError struct {
|
|
||||||
Status ResponseStatus
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r ResponseError) Error() string {
|
|
||||||
return "ocsp: error from server: " + r.Status.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// These are internal structures that reflect the ASN.1 structure of an OCSP
|
|
||||||
// response. See RFC 2560, section 4.2.
|
|
||||||
|
|
||||||
type certID struct {
|
|
||||||
HashAlgorithm pkix.AlgorithmIdentifier
|
|
||||||
NameHash []byte
|
|
||||||
IssuerKeyHash []byte
|
|
||||||
SerialNumber *big.Int
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://tools.ietf.org/html/rfc2560#section-4.1.1
|
|
||||||
type ocspRequest struct {
|
|
||||||
TBSRequest tbsRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
type tbsRequest struct {
|
|
||||||
Version int `asn1:"explicit,tag:0,default:0,optional"`
|
|
||||||
RequestorName pkix.RDNSequence `asn1:"explicit,tag:1,optional"`
|
|
||||||
RequestList []request
|
|
||||||
}
|
|
||||||
|
|
||||||
type request struct {
|
|
||||||
Cert certID
|
|
||||||
}
|
|
||||||
|
|
||||||
type responseASN1 struct {
|
|
||||||
Status asn1.Enumerated
|
|
||||||
Response responseBytes `asn1:"explicit,tag:0,optional"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type responseBytes struct {
|
|
||||||
ResponseType asn1.ObjectIdentifier
|
|
||||||
Response []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type basicResponse struct {
|
|
||||||
TBSResponseData responseData
|
|
||||||
SignatureAlgorithm pkix.AlgorithmIdentifier
|
|
||||||
Signature asn1.BitString
|
|
||||||
Certificates []asn1.RawValue `asn1:"explicit,tag:0,optional"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type responseData struct {
|
|
||||||
Raw asn1.RawContent
|
|
||||||
Version int `asn1:"optional,default:1,explicit,tag:0"`
|
|
||||||
RawResponderName asn1.RawValue `asn1:"optional,explicit,tag:1"`
|
|
||||||
KeyHash []byte `asn1:"optional,explicit,tag:2"`
|
|
||||||
ProducedAt time.Time `asn1:"generalized"`
|
|
||||||
Responses []singleResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
type singleResponse struct {
|
|
||||||
CertID certID
|
|
||||||
Good asn1.Flag `asn1:"tag:0,optional"`
|
|
||||||
Revoked revokedInfo `asn1:"tag:1,optional"`
|
|
||||||
Unknown asn1.Flag `asn1:"tag:2,optional"`
|
|
||||||
ThisUpdate time.Time `asn1:"generalized"`
|
|
||||||
NextUpdate time.Time `asn1:"generalized,explicit,tag:0,optional"`
|
|
||||||
SingleExtensions []pkix.Extension `asn1:"explicit,tag:1,optional"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type revokedInfo struct {
|
|
||||||
RevocationTime time.Time `asn1:"generalized"`
|
|
||||||
Reason asn1.Enumerated `asn1:"explicit,tag:0,optional"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
|
|
||||||
oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
|
|
||||||
oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
|
|
||||||
oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
|
|
||||||
oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
|
|
||||||
oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
|
|
||||||
oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
|
|
||||||
oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2}
|
|
||||||
oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
|
|
||||||
oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
|
|
||||||
oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
|
|
||||||
oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
|
|
||||||
)
|
|
||||||
|
|
||||||
var hashOIDs = map[crypto.Hash]asn1.ObjectIdentifier{
|
|
||||||
crypto.SHA1: asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}),
|
|
||||||
crypto.SHA256: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1}),
|
|
||||||
crypto.SHA384: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2}),
|
|
||||||
crypto.SHA512: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3}),
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below
|
|
||||||
var signatureAlgorithmDetails = []struct {
|
|
||||||
algo x509.SignatureAlgorithm
|
|
||||||
oid asn1.ObjectIdentifier
|
|
||||||
pubKeyAlgo x509.PublicKeyAlgorithm
|
|
||||||
hash crypto.Hash
|
|
||||||
}{
|
|
||||||
{x509.MD2WithRSA, oidSignatureMD2WithRSA, x509.RSA, crypto.Hash(0) /* no value for MD2 */},
|
|
||||||
{x509.MD5WithRSA, oidSignatureMD5WithRSA, x509.RSA, crypto.MD5},
|
|
||||||
{x509.SHA1WithRSA, oidSignatureSHA1WithRSA, x509.RSA, crypto.SHA1},
|
|
||||||
{x509.SHA256WithRSA, oidSignatureSHA256WithRSA, x509.RSA, crypto.SHA256},
|
|
||||||
{x509.SHA384WithRSA, oidSignatureSHA384WithRSA, x509.RSA, crypto.SHA384},
|
|
||||||
{x509.SHA512WithRSA, oidSignatureSHA512WithRSA, x509.RSA, crypto.SHA512},
|
|
||||||
{x509.DSAWithSHA1, oidSignatureDSAWithSHA1, x509.DSA, crypto.SHA1},
|
|
||||||
{x509.DSAWithSHA256, oidSignatureDSAWithSHA256, x509.DSA, crypto.SHA256},
|
|
||||||
{x509.ECDSAWithSHA1, oidSignatureECDSAWithSHA1, x509.ECDSA, crypto.SHA1},
|
|
||||||
{x509.ECDSAWithSHA256, oidSignatureECDSAWithSHA256, x509.ECDSA, crypto.SHA256},
|
|
||||||
{x509.ECDSAWithSHA384, oidSignatureECDSAWithSHA384, x509.ECDSA, crypto.SHA384},
|
|
||||||
{x509.ECDSAWithSHA512, oidSignatureECDSAWithSHA512, x509.ECDSA, crypto.SHA512},
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below
|
|
||||||
func signingParamsForPublicKey(pub interface{}, requestedSigAlgo x509.SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) {
|
|
||||||
var pubType x509.PublicKeyAlgorithm
|
|
||||||
|
|
||||||
switch pub := pub.(type) {
|
|
||||||
case *rsa.PublicKey:
|
|
||||||
pubType = x509.RSA
|
|
||||||
hashFunc = crypto.SHA256
|
|
||||||
sigAlgo.Algorithm = oidSignatureSHA256WithRSA
|
|
||||||
sigAlgo.Parameters = asn1.RawValue{
|
|
||||||
Tag: 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
case *ecdsa.PublicKey:
|
|
||||||
pubType = x509.ECDSA
|
|
||||||
|
|
||||||
switch pub.Curve {
|
|
||||||
case elliptic.P224(), elliptic.P256():
|
|
||||||
hashFunc = crypto.SHA256
|
|
||||||
sigAlgo.Algorithm = oidSignatureECDSAWithSHA256
|
|
||||||
case elliptic.P384():
|
|
||||||
hashFunc = crypto.SHA384
|
|
||||||
sigAlgo.Algorithm = oidSignatureECDSAWithSHA384
|
|
||||||
case elliptic.P521():
|
|
||||||
hashFunc = crypto.SHA512
|
|
||||||
sigAlgo.Algorithm = oidSignatureECDSAWithSHA512
|
|
||||||
default:
|
|
||||||
err = errors.New("x509: unknown elliptic curve")
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
err = errors.New("x509: only RSA and ECDSA keys supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if requestedSigAlgo == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
found := false
|
|
||||||
for _, details := range signatureAlgorithmDetails {
|
|
||||||
if details.algo == requestedSigAlgo {
|
|
||||||
if details.pubKeyAlgo != pubType {
|
|
||||||
err = errors.New("x509: requested SignatureAlgorithm does not match private key type")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sigAlgo.Algorithm, hashFunc = details.oid, details.hash
|
|
||||||
if hashFunc == 0 {
|
|
||||||
err = errors.New("x509: cannot sign with hash function requested")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
err = errors.New("x509: unknown SignatureAlgorithm")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(agl): this is taken from crypto/x509 and so should probably be exported
|
|
||||||
// from crypto/x509 or crypto/x509/pkix.
|
|
||||||
func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm {
|
|
||||||
for _, details := range signatureAlgorithmDetails {
|
|
||||||
if oid.Equal(details.oid) {
|
|
||||||
return details.algo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return x509.UnknownSignatureAlgorithm
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(rlb): This is not taken from crypto/x509, but it's of the same general form.
|
|
||||||
func getHashAlgorithmFromOID(target asn1.ObjectIdentifier) crypto.Hash {
|
|
||||||
for hash, oid := range hashOIDs {
|
|
||||||
if oid.Equal(target) {
|
|
||||||
return hash
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return crypto.Hash(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is the exposed reflection of the internal OCSP structures.
|
|
||||||
|
|
||||||
// The status values that can be expressed in OCSP. See RFC 6960.
|
|
||||||
const (
|
|
||||||
// Good means that the certificate is valid.
|
|
||||||
Good = iota
|
|
||||||
// Revoked means that the certificate has been deliberately revoked.
|
|
||||||
Revoked
|
|
||||||
// Unknown means that the OCSP responder doesn't know about the certificate.
|
|
||||||
Unknown
|
|
||||||
// ServerFailed is unused and was never used (see
|
|
||||||
// https://go-review.googlesource.com/#/c/18944). ParseResponse will
|
|
||||||
// return a ResponseError when an error response is parsed.
|
|
||||||
ServerFailed
|
|
||||||
)
|
|
||||||
|
|
||||||
// The enumerated reasons for revoking a certificate. See RFC 5280.
|
|
||||||
const (
|
|
||||||
Unspecified = iota
|
|
||||||
KeyCompromise = iota
|
|
||||||
CACompromise = iota
|
|
||||||
AffiliationChanged = iota
|
|
||||||
Superseded = iota
|
|
||||||
CessationOfOperation = iota
|
|
||||||
CertificateHold = iota
|
|
||||||
_ = iota
|
|
||||||
RemoveFromCRL = iota
|
|
||||||
PrivilegeWithdrawn = iota
|
|
||||||
AACompromise = iota
|
|
||||||
)
|
|
||||||
|
|
||||||
// Request represents an OCSP request. See RFC 6960.
|
|
||||||
type Request struct {
|
|
||||||
HashAlgorithm crypto.Hash
|
|
||||||
IssuerNameHash []byte
|
|
||||||
IssuerKeyHash []byte
|
|
||||||
SerialNumber *big.Int
|
|
||||||
}
|
|
||||||
|
|
||||||
// Response represents an OCSP response containing a single SingleResponse. See
|
|
||||||
// RFC 6960.
|
|
||||||
type Response struct {
|
|
||||||
// Status is one of {Good, Revoked, Unknown}
|
|
||||||
Status int
|
|
||||||
SerialNumber *big.Int
|
|
||||||
ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time
|
|
||||||
RevocationReason int
|
|
||||||
Certificate *x509.Certificate
|
|
||||||
// TBSResponseData contains the raw bytes of the signed response. If
|
|
||||||
// Certificate is nil then this can be used to verify Signature.
|
|
||||||
TBSResponseData []byte
|
|
||||||
Signature []byte
|
|
||||||
SignatureAlgorithm x509.SignatureAlgorithm
|
|
||||||
|
|
||||||
// Extensions contains raw X.509 extensions from the singleExtensions field
|
|
||||||
// of the OCSP response. When parsing certificates, this can be used to
|
|
||||||
// extract non-critical extensions that are not parsed by this package. When
|
|
||||||
// marshaling OCSP responses, the Extensions field is ignored, see
|
|
||||||
// ExtraExtensions.
|
|
||||||
Extensions []pkix.Extension
|
|
||||||
|
|
||||||
// ExtraExtensions contains extensions to be copied, raw, into any marshaled
|
|
||||||
// OCSP response (in the singleExtensions field). Values override any
|
|
||||||
// extensions that would otherwise be produced based on the other fields. The
|
|
||||||
// ExtraExtensions field is not populated when parsing certificates, see
|
|
||||||
// Extensions.
|
|
||||||
ExtraExtensions []pkix.Extension
|
|
||||||
}
|
|
||||||
|
|
||||||
// These are pre-serialized error responses for the various non-success codes
|
|
||||||
// defined by OCSP. The Unauthorized code in particular can be used by an OCSP
|
|
||||||
// responder that supports only pre-signed responses as a response to requests
|
|
||||||
// for certificates with unknown status. See RFC 5019.
|
|
||||||
var (
|
|
||||||
MalformedRequestErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x01}
|
|
||||||
InternalErrorErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x02}
|
|
||||||
TryLaterErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x03}
|
|
||||||
SigRequredErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x05}
|
|
||||||
UnauthorizedErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x06}
|
|
||||||
)
|
|
||||||
|
|
||||||
// CheckSignatureFrom checks that the signature in resp is a valid signature
|
|
||||||
// from issuer. This should only be used if resp.Certificate is nil. Otherwise,
|
|
||||||
// the OCSP response contained an intermediate certificate that created the
|
|
||||||
// signature. That signature is checked by ParseResponse and only
|
|
||||||
// resp.Certificate remains to be validated.
|
|
||||||
func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error {
|
|
||||||
return issuer.CheckSignature(resp.SignatureAlgorithm, resp.TBSResponseData, resp.Signature)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseError results from an invalid OCSP response.
|
|
||||||
type ParseError string
|
|
||||||
|
|
||||||
func (p ParseError) Error() string {
|
|
||||||
return string(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseRequest parses an OCSP request in DER form. It only supports
|
|
||||||
// requests for a single certificate. Signed requests are not supported.
|
|
||||||
// If a request includes a signature, it will result in a ParseError.
|
|
||||||
func ParseRequest(bytes []byte) (*Request, error) {
|
|
||||||
var req ocspRequest
|
|
||||||
rest, err := asn1.Unmarshal(bytes, &req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(rest) > 0 {
|
|
||||||
return nil, ParseError("trailing data in OCSP request")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(req.TBSRequest.RequestList) == 0 {
|
|
||||||
return nil, ParseError("OCSP request contains no request body")
|
|
||||||
}
|
|
||||||
innerRequest := req.TBSRequest.RequestList[0]
|
|
||||||
|
|
||||||
hashFunc := getHashAlgorithmFromOID(innerRequest.Cert.HashAlgorithm.Algorithm)
|
|
||||||
if hashFunc == crypto.Hash(0) {
|
|
||||||
return nil, ParseError("OCSP request uses unknown hash function")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Request{
|
|
||||||
HashAlgorithm: hashFunc,
|
|
||||||
IssuerNameHash: innerRequest.Cert.NameHash,
|
|
||||||
IssuerKeyHash: innerRequest.Cert.IssuerKeyHash,
|
|
||||||
SerialNumber: innerRequest.Cert.SerialNumber,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseResponse parses an OCSP response in DER form. It only supports
|
|
||||||
// responses for a single certificate. If the response contains a certificate
|
|
||||||
// then the signature over the response is checked. If issuer is not nil then
|
|
||||||
// it will be used to validate the signature or embedded certificate.
|
|
||||||
//
|
|
||||||
// Invalid signatures or parse failures will result in a ParseError. Error
|
|
||||||
// responses will result in a ResponseError.
|
|
||||||
func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) {
|
|
||||||
var resp responseASN1
|
|
||||||
rest, err := asn1.Unmarshal(bytes, &resp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(rest) > 0 {
|
|
||||||
return nil, ParseError("trailing data in OCSP response")
|
|
||||||
}
|
|
||||||
|
|
||||||
if status := ResponseStatus(resp.Status); status != Success {
|
|
||||||
return nil, ResponseError{status}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) {
|
|
||||||
return nil, ParseError("bad OCSP response type")
|
|
||||||
}
|
|
||||||
|
|
||||||
var basicResp basicResponse
|
|
||||||
rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(basicResp.Certificates) > 1 {
|
|
||||||
return nil, ParseError("OCSP response contains bad number of certificates")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(basicResp.TBSResponseData.Responses) != 1 {
|
|
||||||
return nil, ParseError("OCSP response contains bad number of responses")
|
|
||||||
}
|
|
||||||
|
|
||||||
ret := &Response{
|
|
||||||
TBSResponseData: basicResp.TBSResponseData.Raw,
|
|
||||||
Signature: basicResp.Signature.RightAlign(),
|
|
||||||
SignatureAlgorithm: getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm),
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(basicResp.Certificates) > 0 {
|
|
||||||
ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ret.CheckSignatureFrom(ret.Certificate); err != nil {
|
|
||||||
return nil, ParseError("bad OCSP signature")
|
|
||||||
}
|
|
||||||
|
|
||||||
if issuer != nil {
|
|
||||||
if err := issuer.CheckSignature(ret.Certificate.SignatureAlgorithm, ret.Certificate.RawTBSCertificate, ret.Certificate.Signature); err != nil {
|
|
||||||
return nil, ParseError("bad signature on embedded certificate")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if issuer != nil {
|
|
||||||
if err := ret.CheckSignatureFrom(issuer); err != nil {
|
|
||||||
return nil, ParseError("bad OCSP signature")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r := basicResp.TBSResponseData.Responses[0]
|
|
||||||
|
|
||||||
for _, ext := range r.SingleExtensions {
|
|
||||||
if ext.Critical {
|
|
||||||
return nil, ParseError("unsupported critical extension")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret.Extensions = r.SingleExtensions
|
|
||||||
|
|
||||||
ret.SerialNumber = r.CertID.SerialNumber
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case bool(r.Good):
|
|
||||||
ret.Status = Good
|
|
||||||
case bool(r.Unknown):
|
|
||||||
ret.Status = Unknown
|
|
||||||
default:
|
|
||||||
ret.Status = Revoked
|
|
||||||
ret.RevokedAt = r.Revoked.RevocationTime
|
|
||||||
ret.RevocationReason = int(r.Revoked.Reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.ProducedAt = basicResp.TBSResponseData.ProducedAt
|
|
||||||
ret.ThisUpdate = r.ThisUpdate
|
|
||||||
ret.NextUpdate = r.NextUpdate
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RequestOptions contains options for constructing OCSP requests.
|
|
||||||
type RequestOptions struct {
|
|
||||||
// Hash contains the hash function that should be used when
|
|
||||||
// constructing the OCSP request. If zero, SHA-1 will be used.
|
|
||||||
Hash crypto.Hash
|
|
||||||
}
|
|
||||||
|
|
||||||
func (opts *RequestOptions) hash() crypto.Hash {
|
|
||||||
if opts == nil || opts.Hash == 0 {
|
|
||||||
// SHA-1 is nearly universally used in OCSP.
|
|
||||||
return crypto.SHA1
|
|
||||||
}
|
|
||||||
return opts.Hash
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateRequest returns a DER-encoded, OCSP request for the status of cert. If
|
|
||||||
// opts is nil then sensible defaults are used.
|
|
||||||
func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error) {
|
|
||||||
hashFunc := opts.hash()
|
|
||||||
|
|
||||||
// OCSP seems to be the only place where these raw hash identifiers are
|
|
||||||
// used. I took the following from
|
|
||||||
// http://msdn.microsoft.com/en-us/library/ff635603.aspx
|
|
||||||
var hashOID asn1.ObjectIdentifier
|
|
||||||
hashOID, ok := hashOIDs[hashFunc]
|
|
||||||
if !ok {
|
|
||||||
return nil, x509.ErrUnsupportedAlgorithm
|
|
||||||
}
|
|
||||||
|
|
||||||
if !hashFunc.Available() {
|
|
||||||
return nil, x509.ErrUnsupportedAlgorithm
|
|
||||||
}
|
|
||||||
h := opts.hash().New()
|
|
||||||
|
|
||||||
var publicKeyInfo struct {
|
|
||||||
Algorithm pkix.AlgorithmIdentifier
|
|
||||||
PublicKey asn1.BitString
|
|
||||||
}
|
|
||||||
if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
h.Write(publicKeyInfo.PublicKey.RightAlign())
|
|
||||||
issuerKeyHash := h.Sum(nil)
|
|
||||||
|
|
||||||
h.Reset()
|
|
||||||
h.Write(issuer.RawSubject)
|
|
||||||
issuerNameHash := h.Sum(nil)
|
|
||||||
|
|
||||||
return asn1.Marshal(ocspRequest{
|
|
||||||
tbsRequest{
|
|
||||||
Version: 0,
|
|
||||||
RequestList: []request{
|
|
||||||
{
|
|
||||||
Cert: certID{
|
|
||||||
pkix.AlgorithmIdentifier{
|
|
||||||
Algorithm: hashOID,
|
|
||||||
Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */},
|
|
||||||
},
|
|
||||||
issuerNameHash,
|
|
||||||
issuerKeyHash,
|
|
||||||
cert.SerialNumber,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateResponse returns a DER-encoded OCSP response with the specified contents.
|
|
||||||
// The fields in the response are populated as follows:
|
|
||||||
//
|
|
||||||
// The responder cert is used to populate the ResponderName field, and the certificate
|
|
||||||
// itself is provided alongside the OCSP response signature.
|
|
||||||
//
|
|
||||||
// The issuer cert is used to puplate the IssuerNameHash and IssuerKeyHash fields.
|
|
||||||
// (SHA-1 is used for the hash function; this is not configurable.)
|
|
||||||
//
|
|
||||||
// The template is used to populate the SerialNumber, RevocationStatus, RevokedAt,
|
|
||||||
// RevocationReason, ThisUpdate, and NextUpdate fields.
|
|
||||||
//
|
|
||||||
// The ProducedAt date is automatically set to the current date, to the nearest minute.
|
|
||||||
func CreateResponse(issuer, responderCert *x509.Certificate, template Response, priv crypto.Signer) ([]byte, error) {
|
|
||||||
var publicKeyInfo struct {
|
|
||||||
Algorithm pkix.AlgorithmIdentifier
|
|
||||||
PublicKey asn1.BitString
|
|
||||||
}
|
|
||||||
if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
h := sha1.New()
|
|
||||||
h.Write(publicKeyInfo.PublicKey.RightAlign())
|
|
||||||
issuerKeyHash := h.Sum(nil)
|
|
||||||
|
|
||||||
h.Reset()
|
|
||||||
h.Write(issuer.RawSubject)
|
|
||||||
issuerNameHash := h.Sum(nil)
|
|
||||||
|
|
||||||
innerResponse := singleResponse{
|
|
||||||
CertID: certID{
|
|
||||||
HashAlgorithm: pkix.AlgorithmIdentifier{
|
|
||||||
Algorithm: hashOIDs[crypto.SHA1],
|
|
||||||
Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */},
|
|
||||||
},
|
|
||||||
NameHash: issuerNameHash,
|
|
||||||
IssuerKeyHash: issuerKeyHash,
|
|
||||||
SerialNumber: template.SerialNumber,
|
|
||||||
},
|
|
||||||
ThisUpdate: template.ThisUpdate.UTC(),
|
|
||||||
NextUpdate: template.NextUpdate.UTC(),
|
|
||||||
SingleExtensions: template.ExtraExtensions,
|
|
||||||
}
|
|
||||||
|
|
||||||
switch template.Status {
|
|
||||||
case Good:
|
|
||||||
innerResponse.Good = true
|
|
||||||
case Unknown:
|
|
||||||
innerResponse.Unknown = true
|
|
||||||
case Revoked:
|
|
||||||
innerResponse.Revoked = revokedInfo{
|
|
||||||
RevocationTime: template.RevokedAt.UTC(),
|
|
||||||
Reason: asn1.Enumerated(template.RevocationReason),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
responderName := asn1.RawValue{
|
|
||||||
Class: 2, // context-specific
|
|
||||||
Tag: 1, // explicit tag
|
|
||||||
IsCompound: true,
|
|
||||||
Bytes: responderCert.RawSubject,
|
|
||||||
}
|
|
||||||
tbsResponseData := responseData{
|
|
||||||
Version: 0,
|
|
||||||
RawResponderName: responderName,
|
|
||||||
ProducedAt: time.Now().Truncate(time.Minute).UTC(),
|
|
||||||
Responses: []singleResponse{innerResponse},
|
|
||||||
}
|
|
||||||
|
|
||||||
tbsResponseDataDER, err := asn1.Marshal(tbsResponseData)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
responseHash := hashFunc.New()
|
|
||||||
responseHash.Write(tbsResponseDataDER)
|
|
||||||
signature, err := priv.Sign(rand.Reader, responseHash.Sum(nil), hashFunc)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
response := basicResponse{
|
|
||||||
TBSResponseData: tbsResponseData,
|
|
||||||
SignatureAlgorithm: signatureAlgorithm,
|
|
||||||
Signature: asn1.BitString{
|
|
||||||
Bytes: signature,
|
|
||||||
BitLength: 8 * len(signature),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if template.Certificate != nil {
|
|
||||||
response.Certificates = []asn1.RawValue{
|
|
||||||
asn1.RawValue{FullBytes: template.Certificate.Raw},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
responseDER, err := asn1.Marshal(response)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return asn1.Marshal(responseASN1{
|
|
||||||
Status: asn1.Enumerated(Success),
|
|
||||||
Response: responseBytes{
|
|
||||||
ResponseType: idPKIXOCSPBasic,
|
|
||||||
Response: responseDER,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
584
vendor/golang.org/x/crypto/ocsp/ocsp_test.go
generated
vendored
584
vendor/golang.org/x/crypto/ocsp/ocsp_test.go
generated
vendored
|
@ -1,584 +0,0 @@
|
||||||
// Copyright 2013 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 ocsp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto"
|
|
||||||
"crypto/sha1"
|
|
||||||
"crypto/x509"
|
|
||||||
"crypto/x509/pkix"
|
|
||||||
"encoding/asn1"
|
|
||||||
"encoding/hex"
|
|
||||||
"math/big"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestOCSPDecode(t *testing.T) {
|
|
||||||
responseBytes, _ := hex.DecodeString(ocspResponseHex)
|
|
||||||
resp, err := ParseResponse(responseBytes, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
expected := Response{
|
|
||||||
Status: Good,
|
|
||||||
SerialNumber: big.NewInt(0x1d0fa),
|
|
||||||
RevocationReason: Unspecified,
|
|
||||||
ThisUpdate: time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC),
|
|
||||||
NextUpdate: time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC),
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(resp.ThisUpdate, expected.ThisUpdate) {
|
|
||||||
t.Errorf("resp.ThisUpdate: got %d, want %d", resp.ThisUpdate, expected.ThisUpdate)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(resp.NextUpdate, expected.NextUpdate) {
|
|
||||||
t.Errorf("resp.NextUpdate: got %d, want %d", resp.NextUpdate, expected.NextUpdate)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.Status != expected.Status {
|
|
||||||
t.Errorf("resp.Status: got %d, want %d", resp.Status, expected.Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.SerialNumber.Cmp(expected.SerialNumber) != 0 {
|
|
||||||
t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, expected.SerialNumber)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.RevocationReason != expected.RevocationReason {
|
|
||||||
t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, expected.RevocationReason)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOCSPDecodeWithoutCert(t *testing.T) {
|
|
||||||
responseBytes, _ := hex.DecodeString(ocspResponseWithoutCertHex)
|
|
||||||
_, err := ParseResponse(responseBytes, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOCSPDecodeWithExtensions(t *testing.T) {
|
|
||||||
responseBytes, _ := hex.DecodeString(ocspResponseWithCriticalExtensionHex)
|
|
||||||
_, err := ParseResponse(responseBytes, nil)
|
|
||||||
if err == nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
responseBytes, _ = hex.DecodeString(ocspResponseWithExtensionHex)
|
|
||||||
response, err := ParseResponse(responseBytes, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(response.Extensions) != 1 {
|
|
||||||
t.Errorf("len(response.Extensions): got %v, want %v", len(response.Extensions), 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
extensionBytes := response.Extensions[0].Value
|
|
||||||
expectedBytes, _ := hex.DecodeString(ocspExtensionValueHex)
|
|
||||||
if !bytes.Equal(extensionBytes, expectedBytes) {
|
|
||||||
t.Errorf("response.Extensions[0]: got %x, want %x", extensionBytes, expectedBytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOCSPSignature(t *testing.T) {
|
|
||||||
issuerCert, _ := hex.DecodeString(startComHex)
|
|
||||||
issuer, err := x509.ParseCertificate(issuerCert)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
response, _ := hex.DecodeString(ocspResponseHex)
|
|
||||||
if _, err := ParseResponse(response, issuer); err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOCSPRequest(t *testing.T) {
|
|
||||||
leafCert, _ := hex.DecodeString(leafCertHex)
|
|
||||||
cert, err := x509.ParseCertificate(leafCert)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
issuerCert, _ := hex.DecodeString(issuerCertHex)
|
|
||||||
issuer, err := x509.ParseCertificate(issuerCert)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
request, err := CreateRequest(cert, issuer, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedBytes, _ := hex.DecodeString(ocspRequestHex)
|
|
||||||
if !bytes.Equal(request, expectedBytes) {
|
|
||||||
t.Errorf("request: got %x, wanted %x", request, expectedBytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
decodedRequest, err := ParseRequest(expectedBytes)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if decodedRequest.HashAlgorithm != crypto.SHA1 {
|
|
||||||
t.Errorf("request.HashAlgorithm: got %v, want %v", decodedRequest.HashAlgorithm, crypto.SHA1)
|
|
||||||
}
|
|
||||||
|
|
||||||
var publicKeyInfo struct {
|
|
||||||
Algorithm pkix.AlgorithmIdentifier
|
|
||||||
PublicKey asn1.BitString
|
|
||||||
}
|
|
||||||
_, err = asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
h := sha1.New()
|
|
||||||
h.Write(publicKeyInfo.PublicKey.RightAlign())
|
|
||||||
issuerKeyHash := h.Sum(nil)
|
|
||||||
|
|
||||||
h.Reset()
|
|
||||||
h.Write(issuer.RawSubject)
|
|
||||||
issuerNameHash := h.Sum(nil)
|
|
||||||
|
|
||||||
if got := decodedRequest.IssuerKeyHash; !bytes.Equal(got, issuerKeyHash) {
|
|
||||||
t.Errorf("request.IssuerKeyHash: got %x, want %x", got, issuerKeyHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
if got := decodedRequest.IssuerNameHash; !bytes.Equal(got, issuerNameHash) {
|
|
||||||
t.Errorf("request.IssuerKeyHash: got %x, want %x", got, issuerNameHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
if got := decodedRequest.SerialNumber; got.Cmp(cert.SerialNumber) != 0 {
|
|
||||||
t.Errorf("request.SerialNumber: got %x, want %x", got, cert.SerialNumber)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOCSPResponse(t *testing.T) {
|
|
||||||
leafCert, _ := hex.DecodeString(leafCertHex)
|
|
||||||
leaf, err := x509.ParseCertificate(leafCert)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
issuerCert, _ := hex.DecodeString(issuerCertHex)
|
|
||||||
issuer, err := x509.ParseCertificate(issuerCert)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
responderCert, _ := hex.DecodeString(responderCertHex)
|
|
||||||
responder, err := x509.ParseCertificate(responderCert)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
responderPrivateKeyDER, _ := hex.DecodeString(responderPrivateKeyHex)
|
|
||||||
responderPrivateKey, err := x509.ParsePKCS1PrivateKey(responderPrivateKeyDER)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
extensionBytes, _ := hex.DecodeString(ocspExtensionValueHex)
|
|
||||||
extensions := []pkix.Extension{
|
|
||||||
pkix.Extension{
|
|
||||||
Id: ocspExtensionOID,
|
|
||||||
Critical: false,
|
|
||||||
Value: extensionBytes,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
producedAt := time.Now().Truncate(time.Minute)
|
|
||||||
thisUpdate := time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC)
|
|
||||||
nextUpdate := time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC)
|
|
||||||
template := Response{
|
|
||||||
Status: Revoked,
|
|
||||||
SerialNumber: leaf.SerialNumber,
|
|
||||||
ThisUpdate: thisUpdate,
|
|
||||||
NextUpdate: nextUpdate,
|
|
||||||
RevokedAt: thisUpdate,
|
|
||||||
RevocationReason: KeyCompromise,
|
|
||||||
Certificate: responder,
|
|
||||||
ExtraExtensions: extensions,
|
|
||||||
}
|
|
||||||
|
|
||||||
responseBytes, err := CreateResponse(issuer, responder, template, responderPrivateKey)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := ParseResponse(responseBytes, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(resp.ThisUpdate, template.ThisUpdate) {
|
|
||||||
t.Errorf("resp.ThisUpdate: got %d, want %d", resp.ThisUpdate, template.ThisUpdate)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(resp.NextUpdate, template.NextUpdate) {
|
|
||||||
t.Errorf("resp.NextUpdate: got %d, want %d", resp.NextUpdate, template.NextUpdate)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(resp.RevokedAt, template.RevokedAt) {
|
|
||||||
t.Errorf("resp.RevokedAt: got %d, want %d", resp.RevokedAt, template.RevokedAt)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(resp.Extensions, template.ExtraExtensions) {
|
|
||||||
t.Errorf("resp.Extensions: got %v, want %v", resp.Extensions, template.ExtraExtensions)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !resp.ProducedAt.Equal(producedAt) {
|
|
||||||
t.Errorf("resp.ProducedAt: got %d, want %d", resp.ProducedAt, producedAt)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.Status != template.Status {
|
|
||||||
t.Errorf("resp.Status: got %d, want %d", resp.Status, template.Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.SerialNumber.Cmp(template.SerialNumber) != 0 {
|
|
||||||
t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, template.SerialNumber)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.RevocationReason != template.RevocationReason {
|
|
||||||
t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, template.RevocationReason)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestErrorResponse(t *testing.T) {
|
|
||||||
responseBytes, _ := hex.DecodeString(errorResponseHex)
|
|
||||||
_, err := ParseResponse(responseBytes, nil)
|
|
||||||
|
|
||||||
respErr, ok := err.(ResponseError)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("expected ResponseError from ParseResponse but got %#v", err)
|
|
||||||
}
|
|
||||||
if respErr.Status != Malformed {
|
|
||||||
t.Fatalf("expected Malformed status from ParseResponse but got %d", respErr.Status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This OCSP response was taken from Thawte's public OCSP responder.
|
|
||||||
// To recreate:
|
|
||||||
// $ openssl s_client -tls1 -showcerts -servername www.google.com -connect www.google.com:443
|
|
||||||
// Copy and paste the first certificate into /tmp/cert.crt and the second into
|
|
||||||
// /tmp/intermediate.crt
|
|
||||||
// $ openssl ocsp -issuer /tmp/intermediate.crt -cert /tmp/cert.crt -url http://ocsp.thawte.com -resp_text -respout /tmp/ocsp.der
|
|
||||||
// Then hex encode the result:
|
|
||||||
// $ python -c 'print file("/tmp/ocsp.der", "r").read().encode("hex")'
|
|
||||||
|
|
||||||
const ocspResponseHex = "308206bc0a0100a08206b5308206b106092b0601050507300101048206a23082069e3081" +
|
|
||||||
"c9a14e304c310b300906035504061302494c31163014060355040a130d5374617274436f" +
|
|
||||||
"6d204c74642e312530230603550403131c5374617274436f6d20436c6173732031204f43" +
|
|
||||||
"5350205369676e6572180f32303130303730373137333531375a30663064303c30090605" +
|
|
||||||
"2b0e03021a050004146568874f40750f016a3475625e1f5c93e5a26d580414eb4234d098" +
|
|
||||||
"b0ab9ff41b6b08f7cc642eef0e2c45020301d0fa8000180f323031303037303731353031" +
|
|
||||||
"30355aa011180f32303130303730373138333531375a300d06092a864886f70d01010505" +
|
|
||||||
"000382010100ab557ff070d1d7cebbb5f0ec91a15c3fed22eb2e1b8244f1b84545f013a4" +
|
|
||||||
"fb46214c5e3fbfbebb8a56acc2b9db19f68fd3c3201046b3824d5ba689f99864328710cb" +
|
|
||||||
"467195eb37d84f539e49f859316b32964dc3e47e36814ce94d6c56dd02733b1d0802f7ff" +
|
|
||||||
"4eebdbbd2927dcf580f16cbc290f91e81b53cb365e7223f1d6e20a88ea064104875e0145" +
|
|
||||||
"672b20fc14829d51ca122f5f5d77d3ad6c83889c55c7dc43680ba2fe3cef8b05dbcabdc0" +
|
|
||||||
"d3e09aaf9725597f8c858c2fa38c0d6aed2e6318194420dd1a1137445d13e1c97ab47896" +
|
|
||||||
"17a4e08925f46f867b72e3a4dc1f08cb870b2b0717f7207faa0ac512e628a029aba7457a" +
|
|
||||||
"e63dcf3281e2162d9349a08204ba308204b6308204b23082039aa003020102020101300d" +
|
|
||||||
"06092a864886f70d010105050030818c310b300906035504061302494c31163014060355" +
|
|
||||||
"040a130d5374617274436f6d204c74642e312b3029060355040b13225365637572652044" +
|
|
||||||
"69676974616c204365727469666963617465205369676e696e6731383036060355040313" +
|
|
||||||
"2f5374617274436f6d20436c6173732031205072696d61727920496e7465726d65646961" +
|
|
||||||
"746520536572766572204341301e170d3037313032353030323330365a170d3132313032" +
|
|
||||||
"333030323330365a304c310b300906035504061302494c31163014060355040a130d5374" +
|
|
||||||
"617274436f6d204c74642e312530230603550403131c5374617274436f6d20436c617373" +
|
|
||||||
"2031204f435350205369676e657230820122300d06092a864886f70d0101010500038201" +
|
|
||||||
"0f003082010a0282010100b9561b4c45318717178084e96e178df2255e18ed8d8ecc7c2b" +
|
|
||||||
"7b51a6c1c2e6bf0aa3603066f132fe10ae97b50e99fa24b83fc53dd2777496387d14e1c3" +
|
|
||||||
"a9b6a4933e2ac12413d085570a95b8147414a0bc007c7bcf222446ef7f1a156d7ea1c577" +
|
|
||||||
"fc5f0facdfd42eb0f5974990cb2f5cefebceef4d1bdc7ae5c1075c5a99a93171f2b0845b" +
|
|
||||||
"4ff0864e973fcfe32f9d7511ff87a3e943410c90a4493a306b6944359340a9ca96f02b66" +
|
|
||||||
"ce67f028df2980a6aaee8d5d5d452b8b0eb93f923cc1e23fcccbdbe7ffcb114d08fa7a6a" +
|
|
||||||
"3c404f825d1a0e715935cf623a8c7b59670014ed0622f6089a9447a7a19010f7fe58f841" +
|
|
||||||
"29a2765ea367824d1c3bb2fda308530203010001a382015c30820158300c0603551d1301" +
|
|
||||||
"01ff04023000300b0603551d0f0404030203a8301e0603551d250417301506082b060105" +
|
|
||||||
"0507030906092b0601050507300105301d0603551d0e0416041445e0a36695414c5dd449" +
|
|
||||||
"bc00e33cdcdbd2343e173081a80603551d230481a030819d8014eb4234d098b0ab9ff41b" +
|
|
||||||
"6b08f7cc642eef0e2c45a18181a47f307d310b300906035504061302494c311630140603" +
|
|
||||||
"55040a130d5374617274436f6d204c74642e312b3029060355040b132253656375726520" +
|
|
||||||
"4469676974616c204365727469666963617465205369676e696e67312930270603550403" +
|
|
||||||
"13205374617274436f6d2043657274696669636174696f6e20417574686f726974798201" +
|
|
||||||
"0a30230603551d12041c301a8618687474703a2f2f7777772e737461727473736c2e636f" +
|
|
||||||
"6d2f302c06096086480186f842010d041f161d5374617274436f6d205265766f63617469" +
|
|
||||||
"6f6e20417574686f72697479300d06092a864886f70d01010505000382010100182d2215" +
|
|
||||||
"8f0fc0291324fa8574c49bb8ff2835085adcbf7b7fc4191c397ab6951328253fffe1e5ec" +
|
|
||||||
"2a7da0d50fca1a404e6968481366939e666c0a6209073eca57973e2fefa9ed1718e8176f" +
|
|
||||||
"1d85527ff522c08db702e3b2b180f1cbff05d98128252cf0f450f7dd2772f4188047f19d" +
|
|
||||||
"c85317366f94bc52d60f453a550af58e308aaab00ced33040b62bf37f5b1ab2a4f7f0f80" +
|
|
||||||
"f763bf4d707bc8841d7ad9385ee2a4244469260b6f2bf085977af9074796048ecc2f9d48" +
|
|
||||||
"a1d24ce16e41a9941568fec5b42771e118f16c106a54ccc339a4b02166445a167902e75e" +
|
|
||||||
"6d8620b0825dcd18a069b90fd851d10fa8effd409deec02860d26d8d833f304b10669b42"
|
|
||||||
|
|
||||||
const startComHex = "308206343082041ca003020102020118300d06092a864886f70d0101050500307d310b30" +
|
|
||||||
"0906035504061302494c31163014060355040a130d5374617274436f6d204c74642e312b" +
|
|
||||||
"3029060355040b1322536563757265204469676974616c20436572746966696361746520" +
|
|
||||||
"5369676e696e6731293027060355040313205374617274436f6d20436572746966696361" +
|
|
||||||
"74696f6e20417574686f72697479301e170d3037313032343230353431375a170d313731" +
|
|
||||||
"3032343230353431375a30818c310b300906035504061302494c31163014060355040a13" +
|
|
||||||
"0d5374617274436f6d204c74642e312b3029060355040b13225365637572652044696769" +
|
|
||||||
"74616c204365727469666963617465205369676e696e67313830360603550403132f5374" +
|
|
||||||
"617274436f6d20436c6173732031205072696d61727920496e7465726d65646961746520" +
|
|
||||||
"53657276657220434130820122300d06092a864886f70d01010105000382010f00308201" +
|
|
||||||
"0a0282010100b689c6acef09527807ac9263d0f44418188480561f91aee187fa3250b4d3" +
|
|
||||||
"4706f0e6075f700e10f71dc0ce103634855a0f92ac83c6ac58523fba38e8fce7a724e240" +
|
|
||||||
"a60876c0926e9e2a6d4d3f6e61200adb59ded27d63b33e46fefa215118d7cd30a6ed076e" +
|
|
||||||
"3b7087b4f9faebee823c056f92f7a4dc0a301e9373fe07cad75f809d225852ae06da8b87" +
|
|
||||||
"2369b0e42ad8ea83d2bdf371db705a280faf5a387045123f304dcd3baf17e50fcba0a95d" +
|
|
||||||
"48aab16150cb34cd3c5cc30be810c08c9bf0030362feb26c3e720eee1c432ac9480e5739" +
|
|
||||||
"c43121c810c12c87fe5495521f523c31129b7fe7c0a0a559d5e28f3ef0d5a8e1d77031a9" +
|
|
||||||
"c4b3cfaf6d532f06f4a70203010001a38201ad308201a9300f0603551d130101ff040530" +
|
|
||||||
"030101ff300e0603551d0f0101ff040403020106301d0603551d0e04160414eb4234d098" +
|
|
||||||
"b0ab9ff41b6b08f7cc642eef0e2c45301f0603551d230418301680144e0bef1aa4405ba5" +
|
|
||||||
"17698730ca346843d041aef2306606082b06010505070101045a3058302706082b060105" +
|
|
||||||
"05073001861b687474703a2f2f6f6373702e737461727473736c2e636f6d2f6361302d06" +
|
|
||||||
"082b060105050730028621687474703a2f2f7777772e737461727473736c2e636f6d2f73" +
|
|
||||||
"667363612e637274305b0603551d1f045430523027a025a0238621687474703a2f2f7777" +
|
|
||||||
"772e737461727473736c2e636f6d2f73667363612e63726c3027a025a023862168747470" +
|
|
||||||
"3a2f2f63726c2e737461727473736c2e636f6d2f73667363612e63726c3081800603551d" +
|
|
||||||
"20047930773075060b2b0601040181b5370102013066302e06082b060105050702011622" +
|
|
||||||
"687474703a2f2f7777772e737461727473736c2e636f6d2f706f6c6963792e7064663034" +
|
|
||||||
"06082b060105050702011628687474703a2f2f7777772e737461727473736c2e636f6d2f" +
|
|
||||||
"696e7465726d6564696174652e706466300d06092a864886f70d01010505000382020100" +
|
|
||||||
"2109493ea5886ee00b8b48da314d8ff75657a2e1d36257e9b556f38545753be5501f048b" +
|
|
||||||
"e6a05a3ee700ae85d0fbff200364cbad02e1c69172f8a34dd6dee8cc3fa18aa2e37c37a7" +
|
|
||||||
"c64f8f35d6f4d66e067bdd21d9cf56ffcb302249fe8904f385e5aaf1e71fe875904dddf9" +
|
|
||||||
"46f74234f745580c110d84b0c6da5d3ef9019ee7e1da5595be741c7bfc4d144fac7e5547" +
|
|
||||||
"7d7bf4a50d491e95e8f712c1ccff76a62547d0f37535be97b75816ebaa5c786fec5330af" +
|
|
||||||
"ea044dcca902e3f0b60412f630b1113d904e5664d7dc3c435f7339ef4baf87ebf6fe6888" +
|
|
||||||
"4472ead207c669b0c1a18bef1749d761b145485f3b2021e95bb2ccf4d7e931f50b15613b" +
|
|
||||||
"7a94e3ebd9bc7f94ae6ae3626296a8647cb887f399327e92a252bebbf865cfc9f230fc8b" +
|
|
||||||
"c1c2a696d75f89e15c3480f58f47072fb491bfb1a27e5f4b5ad05b9f248605515a690365" +
|
|
||||||
"434971c5e06f94346bf61bd8a9b04c7e53eb8f48dfca33b548fa364a1a53a6330cd089cd" +
|
|
||||||
"4915cd89313c90c072d7654b52358a461144b93d8e2865a63e799e5c084429adb035112e" +
|
|
||||||
"214eb8d2e7103e5d8483b3c3c2e4d2c6fd094b7409ddf1b3d3193e800da20b19f038e7c5" +
|
|
||||||
"c2afe223db61e29d5c6e2089492e236ab262c145b49faf8ba7f1223bf87de290d07a19fb" +
|
|
||||||
"4a4ce3d27d5f4a8303ed27d6239e6b8db459a2d9ef6c8229dd75193c3f4c108defbb7527" +
|
|
||||||
"d2ae83a7a8ce5ba7"
|
|
||||||
|
|
||||||
const ocspResponseWithoutCertHex = "308201d40a0100a08201cd308201c906092b0601050507300101048201ba3082" +
|
|
||||||
"01b630819fa2160414884451ff502a695e2d88f421bad90cf2cecbea7c180f3230313330" +
|
|
||||||
"3631383037323434335a30743072304a300906052b0e03021a0500041448b60d38238df8" +
|
|
||||||
"456e4ee5843ea394111802979f0414884451ff502a695e2d88f421bad90cf2cecbea7c02" +
|
|
||||||
"1100f78b13b946fc9635d8ab49de9d2148218000180f3230313330363138303732343433" +
|
|
||||||
"5aa011180f32303133303632323037323434335a300d06092a864886f70d010105050003" +
|
|
||||||
"82010100103e18b3d297a5e7a6c07a4fc52ac46a15c0eba96f3be17f0ffe84de5b8c8e05" +
|
|
||||||
"5a8f577586a849dc4abd6440eb6fedde4622451e2823c1cbf3558b4e8184959c9fe96eff" +
|
|
||||||
"8bc5f95866c58c6d087519faabfdae37e11d9874f1bc0db292208f645dd848185e4dd38b" +
|
|
||||||
"6a8547dfa7b74d514a8470015719064d35476b95bebb03d4d2845c5ca15202d2784878f2" +
|
|
||||||
"0f904c24f09736f044609e9c271381713400e563023d212db422236440c6f377bbf24b2b" +
|
|
||||||
"9e7dec8698e36a8df68b7592ad3489fb2937afb90eb85d2aa96b81c94c25057dbd4759d9" +
|
|
||||||
"20a1a65c7f0b6427a224b3c98edd96b9b61f706099951188b0289555ad30a216fb774651" +
|
|
||||||
"5a35fca2e054dfa8"
|
|
||||||
|
|
||||||
// PKIX nonce extension
|
|
||||||
var ocspExtensionOID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1, 2}
|
|
||||||
var ocspExtensionValueHex = "0403000000"
|
|
||||||
|
|
||||||
const ocspResponseWithCriticalExtensionHex = "308204fe0a0100a08204f7308204f306092b0601050507300101048204e4308204e03081" +
|
|
||||||
"dba003020100a11b3019311730150603550403130e4f43535020526573706f6e64657218" +
|
|
||||||
"0f32303136303130343137303130305a3081a53081a23049300906052b0e03021a050004" +
|
|
||||||
"14c0fe0278fc99188891b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b21317" +
|
|
||||||
"7e6f8d157cd4f60210017f77deb3bcbb235d44ccc7dba62e72a116180f32303130303730" +
|
|
||||||
"373135303130355aa0030a0101180f32303130303730373135303130355aa011180f3230" +
|
|
||||||
"3130303730373138333531375aa1193017301506092b06010505073001020101ff040504" +
|
|
||||||
"03000000300d06092a864886f70d01010b0500038201010031c730ca60a7a0d92d8e4010" +
|
|
||||||
"911b469de95b4d27e89de6537552436237967694f76f701cf6b45c932bd308bca4a8d092" +
|
|
||||||
"5c604ba94796903091d9e6c000178e72c1f0a24a277dd262835af5d17d3f9d7869606c9f" +
|
|
||||||
"e7c8e708a41645699895beee38bfa63bb46296683761c5d1d65439b8ab868dc3017c9eeb" +
|
|
||||||
"b70b82dbf3a31c55b457d48bb9e82b335ed49f445042eaf606b06a3e0639824924c89c63" +
|
|
||||||
"eccddfe85e6694314138b2536f5e15e07085d0f6e26d4b2f8244bab0d70de07283ac6384" +
|
|
||||||
"a0501fc3dea7cf0adfd4c7f34871080900e252ddc403e3f0265f2a704af905d3727504ed" +
|
|
||||||
"28f3214a219d898a022463c78439799ca81c8cbafdbcec34ea937cd6a08202ea308202e6" +
|
|
||||||
"308202e2308201caa003020102020101300d06092a864886f70d01010b05003019311730" +
|
|
||||||
"150603550403130e4f43535020526573706f6e646572301e170d31353031333031353530" +
|
|
||||||
"33335a170d3136303133303135353033335a3019311730150603550403130e4f43535020" +
|
|
||||||
"526573706f6e64657230820122300d06092a864886f70d01010105000382010f00308201" +
|
|
||||||
"0a0282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616e" +
|
|
||||||
"c5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbc" +
|
|
||||||
"bec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b72" +
|
|
||||||
"3350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b898" +
|
|
||||||
"9ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d" +
|
|
||||||
"285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e6" +
|
|
||||||
"55b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31" +
|
|
||||||
"a77dcf920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030" +
|
|
||||||
"130603551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d" +
|
|
||||||
"06092a864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab8612" +
|
|
||||||
"31c15fd5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d2288" +
|
|
||||||
"9064f4aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f3267" +
|
|
||||||
"09dce52c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156" +
|
|
||||||
"d67156e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff5" +
|
|
||||||
"9e2005d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf9" +
|
|
||||||
"66705de17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d9" +
|
|
||||||
"3a25439a94299a65a709756c7a3e568be049d5c38839"
|
|
||||||
|
|
||||||
const ocspResponseWithExtensionHex = "308204fb0a0100a08204f4308204f006092b0601050507300101048204e1308204dd3081" +
|
|
||||||
"d8a003020100a11b3019311730150603550403130e4f43535020526573706f6e64657218" +
|
|
||||||
"0f32303136303130343136353930305a3081a230819f3049300906052b0e03021a050004" +
|
|
||||||
"14c0fe0278fc99188891b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b21317" +
|
|
||||||
"7e6f8d157cd4f60210017f77deb3bcbb235d44ccc7dba62e72a116180f32303130303730" +
|
|
||||||
"373135303130355aa0030a0101180f32303130303730373135303130355aa011180f3230" +
|
|
||||||
"3130303730373138333531375aa1163014301206092b0601050507300102040504030000" +
|
|
||||||
"00300d06092a864886f70d01010b05000382010100c09a33e0b2324c852421bb83f85ac9" +
|
|
||||||
"9113f5426012bd2d2279a8166e9241d18a33c870894250622ffc7ed0c4601b16d624f90b" +
|
|
||||||
"779265442cdb6868cf40ab304ab4b66e7315ed02cf663b1601d1d4751772b31bc299db23" +
|
|
||||||
"9aebac78ed6797c06ed815a7a8d18d63cfbb609cafb47ec2e89e37db255216eb09307848" +
|
|
||||||
"d01be0a3e943653c78212b96ff524b74c9ec456b17cdfb950cc97645c577b2e09ff41dde" +
|
|
||||||
"b03afb3adaa381cc0f7c1d95663ef22a0f72f2c45613ae8e2b2d1efc96e8463c7d1d8a1d" +
|
|
||||||
"7e3b35df8fe73a301fc3f804b942b2b3afa337ff105fc1462b7b1c1d75eb4566c8665e59" +
|
|
||||||
"f80393b0adbf8004ff6c3327ed34f007cb4a3348a7d55e06e3a08202ea308202e6308202" +
|
|
||||||
"e2308201caa003020102020101300d06092a864886f70d01010b05003019311730150603" +
|
|
||||||
"550403130e4f43535020526573706f6e646572301e170d3135303133303135353033335a" +
|
|
||||||
"170d3136303133303135353033335a3019311730150603550403130e4f43535020526573" +
|
|
||||||
"706f6e64657230820122300d06092a864886f70d01010105000382010f003082010a0282" +
|
|
||||||
"010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616ec5265b" +
|
|
||||||
"56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbcbec75a" +
|
|
||||||
"70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b723350f0" +
|
|
||||||
"a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b8989ad0f6" +
|
|
||||||
"3aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d285b6a" +
|
|
||||||
"04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e655b104" +
|
|
||||||
"9a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31a77dcf" +
|
|
||||||
"920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030130603" +
|
|
||||||
"551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d06092a" +
|
|
||||||
"864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab861231c15f" +
|
|
||||||
"d5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d22889064f4" +
|
|
||||||
"aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f326709dce5" +
|
|
||||||
"2c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156d67156" +
|
|
||||||
"e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff59e2005" +
|
|
||||||
"d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf966705d" +
|
|
||||||
"e17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d93a2543" +
|
|
||||||
"9a94299a65a709756c7a3e568be049d5c38839"
|
|
||||||
|
|
||||||
const ocspRequestHex = "3051304f304d304b3049300906052b0e03021a05000414c0fe0278fc99188891b3f212e9" +
|
|
||||||
"c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b213177e6f8d157cd4f60210017f77deb3" +
|
|
||||||
"bcbb235d44ccc7dba62e72"
|
|
||||||
|
|
||||||
const leafCertHex = "308203c830820331a0030201020210017f77deb3bcbb235d44ccc7dba62e72300d06092a" +
|
|
||||||
"864886f70d01010505003081ba311f301d060355040a1316566572695369676e20547275" +
|
|
||||||
"7374204e6574776f726b31173015060355040b130e566572695369676e2c20496e632e31" +
|
|
||||||
"333031060355040b132a566572695369676e20496e7465726e6174696f6e616c20536572" +
|
|
||||||
"766572204341202d20436c617373203331493047060355040b13407777772e7665726973" +
|
|
||||||
"69676e2e636f6d2f43505320496e636f72702e6279205265662e204c494142494c495459" +
|
|
||||||
"204c54442e286329393720566572695369676e301e170d3132303632313030303030305a" +
|
|
||||||
"170d3133313233313233353935395a3068310b3009060355040613025553311330110603" +
|
|
||||||
"550408130a43616c69666f726e6961311230100603550407130950616c6f20416c746f31" +
|
|
||||||
"173015060355040a130e46616365626f6f6b2c20496e632e311730150603550403140e2a" +
|
|
||||||
"2e66616365626f6f6b2e636f6d30819f300d06092a864886f70d010101050003818d0030" +
|
|
||||||
"818902818100ae94b171e2deccc1693e051063240102e0689ae83c39b6b3e74b97d48d7b" +
|
|
||||||
"23689100b0b496ee62f0e6d356bcf4aa0f50643402f5d1766aa972835a7564723f39bbef" +
|
|
||||||
"5290ded9bcdbf9d3d55dfad23aa03dc604c54d29cf1d4b3bdbd1a809cfae47b44c7eae17" +
|
|
||||||
"c5109bee24a9cf4a8d911bb0fd0415ae4c3f430aa12a557e2ae10203010001a382011e30" +
|
|
||||||
"82011a30090603551d130402300030440603551d20043d303b3039060b6086480186f845" +
|
|
||||||
"01071703302a302806082b06010505070201161c68747470733a2f2f7777772e76657269" +
|
|
||||||
"7369676e2e636f6d2f727061303c0603551d1f043530333031a02fa02d862b687474703a" +
|
|
||||||
"2f2f535652496e746c2d63726c2e766572697369676e2e636f6d2f535652496e746c2e63" +
|
|
||||||
"726c301d0603551d250416301406082b0601050507030106082b06010505070302300b06" +
|
|
||||||
"03551d0f0404030205a0303406082b0601050507010104283026302406082b0601050507" +
|
|
||||||
"30018618687474703a2f2f6f6373702e766572697369676e2e636f6d30270603551d1104" +
|
|
||||||
"20301e820e2a2e66616365626f6f6b2e636f6d820c66616365626f6f6b2e636f6d300d06" +
|
|
||||||
"092a864886f70d0101050500038181005b6c2b75f8ed30aa51aad36aba595e555141951f" +
|
|
||||||
"81a53b447910ac1f76ff78fc2781616b58f3122afc1c87010425e9ed43df1a7ba6498060" +
|
|
||||||
"67e2688af03db58c7df4ee03309a6afc247ccb134dc33e54c6bc1d5133a532a73273b1d7" +
|
|
||||||
"9cadc08e7e1a83116d34523340b0305427a21742827c98916698ee7eaf8c3bdd71700817"
|
|
||||||
|
|
||||||
const issuerCertHex = "30820383308202eca003020102021046fcebbab4d02f0f926098233f93078f300d06092a" +
|
|
||||||
"864886f70d0101050500305f310b300906035504061302555331173015060355040a130e" +
|
|
||||||
"566572695369676e2c20496e632e31373035060355040b132e436c617373203320507562" +
|
|
||||||
"6c6963205072696d6172792043657274696669636174696f6e20417574686f7269747930" +
|
|
||||||
"1e170d3937303431373030303030305a170d3136313032343233353935395a3081ba311f" +
|
|
||||||
"301d060355040a1316566572695369676e205472757374204e6574776f726b3117301506" +
|
|
||||||
"0355040b130e566572695369676e2c20496e632e31333031060355040b132a5665726953" +
|
|
||||||
"69676e20496e7465726e6174696f6e616c20536572766572204341202d20436c61737320" +
|
|
||||||
"3331493047060355040b13407777772e766572697369676e2e636f6d2f43505320496e63" +
|
|
||||||
"6f72702e6279205265662e204c494142494c495459204c54442e28632939372056657269" +
|
|
||||||
"5369676e30819f300d06092a864886f70d010101050003818d0030818902818100d88280" +
|
|
||||||
"e8d619027d1f85183925a2652be1bfd405d3bce6363baaf04c6c5bb6e7aa3c734555b2f1" +
|
|
||||||
"bdea9742ed9a340a15d4a95cf54025ddd907c132b2756cc4cabba3fe56277143aa63f530" +
|
|
||||||
"3e9328e5faf1093bf3b74d4e39f75c495ab8c11dd3b28afe70309542cbfe2b518b5a3c3a" +
|
|
||||||
"f9224f90b202a7539c4f34e7ab04b27b6f0203010001a381e33081e0300f0603551d1304" +
|
|
||||||
"0830060101ff02010030440603551d20043d303b3039060b6086480186f8450107010130" +
|
|
||||||
"2a302806082b06010505070201161c68747470733a2f2f7777772e766572697369676e2e" +
|
|
||||||
"636f6d2f43505330340603551d25042d302b06082b0601050507030106082b0601050507" +
|
|
||||||
"030206096086480186f8420401060a6086480186f845010801300b0603551d0f04040302" +
|
|
||||||
"0106301106096086480186f842010104040302010630310603551d1f042a30283026a024" +
|
|
||||||
"a0228620687474703a2f2f63726c2e766572697369676e2e636f6d2f706361332e63726c" +
|
|
||||||
"300d06092a864886f70d010105050003818100408e4997968a73dd8e4def3e61b7caa062" +
|
|
||||||
"adf40e0abb753de26ed82cc7bff4b98c369bcaa2d09c724639f6a682036511c4bcbf2da6" +
|
|
||||||
"f5d93b0ab598fab378b91ef22b4c62d5fdb27a1ddf33fd73f9a5d82d8c2aead1fcb028b6" +
|
|
||||||
"e94948134b838a1b487b24f738de6f4154b8ab576b06dfc7a2d4a9f6f136628088f28b75" +
|
|
||||||
"d68071"
|
|
||||||
|
|
||||||
// Key and certificate for the OCSP responder were not taken from the Thawte
|
|
||||||
// responder, since CreateResponse requires that we have the private key.
|
|
||||||
// Instead, they were generated randomly.
|
|
||||||
const responderPrivateKeyHex = "308204a40201000282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef" +
|
|
||||||
"1099f0f6616ec5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df" +
|
|
||||||
"1701dc6ccfbcbec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074f" +
|
|
||||||
"fde8a99d5b723350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14" +
|
|
||||||
"c9fc0f27b8989ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa7" +
|
|
||||||
"7e7332971c7d285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f" +
|
|
||||||
"1290bafd97e655b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb9" +
|
|
||||||
"6222b12ace31a77dcf920334dc94581b02030100010282010100bcf0b93d7238bda329a8" +
|
|
||||||
"72e7149f61bcb37c154330ccb3f42a85c9002c2e2bdea039d77d8581cd19bed94078794e" +
|
|
||||||
"56293d601547fc4bf6a2f9002fe5772b92b21b254403b403585e3130cc99ccf08f0ef81a" +
|
|
||||||
"575b38f597ba4660448b54f44bfbb97072b5a2bf043bfeca828cf7741d13698e3f38162b" +
|
|
||||||
"679faa646b82abd9a72c5c7d722c5fc577a76d2c2daac588accad18516d1bbad10b0dfa2" +
|
|
||||||
"05cfe246b59e28608a43942e1b71b0c80498075121de5b900d727c31c42c78cf1db5c0aa" +
|
|
||||||
"5b491e10ea4ed5c0962aaf2ae025dd81fa4ce490d9d6b4a4465411d8e542fc88617e5695" +
|
|
||||||
"1aa4fc8ea166f2b4d0eb89ef17f2b206bd5f1014bf8fe0e71fe62f2cccf102818100f2dc" +
|
|
||||||
"ddf878d553286daad68bac4070a82ffec3dc4666a2750f47879eec913f91836f1d976b60" +
|
|
||||||
"daf9356e078446dafab5bd2e489e5d64f8572ba24a4ba4f3729b5e106c4dd831cc2497a7" +
|
|
||||||
"e6c7507df05cb64aeb1bbc81c1e340d58b5964cf39cff84ea30c29ec5d3f005ee1362698" +
|
|
||||||
"07395037955955655292c3e85f6187fa1f9502818100f4a33c102630840705f8c778a47b" +
|
|
||||||
"87e8da31e68809af981ac5e5999cf1551685d761cdf0d6520361b99aebd5777a940fa64d" +
|
|
||||||
"327c09fa63746fbb3247ec73a86edf115f1fe5c83598db803881ade71c33c6e956118345" +
|
|
||||||
"497b98b5e07bb5be75971465ec78f2f9467e1b74956ca9d4c7c3e314e742a72d8b33889c" +
|
|
||||||
"6c093a466cef0281801d3df0d02124766dd0be98349b19eb36a508c4e679e793ba0a8bef" +
|
|
||||||
"4d786888c1e9947078b1ea28938716677b4ad8c5052af12eb73ac194915264a913709a0b" +
|
|
||||||
"7b9f98d4a18edd781a13d49899f91c20dbd8eb2e61d991ba19b5cdc08893f5cb9d39e5a6" +
|
|
||||||
"0629ea16d426244673b1b3ee72bd30e41fac8395acac40077403de5efd028180050731dd" +
|
|
||||||
"d71b1a2b96c8d538ba90bb6b62c8b1c74c03aae9a9f59d21a7a82b0d572ef06fa9c807bf" +
|
|
||||||
"c373d6b30d809c7871df96510c577421d9860c7383fda0919ece19996b3ca13562159193" +
|
|
||||||
"c0c246471e287f975e8e57034e5136aaf44254e2650def3d51292474c515b1588969112e" +
|
|
||||||
"0a85cc77073e9d64d2c2fc497844284b02818100d71d63eabf416cf677401ebf965f8314" +
|
|
||||||
"120b568a57dd3bd9116c629c40dc0c6948bab3a13cc544c31c7da40e76132ef5dd3f7534" +
|
|
||||||
"45a635930c74326ae3df0edd1bfb1523e3aa259873ac7cf1ac31151ec8f37b528c275622" +
|
|
||||||
"48f99b8bed59fd4da2576aa6ee20d93a684900bf907e80c66d6e2261ae15e55284b4ed9d" +
|
|
||||||
"6bdaa059"
|
|
||||||
|
|
||||||
const responderCertHex = "308202e2308201caa003020102020101300d06092a864886f70d01010b05003019311730" +
|
|
||||||
"150603550403130e4f43535020526573706f6e646572301e170d31353031333031353530" +
|
|
||||||
"33335a170d3136303133303135353033335a3019311730150603550403130e4f43535020" +
|
|
||||||
"526573706f6e64657230820122300d06092a864886f70d01010105000382010f00308201" +
|
|
||||||
"0a0282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616e" +
|
|
||||||
"c5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbc" +
|
|
||||||
"bec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b72" +
|
|
||||||
"3350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b898" +
|
|
||||||
"9ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d" +
|
|
||||||
"285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e6" +
|
|
||||||
"55b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31" +
|
|
||||||
"a77dcf920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030" +
|
|
||||||
"130603551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d" +
|
|
||||||
"06092a864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab8612" +
|
|
||||||
"31c15fd5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d2288" +
|
|
||||||
"9064f4aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f3267" +
|
|
||||||
"09dce52c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156" +
|
|
||||||
"d67156e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff5" +
|
|
||||||
"9e2005d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf9" +
|
|
||||||
"66705de17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d9" +
|
|
||||||
"3a25439a94299a65a709756c7a3e568be049d5c38839"
|
|
||||||
|
|
||||||
const errorResponseHex = "30030a0101"
|
|
219
vendor/golang.org/x/crypto/openpgp/armor/armor.go
generated
vendored
219
vendor/golang.org/x/crypto/openpgp/armor/armor.go
generated
vendored
|
@ -1,219 +0,0 @@
|
||||||
// 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 "golang.org/x/crypto/openpgp/armor"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"encoding/base64"
|
|
||||||
"golang.org/x/crypto/openpgp/errors"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
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, isPrefix, err := l.in.ReadLine()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if isPrefix {
|
|
||||||
return 0, ArmorCorrupt
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
l.crc = uint32(expectedBytes[0])<<16 |
|
|
||||||
uint32(expectedBytes[1])<<8 |
|
|
||||||
uint32(expectedBytes[2])
|
|
||||||
|
|
||||||
line, _, err = l.in.ReadLine()
|
|
||||||
if err != nil && err != io.EOF {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !bytes.HasPrefix(line, armorEnd) {
|
|
||||||
return 0, ArmorCorrupt
|
|
||||||
}
|
|
||||||
|
|
||||||
l.eof = true
|
|
||||||
return 0, io.EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(line) > 96 {
|
|
||||||
return 0, ArmorCorrupt
|
|
||||||
}
|
|
||||||
|
|
||||||
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 != 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.TrimSpace(line)
|
|
||||||
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
|
|
||||||
}
|
|
95
vendor/golang.org/x/crypto/openpgp/armor/armor_test.go
generated
vendored
95
vendor/golang.org/x/crypto/openpgp/armor/armor_test.go
generated
vendored
|
@ -1,95 +0,0 @@
|
||||||
// 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 (
|
|
||||||
"bytes"
|
|
||||||
"hash/adler32"
|
|
||||||
"io/ioutil"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDecodeEncode(t *testing.T) {
|
|
||||||
buf := bytes.NewBuffer([]byte(armorExample1))
|
|
||||||
result, err := Decode(buf)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
expectedType := "PGP SIGNATURE"
|
|
||||||
if result.Type != expectedType {
|
|
||||||
t.Errorf("result.Type: got:%s want:%s", result.Type, expectedType)
|
|
||||||
}
|
|
||||||
if len(result.Header) != 1 {
|
|
||||||
t.Errorf("len(result.Header): got:%d want:1", len(result.Header))
|
|
||||||
}
|
|
||||||
v, ok := result.Header["Version"]
|
|
||||||
if !ok || v != "GnuPG v1.4.10 (GNU/Linux)" {
|
|
||||||
t.Errorf("result.Header: got:%#v", result.Header)
|
|
||||||
}
|
|
||||||
|
|
||||||
contents, err := ioutil.ReadAll(result.Body)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if adler32.Checksum(contents) != 0x27b144be {
|
|
||||||
t.Errorf("contents: got: %x", contents)
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = bytes.NewBuffer(nil)
|
|
||||||
w, err := Encode(buf, result.Type, result.Header)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
_, err = w.Write(contents)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
w.Close()
|
|
||||||
|
|
||||||
if !bytes.Equal(buf.Bytes(), []byte(armorExample1)) {
|
|
||||||
t.Errorf("got: %s\nwant: %s", string(buf.Bytes()), armorExample1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLongHeader(t *testing.T) {
|
|
||||||
buf := bytes.NewBuffer([]byte(armorLongLine))
|
|
||||||
result, err := Decode(buf)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
value, ok := result.Header["Version"]
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("missing Version header")
|
|
||||||
}
|
|
||||||
if value != longValueExpected {
|
|
||||||
t.Errorf("got: %s want: %s", value, longValueExpected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const armorExample1 = `-----BEGIN PGP SIGNATURE-----
|
|
||||||
Version: GnuPG v1.4.10 (GNU/Linux)
|
|
||||||
|
|
||||||
iJwEAAECAAYFAk1Fv/0ACgkQo01+GMIMMbsYTwQAiAw+QAaNfY6WBdplZ/uMAccm
|
|
||||||
4g+81QPmTSGHnetSb6WBiY13kVzK4HQiZH8JSkmmroMLuGeJwsRTEL4wbjRyUKEt
|
|
||||||
p1xwUZDECs234F1xiG5enc5SGlRtP7foLBz9lOsjx+LEcA4sTl5/2eZR9zyFZqWW
|
|
||||||
TxRjs+fJCIFuo71xb1g=
|
|
||||||
=/teI
|
|
||||||
-----END PGP SIGNATURE-----`
|
|
||||||
|
|
||||||
const armorLongLine = `-----BEGIN PGP SIGNATURE-----
|
|
||||||
Version: 0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz
|
|
||||||
|
|
||||||
iQEcBAABAgAGBQJMtFESAAoJEKsQXJGvOPsVj40H/1WW6jaMXv4BW+1ueDSMDwM8
|
|
||||||
kx1fLOXbVM5/Kn5LStZNt1jWWnpxdz7eq3uiqeCQjmqUoRde3YbB2EMnnwRbAhpp
|
|
||||||
cacnAvy9ZQ78OTxUdNW1mhX5bS6q1MTEJnl+DcyigD70HG/yNNQD7sOPMdYQw0TA
|
|
||||||
byQBwmLwmTsuZsrYqB68QyLHI+DUugn+kX6Hd2WDB62DKa2suoIUIHQQCd/ofwB3
|
|
||||||
WfCYInXQKKOSxu2YOg2Eb4kLNhSMc1i9uKUWAH+sdgJh7NBgdoE4MaNtBFkHXRvv
|
|
||||||
okWuf3+xA9ksp1npSY/mDvgHijmjvtpRDe6iUeqfCn8N9u9CBg8geANgaG8+QA4=
|
|
||||||
=wfQG
|
|
||||||
-----END PGP SIGNATURE-----`
|
|
||||||
|
|
||||||
const longValueExpected = "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz"
|
|
160
vendor/golang.org/x/crypto/openpgp/armor/encode.go
generated
vendored
160
vendor/golang.org/x/crypto/openpgp/armor/encode.go
generated
vendored
|
@ -1,160 +0,0 @@
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
59
vendor/golang.org/x/crypto/openpgp/canonical_text.go
generated
vendored
59
vendor/golang.org/x/crypto/openpgp/canonical_text.go
generated
vendored
|
@ -1,59 +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 openpgp
|
|
||||||
|
|
||||||
import "hash"
|
|
||||||
|
|
||||||
// NewCanonicalTextHash reformats text written to it into the canonical
|
|
||||||
// form and then applies the hash h. See RFC 4880, section 5.2.1.
|
|
||||||
func NewCanonicalTextHash(h hash.Hash) hash.Hash {
|
|
||||||
return &canonicalTextHash{h, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
type canonicalTextHash struct {
|
|
||||||
h hash.Hash
|
|
||||||
s int
|
|
||||||
}
|
|
||||||
|
|
||||||
var newline = []byte{'\r', '\n'}
|
|
||||||
|
|
||||||
func (cth *canonicalTextHash) Write(buf []byte) (int, error) {
|
|
||||||
start := 0
|
|
||||||
|
|
||||||
for i, c := range buf {
|
|
||||||
switch cth.s {
|
|
||||||
case 0:
|
|
||||||
if c == '\r' {
|
|
||||||
cth.s = 1
|
|
||||||
} else if c == '\n' {
|
|
||||||
cth.h.Write(buf[start:i])
|
|
||||||
cth.h.Write(newline)
|
|
||||||
start = i + 1
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
cth.s = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cth.h.Write(buf[start:])
|
|
||||||
return len(buf), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cth *canonicalTextHash) Sum(in []byte) []byte {
|
|
||||||
return cth.h.Sum(in)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cth *canonicalTextHash) Reset() {
|
|
||||||
cth.h.Reset()
|
|
||||||
cth.s = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cth *canonicalTextHash) Size() int {
|
|
||||||
return cth.h.Size()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cth *canonicalTextHash) BlockSize() int {
|
|
||||||
return cth.h.BlockSize()
|
|
||||||
}
|
|
52
vendor/golang.org/x/crypto/openpgp/canonical_text_test.go
generated
vendored
52
vendor/golang.org/x/crypto/openpgp/canonical_text_test.go
generated
vendored
|
@ -1,52 +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 openpgp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
type recordingHash struct {
|
|
||||||
buf *bytes.Buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r recordingHash) Write(b []byte) (n int, err error) {
|
|
||||||
return r.buf.Write(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r recordingHash) Sum(in []byte) []byte {
|
|
||||||
return append(in, r.buf.Bytes()...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r recordingHash) Reset() {
|
|
||||||
panic("shouldn't be called")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r recordingHash) Size() int {
|
|
||||||
panic("shouldn't be called")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r recordingHash) BlockSize() int {
|
|
||||||
panic("shouldn't be called")
|
|
||||||
}
|
|
||||||
|
|
||||||
func testCanonicalText(t *testing.T, input, expected string) {
|
|
||||||
r := recordingHash{bytes.NewBuffer(nil)}
|
|
||||||
c := NewCanonicalTextHash(r)
|
|
||||||
c.Write([]byte(input))
|
|
||||||
result := c.Sum(nil)
|
|
||||||
if expected != string(result) {
|
|
||||||
t.Errorf("input: %x got: %x want: %x", input, result, expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCanonicalText(t *testing.T) {
|
|
||||||
testCanonicalText(t, "foo\n", "foo\r\n")
|
|
||||||
testCanonicalText(t, "foo", "foo")
|
|
||||||
testCanonicalText(t, "foo\r\n", "foo\r\n")
|
|
||||||
testCanonicalText(t, "foo\r\nbar", "foo\r\nbar")
|
|
||||||
testCanonicalText(t, "foo\r\nbar\n\n", "foo\r\nbar\r\n\r\n")
|
|
||||||
}
|
|
376
vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go
generated
vendored
376
vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go
generated
vendored
|
@ -1,376 +0,0 @@
|
||||||
// Copyright 2012 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 clearsign generates and processes OpenPGP, clear-signed data. See
|
|
||||||
// RFC 4880, section 7.
|
|
||||||
//
|
|
||||||
// Clearsigned messages are cryptographically signed, but the contents of the
|
|
||||||
// message are kept in plaintext so that it can be read without special tools.
|
|
||||||
package clearsign // import "golang.org/x/crypto/openpgp/clearsign"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"crypto"
|
|
||||||
"hash"
|
|
||||||
"io"
|
|
||||||
"net/textproto"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp/armor"
|
|
||||||
"golang.org/x/crypto/openpgp/errors"
|
|
||||||
"golang.org/x/crypto/openpgp/packet"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Block represents a clearsigned message. A signature on a Block can
|
|
||||||
// be checked by passing Bytes into openpgp.CheckDetachedSignature.
|
|
||||||
type Block struct {
|
|
||||||
Headers textproto.MIMEHeader // Optional message headers
|
|
||||||
Plaintext []byte // The original message text
|
|
||||||
Bytes []byte // The signed message
|
|
||||||
ArmoredSignature *armor.Block // The signature block
|
|
||||||
}
|
|
||||||
|
|
||||||
// start is the marker which denotes the beginning of a clearsigned message.
|
|
||||||
var start = []byte("\n-----BEGIN PGP SIGNED MESSAGE-----")
|
|
||||||
|
|
||||||
// dashEscape is prefixed to any lines that begin with a hyphen so that they
|
|
||||||
// can't be confused with endText.
|
|
||||||
var dashEscape = []byte("- ")
|
|
||||||
|
|
||||||
// endText is a marker which denotes the end of the message and the start of
|
|
||||||
// an armored signature.
|
|
||||||
var endText = []byte("-----BEGIN PGP SIGNATURE-----")
|
|
||||||
|
|
||||||
// end is a marker which denotes the end of the armored signature.
|
|
||||||
var end = []byte("\n-----END PGP SIGNATURE-----")
|
|
||||||
|
|
||||||
var crlf = []byte("\r\n")
|
|
||||||
var lf = byte('\n')
|
|
||||||
|
|
||||||
// getLine returns the first \r\n or \n delineated line from the given byte
|
|
||||||
// array. The line does not include the \r\n or \n. The remainder of the byte
|
|
||||||
// array (also not including the new line bytes) is also returned and this will
|
|
||||||
// always be smaller than the original argument.
|
|
||||||
func getLine(data []byte) (line, rest []byte) {
|
|
||||||
i := bytes.Index(data, []byte{'\n'})
|
|
||||||
var j int
|
|
||||||
if i < 0 {
|
|
||||||
i = len(data)
|
|
||||||
j = i
|
|
||||||
} else {
|
|
||||||
j = i + 1
|
|
||||||
if i > 0 && data[i-1] == '\r' {
|
|
||||||
i--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return data[0:i], data[j:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode finds the first clearsigned message in data and returns it, as well
|
|
||||||
// as the suffix of data which remains after the message.
|
|
||||||
func Decode(data []byte) (b *Block, rest []byte) {
|
|
||||||
// start begins with a newline. However, at the very beginning of
|
|
||||||
// the byte array, we'll accept the start string without it.
|
|
||||||
rest = data
|
|
||||||
if bytes.HasPrefix(data, start[1:]) {
|
|
||||||
rest = rest[len(start)-1:]
|
|
||||||
} else if i := bytes.Index(data, start); i >= 0 {
|
|
||||||
rest = rest[i+len(start):]
|
|
||||||
} else {
|
|
||||||
return nil, data
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consume the start line.
|
|
||||||
_, rest = getLine(rest)
|
|
||||||
|
|
||||||
var line []byte
|
|
||||||
b = &Block{
|
|
||||||
Headers: make(textproto.MIMEHeader),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next come a series of header lines.
|
|
||||||
for {
|
|
||||||
// This loop terminates because getLine's second result is
|
|
||||||
// always smaller than its argument.
|
|
||||||
if len(rest) == 0 {
|
|
||||||
return nil, data
|
|
||||||
}
|
|
||||||
// An empty line marks the end of the headers.
|
|
||||||
if line, rest = getLine(rest); len(line) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
i := bytes.Index(line, []byte{':'})
|
|
||||||
if i == -1 {
|
|
||||||
return nil, data
|
|
||||||
}
|
|
||||||
|
|
||||||
key, val := line[0:i], line[i+1:]
|
|
||||||
key = bytes.TrimSpace(key)
|
|
||||||
val = bytes.TrimSpace(val)
|
|
||||||
b.Headers.Add(string(key), string(val))
|
|
||||||
}
|
|
||||||
|
|
||||||
firstLine := true
|
|
||||||
for {
|
|
||||||
start := rest
|
|
||||||
|
|
||||||
line, rest = getLine(rest)
|
|
||||||
if len(line) == 0 && len(rest) == 0 {
|
|
||||||
// No armored data was found, so this isn't a complete message.
|
|
||||||
return nil, data
|
|
||||||
}
|
|
||||||
if bytes.Equal(line, endText) {
|
|
||||||
// Back up to the start of the line because armor expects to see the
|
|
||||||
// header line.
|
|
||||||
rest = start
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// The final CRLF isn't included in the hash so we don't write it until
|
|
||||||
// we've seen the next line.
|
|
||||||
if firstLine {
|
|
||||||
firstLine = false
|
|
||||||
} else {
|
|
||||||
b.Bytes = append(b.Bytes, crlf...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if bytes.HasPrefix(line, dashEscape) {
|
|
||||||
line = line[2:]
|
|
||||||
}
|
|
||||||
line = bytes.TrimRight(line, " \t")
|
|
||||||
b.Bytes = append(b.Bytes, line...)
|
|
||||||
|
|
||||||
b.Plaintext = append(b.Plaintext, line...)
|
|
||||||
b.Plaintext = append(b.Plaintext, lf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// We want to find the extent of the armored data (including any newlines at
|
|
||||||
// the end).
|
|
||||||
i := bytes.Index(rest, end)
|
|
||||||
if i == -1 {
|
|
||||||
return nil, data
|
|
||||||
}
|
|
||||||
i += len(end)
|
|
||||||
for i < len(rest) && (rest[i] == '\r' || rest[i] == '\n') {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
armored := rest[:i]
|
|
||||||
rest = rest[i:]
|
|
||||||
|
|
||||||
var err error
|
|
||||||
b.ArmoredSignature, err = armor.Decode(bytes.NewBuffer(armored))
|
|
||||||
if err != nil {
|
|
||||||
return nil, data
|
|
||||||
}
|
|
||||||
|
|
||||||
return b, rest
|
|
||||||
}
|
|
||||||
|
|
||||||
// A dashEscaper is an io.WriteCloser which processes the body of a clear-signed
|
|
||||||
// message. The clear-signed message is written to buffered and a hash, suitable
|
|
||||||
// for signing, is maintained in h.
|
|
||||||
//
|
|
||||||
// When closed, an armored signature is created and written to complete the
|
|
||||||
// message.
|
|
||||||
type dashEscaper struct {
|
|
||||||
buffered *bufio.Writer
|
|
||||||
h hash.Hash
|
|
||||||
hashType crypto.Hash
|
|
||||||
|
|
||||||
atBeginningOfLine bool
|
|
||||||
isFirstLine bool
|
|
||||||
|
|
||||||
whitespace []byte
|
|
||||||
byteBuf []byte // a one byte buffer to save allocations
|
|
||||||
|
|
||||||
privateKey *packet.PrivateKey
|
|
||||||
config *packet.Config
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *dashEscaper) Write(data []byte) (n int, err error) {
|
|
||||||
for _, b := range data {
|
|
||||||
d.byteBuf[0] = b
|
|
||||||
|
|
||||||
if d.atBeginningOfLine {
|
|
||||||
// The final CRLF isn't included in the hash so we have to wait
|
|
||||||
// until this point (the start of the next line) before writing it.
|
|
||||||
if !d.isFirstLine {
|
|
||||||
d.h.Write(crlf)
|
|
||||||
}
|
|
||||||
d.isFirstLine = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Any whitespace at the end of the line has to be removed so we
|
|
||||||
// buffer it until we find out whether there's more on this line.
|
|
||||||
if b == ' ' || b == '\t' || b == '\r' {
|
|
||||||
d.whitespace = append(d.whitespace, b)
|
|
||||||
d.atBeginningOfLine = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if d.atBeginningOfLine {
|
|
||||||
// At the beginning of a line, hyphens have to be escaped.
|
|
||||||
if b == '-' {
|
|
||||||
// The signature isn't calculated over the dash-escaped text so
|
|
||||||
// the escape is only written to buffered.
|
|
||||||
if _, err = d.buffered.Write(dashEscape); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
d.h.Write(d.byteBuf)
|
|
||||||
d.atBeginningOfLine = false
|
|
||||||
} else if b == '\n' {
|
|
||||||
// Nothing to do because we delay writing CRLF to the hash.
|
|
||||||
} else {
|
|
||||||
d.h.Write(d.byteBuf)
|
|
||||||
d.atBeginningOfLine = false
|
|
||||||
}
|
|
||||||
if err = d.buffered.WriteByte(b); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if b == '\n' {
|
|
||||||
// We got a raw \n. Drop any trailing whitespace and write a
|
|
||||||
// CRLF.
|
|
||||||
d.whitespace = d.whitespace[:0]
|
|
||||||
// We delay writing CRLF to the hash until the start of the
|
|
||||||
// next line.
|
|
||||||
if err = d.buffered.WriteByte(b); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
d.atBeginningOfLine = true
|
|
||||||
} else {
|
|
||||||
// Any buffered whitespace wasn't at the end of the line so
|
|
||||||
// we need to write it out.
|
|
||||||
if len(d.whitespace) > 0 {
|
|
||||||
d.h.Write(d.whitespace)
|
|
||||||
if _, err = d.buffered.Write(d.whitespace); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
d.whitespace = d.whitespace[:0]
|
|
||||||
}
|
|
||||||
d.h.Write(d.byteBuf)
|
|
||||||
if err = d.buffered.WriteByte(b); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
n = len(data)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *dashEscaper) Close() (err error) {
|
|
||||||
if !d.atBeginningOfLine {
|
|
||||||
if err = d.buffered.WriteByte(lf); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sig := new(packet.Signature)
|
|
||||||
sig.SigType = packet.SigTypeText
|
|
||||||
sig.PubKeyAlgo = d.privateKey.PubKeyAlgo
|
|
||||||
sig.Hash = d.hashType
|
|
||||||
sig.CreationTime = d.config.Now()
|
|
||||||
sig.IssuerKeyId = &d.privateKey.KeyId
|
|
||||||
|
|
||||||
if err = sig.Sign(d.h, d.privateKey, d.config); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := armor.Encode(d.buffered, "PGP SIGNATURE", nil)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = sig.Serialize(out); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err = out.Close(); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err = d.buffered.Flush(); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode returns a WriteCloser which will clear-sign a message with privateKey
|
|
||||||
// and write it to w. If config is nil, sensible defaults are used.
|
|
||||||
func Encode(w io.Writer, privateKey *packet.PrivateKey, config *packet.Config) (plaintext io.WriteCloser, err error) {
|
|
||||||
if privateKey.Encrypted {
|
|
||||||
return nil, errors.InvalidArgumentError("signing key is encrypted")
|
|
||||||
}
|
|
||||||
|
|
||||||
hashType := config.Hash()
|
|
||||||
name := nameOfHash(hashType)
|
|
||||||
if len(name) == 0 {
|
|
||||||
return nil, errors.UnsupportedError("unknown hash type: " + strconv.Itoa(int(hashType)))
|
|
||||||
}
|
|
||||||
|
|
||||||
if !hashType.Available() {
|
|
||||||
return nil, errors.UnsupportedError("unsupported hash type: " + strconv.Itoa(int(hashType)))
|
|
||||||
}
|
|
||||||
h := hashType.New()
|
|
||||||
|
|
||||||
buffered := bufio.NewWriter(w)
|
|
||||||
// start has a \n at the beginning that we don't want here.
|
|
||||||
if _, err = buffered.Write(start[1:]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err = buffered.WriteByte(lf); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, err = buffered.WriteString("Hash: "); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, err = buffered.WriteString(name); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err = buffered.WriteByte(lf); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err = buffered.WriteByte(lf); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
plaintext = &dashEscaper{
|
|
||||||
buffered: buffered,
|
|
||||||
h: h,
|
|
||||||
hashType: hashType,
|
|
||||||
|
|
||||||
atBeginningOfLine: true,
|
|
||||||
isFirstLine: true,
|
|
||||||
|
|
||||||
byteBuf: make([]byte, 1),
|
|
||||||
|
|
||||||
privateKey: privateKey,
|
|
||||||
config: config,
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// nameOfHash returns the OpenPGP name for the given hash, or the empty string
|
|
||||||
// if the name isn't known. See RFC 4880, section 9.4.
|
|
||||||
func nameOfHash(h crypto.Hash) string {
|
|
||||||
switch h {
|
|
||||||
case crypto.MD5:
|
|
||||||
return "MD5"
|
|
||||||
case crypto.SHA1:
|
|
||||||
return "SHA1"
|
|
||||||
case crypto.RIPEMD160:
|
|
||||||
return "RIPEMD160"
|
|
||||||
case crypto.SHA224:
|
|
||||||
return "SHA224"
|
|
||||||
case crypto.SHA256:
|
|
||||||
return "SHA256"
|
|
||||||
case crypto.SHA384:
|
|
||||||
return "SHA384"
|
|
||||||
case crypto.SHA512:
|
|
||||||
return "SHA512"
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
210
vendor/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go
generated
vendored
210
vendor/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go
generated
vendored
|
@ -1,210 +0,0 @@
|
||||||
// Copyright 2012 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 clearsign
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"golang.org/x/crypto/openpgp"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func testParse(t *testing.T, input []byte, expected, expectedPlaintext string) {
|
|
||||||
b, rest := Decode(input)
|
|
||||||
if b == nil {
|
|
||||||
t.Fatal("failed to decode clearsign message")
|
|
||||||
}
|
|
||||||
if !bytes.Equal(rest, []byte("trailing")) {
|
|
||||||
t.Errorf("unexpected remaining bytes returned: %s", string(rest))
|
|
||||||
}
|
|
||||||
if b.ArmoredSignature.Type != "PGP SIGNATURE" {
|
|
||||||
t.Errorf("bad armor type, got:%s, want:PGP SIGNATURE", b.ArmoredSignature.Type)
|
|
||||||
}
|
|
||||||
if !bytes.Equal(b.Bytes, []byte(expected)) {
|
|
||||||
t.Errorf("bad body, got:%x want:%x", b.Bytes, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(b.Plaintext, []byte(expectedPlaintext)) {
|
|
||||||
t.Errorf("bad plaintext, got:%x want:%x", b.Plaintext, expectedPlaintext)
|
|
||||||
}
|
|
||||||
|
|
||||||
keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("failed to parse public key: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil {
|
|
||||||
t.Errorf("failed to check signature: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParse(t *testing.T) {
|
|
||||||
testParse(t, clearsignInput, "Hello world\r\nline 2", "Hello world\nline 2\n")
|
|
||||||
testParse(t, clearsignInput2, "\r\n\r\n(This message has a couple of blank lines at the start and end.)\r\n\r\n", "\n\n(This message has a couple of blank lines at the start and end.)\n\n\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseInvalid(t *testing.T) {
|
|
||||||
if b, _ := Decode(clearsignInput3); b != nil {
|
|
||||||
t.Fatal("decoded a bad clearsigned message without any error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseWithNoNewlineAtEnd(t *testing.T) {
|
|
||||||
input := clearsignInput
|
|
||||||
input = input[:len(input)-len("trailing")-1]
|
|
||||||
b, rest := Decode(input)
|
|
||||||
if b == nil {
|
|
||||||
t.Fatal("failed to decode clearsign message")
|
|
||||||
}
|
|
||||||
if len(rest) > 0 {
|
|
||||||
t.Errorf("unexpected remaining bytes returned: %s", string(rest))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var signingTests = []struct {
|
|
||||||
in, signed, plaintext string
|
|
||||||
}{
|
|
||||||
{"", "", ""},
|
|
||||||
{"a", "a", "a\n"},
|
|
||||||
{"a\n", "a", "a\n"},
|
|
||||||
{"-a\n", "-a", "-a\n"},
|
|
||||||
{"--a\nb", "--a\r\nb", "--a\nb\n"},
|
|
||||||
// leading whitespace
|
|
||||||
{" a\n", " a", " a\n"},
|
|
||||||
{" a\n", " a", " a\n"},
|
|
||||||
// trailing whitespace (should be stripped)
|
|
||||||
{"a \n", "a", "a\n"},
|
|
||||||
{"a ", "a", "a\n"},
|
|
||||||
// whitespace-only lines (should be stripped)
|
|
||||||
{" \n", "", "\n"},
|
|
||||||
{" ", "", "\n"},
|
|
||||||
{"a\n \n \nb\n", "a\r\n\r\n\r\nb", "a\n\n\nb\n"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSigning(t *testing.T) {
|
|
||||||
keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("failed to parse public key: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, test := range signingTests {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
|
|
||||||
plaintext, err := Encode(&buf, keyring[0].PrivateKey, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("#%d: error from Encode: %s", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, err := plaintext.Write([]byte(test.in)); err != nil {
|
|
||||||
t.Errorf("#%d: error from Write: %s", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := plaintext.Close(); err != nil {
|
|
||||||
t.Fatalf("#%d: error from Close: %s", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
b, _ := Decode(buf.Bytes())
|
|
||||||
if b == nil {
|
|
||||||
t.Errorf("#%d: failed to decode clearsign message", i)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !bytes.Equal(b.Bytes, []byte(test.signed)) {
|
|
||||||
t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Bytes, test.signed)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !bytes.Equal(b.Plaintext, []byte(test.plaintext)) {
|
|
||||||
t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Plaintext, test.plaintext)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil {
|
|
||||||
t.Errorf("#%d: failed to check signature: %s", i, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var clearsignInput = []byte(`
|
|
||||||
;lasjlkfdsa
|
|
||||||
|
|
||||||
-----BEGIN PGP SIGNED MESSAGE-----
|
|
||||||
Hash: SHA1
|
|
||||||
|
|
||||||
Hello world
|
|
||||||
line 2
|
|
||||||
-----BEGIN PGP SIGNATURE-----
|
|
||||||
Version: GnuPG v1.4.10 (GNU/Linux)
|
|
||||||
|
|
||||||
iJwEAQECAAYFAk8kMuEACgkQO9o98PRieSpMsAQAhmY/vwmNpflrPgmfWsYhk5O8
|
|
||||||
pjnBUzZwqTDoDeINjZEoPDSpQAHGhjFjgaDx/Gj4fAl0dM4D0wuUEBb6QOrwflog
|
|
||||||
2A2k9kfSOMOtk0IH/H5VuFN1Mie9L/erYXjTQIptv9t9J7NoRBMU0QOOaFU0JaO9
|
|
||||||
MyTpno24AjIAGb+mH1U=
|
|
||||||
=hIJ6
|
|
||||||
-----END PGP SIGNATURE-----
|
|
||||||
trailing`)
|
|
||||||
|
|
||||||
var clearsignInput2 = []byte(`
|
|
||||||
asdlfkjasdlkfjsadf
|
|
||||||
|
|
||||||
-----BEGIN PGP SIGNED MESSAGE-----
|
|
||||||
Hash: SHA256
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(This message has a couple of blank lines at the start and end.)
|
|
||||||
|
|
||||||
|
|
||||||
-----BEGIN PGP SIGNATURE-----
|
|
||||||
Version: GnuPG v1.4.11 (GNU/Linux)
|
|
||||||
|
|
||||||
iJwEAQEIAAYFAlPpSREACgkQO9o98PRieSpZTAP+M8QUoCt/7Rf3YbXPcdzIL32v
|
|
||||||
pt1I+cMNeopzfLy0u4ioEFi8s5VkwpL1AFmirvgViCwlf82inoRxzZRiW05JQ5LI
|
|
||||||
ESEzeCoy2LIdRCQ2hcrG8pIUPzUO4TqO5D/dMbdHwNH4h5nNmGJUAEG6FpURlPm+
|
|
||||||
qZg6BaTvOxepqOxnhVU=
|
|
||||||
=e+C6
|
|
||||||
-----END PGP SIGNATURE-----
|
|
||||||
|
|
||||||
trailing`)
|
|
||||||
|
|
||||||
var clearsignInput3 = []byte(`
|
|
||||||
-----BEGIN PGP SIGNED MESSAGE-----
|
|
||||||
Hash: SHA256
|
|
||||||
|
|
||||||
(This message was truncated.)
|
|
||||||
`)
|
|
||||||
|
|
||||||
var signingKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
|
||||||
Version: GnuPG v1.4.10 (GNU/Linux)
|
|
||||||
|
|
||||||
lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp
|
|
||||||
idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn
|
|
||||||
vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB
|
|
||||||
AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X
|
|
||||||
0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL
|
|
||||||
IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk
|
|
||||||
VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn
|
|
||||||
gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9
|
|
||||||
TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx
|
|
||||||
q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz
|
|
||||||
dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
|
|
||||||
CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1
|
|
||||||
ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+
|
|
||||||
eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid
|
|
||||||
AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV
|
|
||||||
bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK
|
|
||||||
/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA
|
|
||||||
A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX
|
|
||||||
TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc
|
|
||||||
lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6
|
|
||||||
rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN
|
|
||||||
oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8
|
|
||||||
QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU
|
|
||||||
nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC
|
|
||||||
AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp
|
|
||||||
BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad
|
|
||||||
AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL
|
|
||||||
VrM0m72/jnpKo04=
|
|
||||||
=zNCn
|
|
||||||
-----END PGP PRIVATE KEY BLOCK-----
|
|
||||||
`
|
|
122
vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go
generated
vendored
122
vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go
generated
vendored
|
@ -1,122 +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 elgamal implements ElGamal encryption, suitable for OpenPGP,
|
|
||||||
// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on
|
|
||||||
// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31,
|
|
||||||
// n. 4, 1985, pp. 469-472.
|
|
||||||
//
|
|
||||||
// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it
|
|
||||||
// unsuitable for other protocols. RSA should be used in preference in any
|
|
||||||
// case.
|
|
||||||
package elgamal // import "golang.org/x/crypto/openpgp/elgamal"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/subtle"
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"math/big"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PublicKey represents an ElGamal public key.
|
|
||||||
type PublicKey struct {
|
|
||||||
G, P, Y *big.Int
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrivateKey represents an ElGamal private key.
|
|
||||||
type PrivateKey struct {
|
|
||||||
PublicKey
|
|
||||||
X *big.Int
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encrypt encrypts the given message to the given public key. The result is a
|
|
||||||
// pair of integers. Errors can result from reading random, or because msg is
|
|
||||||
// too large to be encrypted to the public key.
|
|
||||||
func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) {
|
|
||||||
pLen := (pub.P.BitLen() + 7) / 8
|
|
||||||
if len(msg) > pLen-11 {
|
|
||||||
err = errors.New("elgamal: message too long")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// EM = 0x02 || PS || 0x00 || M
|
|
||||||
em := make([]byte, pLen-1)
|
|
||||||
em[0] = 2
|
|
||||||
ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):]
|
|
||||||
err = nonZeroRandomBytes(ps, random)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
em[len(em)-len(msg)-1] = 0
|
|
||||||
copy(mm, msg)
|
|
||||||
|
|
||||||
m := new(big.Int).SetBytes(em)
|
|
||||||
|
|
||||||
k, err := rand.Int(random, pub.P)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c1 = new(big.Int).Exp(pub.G, k, pub.P)
|
|
||||||
s := new(big.Int).Exp(pub.Y, k, pub.P)
|
|
||||||
c2 = s.Mul(s, m)
|
|
||||||
c2.Mod(c2, pub.P)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrypt takes two integers, resulting from an ElGamal encryption, and
|
|
||||||
// returns the plaintext of the message. An error can result only if the
|
|
||||||
// ciphertext is invalid. Users should keep in mind that this is a padding
|
|
||||||
// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can
|
|
||||||
// be used to break the cryptosystem. See ``Chosen Ciphertext Attacks
|
|
||||||
// Against Protocols Based on the RSA Encryption Standard PKCS #1'', Daniel
|
|
||||||
// Bleichenbacher, Advances in Cryptology (Crypto '98),
|
|
||||||
func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
|
|
||||||
s := new(big.Int).Exp(c1, priv.X, priv.P)
|
|
||||||
s.ModInverse(s, priv.P)
|
|
||||||
s.Mul(s, c2)
|
|
||||||
s.Mod(s, priv.P)
|
|
||||||
em := s.Bytes()
|
|
||||||
|
|
||||||
firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2)
|
|
||||||
|
|
||||||
// The remainder of the plaintext must be a string of non-zero random
|
|
||||||
// octets, followed by a 0, followed by the message.
|
|
||||||
// lookingForIndex: 1 iff we are still looking for the zero.
|
|
||||||
// index: the offset of the first zero byte.
|
|
||||||
var lookingForIndex, index int
|
|
||||||
lookingForIndex = 1
|
|
||||||
|
|
||||||
for i := 1; i < len(em); i++ {
|
|
||||||
equals0 := subtle.ConstantTimeByteEq(em[i], 0)
|
|
||||||
index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
|
|
||||||
lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
|
|
||||||
}
|
|
||||||
|
|
||||||
if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 {
|
|
||||||
return nil, errors.New("elgamal: decryption error")
|
|
||||||
}
|
|
||||||
return em[index+1:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// nonZeroRandomBytes fills the given slice with non-zero random octets.
|
|
||||||
func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
|
|
||||||
_, err = io.ReadFull(rand, s)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
for s[i] == 0 {
|
|
||||||
_, err = io.ReadFull(rand, s[i:i+1])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
49
vendor/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go
generated
vendored
49
vendor/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go
generated
vendored
|
@ -1,49 +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 elgamal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
|
||||||
"math/big"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This is the 1024-bit MODP group from RFC 5114, section 2.1:
|
|
||||||
const primeHex = "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371"
|
|
||||||
|
|
||||||
const generatorHex = "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507FD6406CFF14266D31266FEA1E5C41564B777E690F5504F213160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28AD662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24855E6EEB22B3B2E5"
|
|
||||||
|
|
||||||
func fromHex(hex string) *big.Int {
|
|
||||||
n, ok := new(big.Int).SetString(hex, 16)
|
|
||||||
if !ok {
|
|
||||||
panic("failed to parse hex number")
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEncryptDecrypt(t *testing.T) {
|
|
||||||
priv := &PrivateKey{
|
|
||||||
PublicKey: PublicKey{
|
|
||||||
G: fromHex(generatorHex),
|
|
||||||
P: fromHex(primeHex),
|
|
||||||
},
|
|
||||||
X: fromHex("42"),
|
|
||||||
}
|
|
||||||
priv.Y = new(big.Int).Exp(priv.G, priv.X, priv.P)
|
|
||||||
|
|
||||||
message := []byte("hello world")
|
|
||||||
c1, c2, err := Encrypt(rand.Reader, &priv.PublicKey, message)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error encrypting: %s", err)
|
|
||||||
}
|
|
||||||
message2, err := Decrypt(priv, c1, c2)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error decrypting: %s", err)
|
|
||||||
}
|
|
||||||
if !bytes.Equal(message2, message) {
|
|
||||||
t.Errorf("decryption failed, got: %x, want: %x", message2, message)
|
|
||||||
}
|
|
||||||
}
|
|
72
vendor/golang.org/x/crypto/openpgp/errors/errors.go
generated
vendored
72
vendor/golang.org/x/crypto/openpgp/errors/errors.go
generated
vendored
|
@ -1,72 +0,0 @@
|
||||||
// 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 errors contains common error types for the OpenPGP packages.
|
|
||||||
package errors // import "golang.org/x/crypto/openpgp/errors"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A StructuralError is returned when OpenPGP data is found to be syntactically
|
|
||||||
// invalid.
|
|
||||||
type StructuralError string
|
|
||||||
|
|
||||||
func (s StructuralError) Error() string {
|
|
||||||
return "openpgp: invalid data: " + string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnsupportedError indicates that, although the OpenPGP data is valid, it
|
|
||||||
// makes use of currently unimplemented features.
|
|
||||||
type UnsupportedError string
|
|
||||||
|
|
||||||
func (s UnsupportedError) Error() string {
|
|
||||||
return "openpgp: unsupported feature: " + string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InvalidArgumentError indicates that the caller is in error and passed an
|
|
||||||
// incorrect value.
|
|
||||||
type InvalidArgumentError string
|
|
||||||
|
|
||||||
func (i InvalidArgumentError) Error() string {
|
|
||||||
return "openpgp: invalid argument: " + string(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignatureError indicates that a syntactically valid signature failed to
|
|
||||||
// validate.
|
|
||||||
type SignatureError string
|
|
||||||
|
|
||||||
func (b SignatureError) Error() string {
|
|
||||||
return "openpgp: invalid signature: " + string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
type keyIncorrectError int
|
|
||||||
|
|
||||||
func (ki keyIncorrectError) Error() string {
|
|
||||||
return "openpgp: incorrect key"
|
|
||||||
}
|
|
||||||
|
|
||||||
var ErrKeyIncorrect error = keyIncorrectError(0)
|
|
||||||
|
|
||||||
type unknownIssuerError int
|
|
||||||
|
|
||||||
func (unknownIssuerError) Error() string {
|
|
||||||
return "openpgp: signature made by unknown entity"
|
|
||||||
}
|
|
||||||
|
|
||||||
var ErrUnknownIssuer error = unknownIssuerError(0)
|
|
||||||
|
|
||||||
type keyRevokedError int
|
|
||||||
|
|
||||||
func (keyRevokedError) Error() string {
|
|
||||||
return "openpgp: signature made by revoked key"
|
|
||||||
}
|
|
||||||
|
|
||||||
var ErrKeyRevoked error = keyRevokedError(0)
|
|
||||||
|
|
||||||
type UnknownPacketTypeError uint8
|
|
||||||
|
|
||||||
func (upte UnknownPacketTypeError) Error() string {
|
|
||||||
return "openpgp: unknown packet type: " + strconv.Itoa(int(upte))
|
|
||||||
}
|
|
633
vendor/golang.org/x/crypto/openpgp/keys.go
generated
vendored
633
vendor/golang.org/x/crypto/openpgp/keys.go
generated
vendored
|
@ -1,633 +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 openpgp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rsa"
|
|
||||||
"io"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp/armor"
|
|
||||||
"golang.org/x/crypto/openpgp/errors"
|
|
||||||
"golang.org/x/crypto/openpgp/packet"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PublicKeyType is the armor type for a PGP public key.
|
|
||||||
var PublicKeyType = "PGP PUBLIC KEY BLOCK"
|
|
||||||
|
|
||||||
// PrivateKeyType is the armor type for a PGP private key.
|
|
||||||
var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
|
|
||||||
|
|
||||||
// An Entity represents the components of an OpenPGP key: a primary public key
|
|
||||||
// (which must be a signing key), one or more identities claimed by that key,
|
|
||||||
// and zero or more subkeys, which may be encryption keys.
|
|
||||||
type Entity struct {
|
|
||||||
PrimaryKey *packet.PublicKey
|
|
||||||
PrivateKey *packet.PrivateKey
|
|
||||||
Identities map[string]*Identity // indexed by Identity.Name
|
|
||||||
Revocations []*packet.Signature
|
|
||||||
Subkeys []Subkey
|
|
||||||
}
|
|
||||||
|
|
||||||
// An Identity represents an identity claimed by an Entity and zero or more
|
|
||||||
// assertions by other entities about that claim.
|
|
||||||
type Identity struct {
|
|
||||||
Name string // by convention, has the form "Full Name (comment) <email@example.com>"
|
|
||||||
UserId *packet.UserId
|
|
||||||
SelfSignature *packet.Signature
|
|
||||||
Signatures []*packet.Signature
|
|
||||||
}
|
|
||||||
|
|
||||||
// A Subkey is an additional public key in an Entity. Subkeys can be used for
|
|
||||||
// encryption.
|
|
||||||
type Subkey struct {
|
|
||||||
PublicKey *packet.PublicKey
|
|
||||||
PrivateKey *packet.PrivateKey
|
|
||||||
Sig *packet.Signature
|
|
||||||
}
|
|
||||||
|
|
||||||
// A Key identifies a specific public key in an Entity. This is either the
|
|
||||||
// Entity's primary key or a subkey.
|
|
||||||
type Key struct {
|
|
||||||
Entity *Entity
|
|
||||||
PublicKey *packet.PublicKey
|
|
||||||
PrivateKey *packet.PrivateKey
|
|
||||||
SelfSignature *packet.Signature
|
|
||||||
}
|
|
||||||
|
|
||||||
// A KeyRing provides access to public and private keys.
|
|
||||||
type KeyRing interface {
|
|
||||||
// KeysById returns the set of keys that have the given key id.
|
|
||||||
KeysById(id uint64) []Key
|
|
||||||
// KeysByIdAndUsage returns the set of keys with the given id
|
|
||||||
// that also meet the key usage given by requiredUsage.
|
|
||||||
// The requiredUsage is expressed as the bitwise-OR of
|
|
||||||
// packet.KeyFlag* values.
|
|
||||||
KeysByIdUsage(id uint64, requiredUsage byte) []Key
|
|
||||||
// DecryptionKeys returns all private keys that are valid for
|
|
||||||
// decryption.
|
|
||||||
DecryptionKeys() []Key
|
|
||||||
}
|
|
||||||
|
|
||||||
// primaryIdentity returns the Identity marked as primary or the first identity
|
|
||||||
// if none are so marked.
|
|
||||||
func (e *Entity) primaryIdentity() *Identity {
|
|
||||||
var firstIdentity *Identity
|
|
||||||
for _, ident := range e.Identities {
|
|
||||||
if firstIdentity == nil {
|
|
||||||
firstIdentity = ident
|
|
||||||
}
|
|
||||||
if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
|
|
||||||
return ident
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return firstIdentity
|
|
||||||
}
|
|
||||||
|
|
||||||
// encryptionKey returns the best candidate Key for encrypting a message to the
|
|
||||||
// given Entity.
|
|
||||||
func (e *Entity) encryptionKey(now time.Time) (Key, bool) {
|
|
||||||
candidateSubkey := -1
|
|
||||||
|
|
||||||
// Iterate the keys to find the newest key
|
|
||||||
var maxTime time.Time
|
|
||||||
for i, subkey := range e.Subkeys {
|
|
||||||
if subkey.Sig.FlagsValid &&
|
|
||||||
subkey.Sig.FlagEncryptCommunications &&
|
|
||||||
subkey.PublicKey.PubKeyAlgo.CanEncrypt() &&
|
|
||||||
!subkey.Sig.KeyExpired(now) &&
|
|
||||||
(maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) {
|
|
||||||
candidateSubkey = i
|
|
||||||
maxTime = subkey.Sig.CreationTime
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if candidateSubkey != -1 {
|
|
||||||
subkey := e.Subkeys[candidateSubkey]
|
|
||||||
return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we don't have any candidate subkeys for encryption and
|
|
||||||
// the primary key doesn't have any usage metadata then we
|
|
||||||
// assume that the primary key is ok. Or, if the primary key is
|
|
||||||
// marked as ok to encrypt to, then we can obviously use it.
|
|
||||||
i := e.primaryIdentity()
|
|
||||||
if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications &&
|
|
||||||
e.PrimaryKey.PubKeyAlgo.CanEncrypt() &&
|
|
||||||
!i.SelfSignature.KeyExpired(now) {
|
|
||||||
return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// This Entity appears to be signing only.
|
|
||||||
return Key{}, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// signingKey return the best candidate Key for signing a message with this
|
|
||||||
// Entity.
|
|
||||||
func (e *Entity) signingKey(now time.Time) (Key, bool) {
|
|
||||||
candidateSubkey := -1
|
|
||||||
|
|
||||||
for i, subkey := range e.Subkeys {
|
|
||||||
if subkey.Sig.FlagsValid &&
|
|
||||||
subkey.Sig.FlagSign &&
|
|
||||||
subkey.PublicKey.PubKeyAlgo.CanSign() &&
|
|
||||||
!subkey.Sig.KeyExpired(now) {
|
|
||||||
candidateSubkey = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if candidateSubkey != -1 {
|
|
||||||
subkey := e.Subkeys[candidateSubkey]
|
|
||||||
return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have no candidate subkey then we assume that it's ok to sign
|
|
||||||
// with the primary key.
|
|
||||||
i := e.primaryIdentity()
|
|
||||||
if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign &&
|
|
||||||
!i.SelfSignature.KeyExpired(now) {
|
|
||||||
return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true
|
|
||||||
}
|
|
||||||
|
|
||||||
return Key{}, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// An EntityList contains one or more Entities.
|
|
||||||
type EntityList []*Entity
|
|
||||||
|
|
||||||
// KeysById returns the set of keys that have the given key id.
|
|
||||||
func (el EntityList) KeysById(id uint64) (keys []Key) {
|
|
||||||
for _, e := range el {
|
|
||||||
if e.PrimaryKey.KeyId == id {
|
|
||||||
var selfSig *packet.Signature
|
|
||||||
for _, ident := range e.Identities {
|
|
||||||
if selfSig == nil {
|
|
||||||
selfSig = ident.SelfSignature
|
|
||||||
} else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
|
|
||||||
selfSig = ident.SelfSignature
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig})
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, subKey := range e.Subkeys {
|
|
||||||
if subKey.PublicKey.KeyId == id {
|
|
||||||
keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// KeysByIdAndUsage returns the set of keys with the given id that also meet
|
|
||||||
// the key usage given by requiredUsage. The requiredUsage is expressed as
|
|
||||||
// the bitwise-OR of packet.KeyFlag* values.
|
|
||||||
func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) {
|
|
||||||
for _, key := range el.KeysById(id) {
|
|
||||||
if len(key.Entity.Revocations) > 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if key.SelfSignature.RevocationReason != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if key.SelfSignature.FlagsValid && requiredUsage != 0 {
|
|
||||||
var usage byte
|
|
||||||
if key.SelfSignature.FlagCertify {
|
|
||||||
usage |= packet.KeyFlagCertify
|
|
||||||
}
|
|
||||||
if key.SelfSignature.FlagSign {
|
|
||||||
usage |= packet.KeyFlagSign
|
|
||||||
}
|
|
||||||
if key.SelfSignature.FlagEncryptCommunications {
|
|
||||||
usage |= packet.KeyFlagEncryptCommunications
|
|
||||||
}
|
|
||||||
if key.SelfSignature.FlagEncryptStorage {
|
|
||||||
usage |= packet.KeyFlagEncryptStorage
|
|
||||||
}
|
|
||||||
if usage&requiredUsage != requiredUsage {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
keys = append(keys, key)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptionKeys returns all private keys that are valid for decryption.
|
|
||||||
func (el EntityList) DecryptionKeys() (keys []Key) {
|
|
||||||
for _, e := range el {
|
|
||||||
for _, subKey := range e.Subkeys {
|
|
||||||
if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) {
|
|
||||||
keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
|
|
||||||
func ReadArmoredKeyRing(r io.Reader) (EntityList, error) {
|
|
||||||
block, err := armor.Decode(r)
|
|
||||||
if err == io.EOF {
|
|
||||||
return nil, errors.InvalidArgumentError("no armored data found")
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if block.Type != PublicKeyType && block.Type != PrivateKeyType {
|
|
||||||
return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ReadKeyRing(block.Body)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadKeyRing reads one or more public/private keys. Unsupported keys are
|
|
||||||
// ignored as long as at least a single valid key is found.
|
|
||||||
func ReadKeyRing(r io.Reader) (el EntityList, err error) {
|
|
||||||
packets := packet.NewReader(r)
|
|
||||||
var lastUnsupportedError error
|
|
||||||
|
|
||||||
for {
|
|
||||||
var e *Entity
|
|
||||||
e, err = ReadEntity(packets)
|
|
||||||
if err != nil {
|
|
||||||
// TODO: warn about skipped unsupported/unreadable keys
|
|
||||||
if _, ok := err.(errors.UnsupportedError); ok {
|
|
||||||
lastUnsupportedError = err
|
|
||||||
err = readToNextPublicKey(packets)
|
|
||||||
} else if _, ok := err.(errors.StructuralError); ok {
|
|
||||||
// Skip unreadable, badly-formatted keys
|
|
||||||
lastUnsupportedError = err
|
|
||||||
err = readToNextPublicKey(packets)
|
|
||||||
}
|
|
||||||
if err == io.EOF {
|
|
||||||
err = nil
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
el = nil
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
el = append(el, e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(el) == 0 && err == nil {
|
|
||||||
err = lastUnsupportedError
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// readToNextPublicKey reads packets until the start of the entity and leaves
|
|
||||||
// the first packet of the new entity in the Reader.
|
|
||||||
func readToNextPublicKey(packets *packet.Reader) (err error) {
|
|
||||||
var p packet.Packet
|
|
||||||
for {
|
|
||||||
p, err = packets.Next()
|
|
||||||
if err == io.EOF {
|
|
||||||
return
|
|
||||||
} else if err != nil {
|
|
||||||
if _, ok := err.(errors.UnsupportedError); ok {
|
|
||||||
err = nil
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey {
|
|
||||||
packets.Unread(p)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadEntity reads an entity (public key, identities, subkeys etc) from the
|
|
||||||
// given Reader.
|
|
||||||
func ReadEntity(packets *packet.Reader) (*Entity, error) {
|
|
||||||
e := new(Entity)
|
|
||||||
e.Identities = make(map[string]*Identity)
|
|
||||||
|
|
||||||
p, err := packets.Next()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var ok bool
|
|
||||||
if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
|
|
||||||
if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
|
|
||||||
packets.Unread(p)
|
|
||||||
return nil, errors.StructuralError("first packet was not a public/private key")
|
|
||||||
} else {
|
|
||||||
e.PrimaryKey = &e.PrivateKey.PublicKey
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !e.PrimaryKey.PubKeyAlgo.CanSign() {
|
|
||||||
return nil, errors.StructuralError("primary key cannot be used for signatures")
|
|
||||||
}
|
|
||||||
|
|
||||||
var current *Identity
|
|
||||||
var revocations []*packet.Signature
|
|
||||||
EachPacket:
|
|
||||||
for {
|
|
||||||
p, err := packets.Next()
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
} else if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch pkt := p.(type) {
|
|
||||||
case *packet.UserId:
|
|
||||||
current = new(Identity)
|
|
||||||
current.Name = pkt.Id
|
|
||||||
current.UserId = pkt
|
|
||||||
e.Identities[pkt.Id] = current
|
|
||||||
|
|
||||||
for {
|
|
||||||
p, err = packets.Next()
|
|
||||||
if err == io.EOF {
|
|
||||||
return nil, io.ErrUnexpectedEOF
|
|
||||||
} else if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
sig, ok := p.(*packet.Signature)
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.StructuralError("user ID packet not followed by self-signature")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId {
|
|
||||||
if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil {
|
|
||||||
return nil, errors.StructuralError("user ID self-signature invalid: " + err.Error())
|
|
||||||
}
|
|
||||||
current.SelfSignature = sig
|
|
||||||
break
|
|
||||||
}
|
|
||||||
current.Signatures = append(current.Signatures, sig)
|
|
||||||
}
|
|
||||||
case *packet.Signature:
|
|
||||||
if pkt.SigType == packet.SigTypeKeyRevocation {
|
|
||||||
revocations = append(revocations, pkt)
|
|
||||||
} else if pkt.SigType == packet.SigTypeDirectSignature {
|
|
||||||
// TODO: RFC4880 5.2.1 permits signatures
|
|
||||||
// directly on keys (eg. to bind additional
|
|
||||||
// revocation keys).
|
|
||||||
} else if current == nil {
|
|
||||||
return nil, errors.StructuralError("signature packet found before user id packet")
|
|
||||||
} else {
|
|
||||||
current.Signatures = append(current.Signatures, pkt)
|
|
||||||
}
|
|
||||||
case *packet.PrivateKey:
|
|
||||||
if pkt.IsSubkey == false {
|
|
||||||
packets.Unread(p)
|
|
||||||
break EachPacket
|
|
||||||
}
|
|
||||||
err = addSubkey(e, packets, &pkt.PublicKey, pkt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
case *packet.PublicKey:
|
|
||||||
if pkt.IsSubkey == false {
|
|
||||||
packets.Unread(p)
|
|
||||||
break EachPacket
|
|
||||||
}
|
|
||||||
err = addSubkey(e, packets, pkt, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// we ignore unknown packets
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(e.Identities) == 0 {
|
|
||||||
return nil, errors.StructuralError("entity without any identities")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, revocation := range revocations {
|
|
||||||
err = e.PrimaryKey.VerifyRevocationSignature(revocation)
|
|
||||||
if err == nil {
|
|
||||||
e.Revocations = append(e.Revocations, revocation)
|
|
||||||
} else {
|
|
||||||
// TODO: RFC 4880 5.2.3.15 defines revocation keys.
|
|
||||||
return nil, errors.StructuralError("revocation signature signed by alternate key")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return e, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error {
|
|
||||||
var subKey Subkey
|
|
||||||
subKey.PublicKey = pub
|
|
||||||
subKey.PrivateKey = priv
|
|
||||||
p, err := packets.Next()
|
|
||||||
if err == io.EOF {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return errors.StructuralError("subkey signature invalid: " + err.Error())
|
|
||||||
}
|
|
||||||
var ok bool
|
|
||||||
subKey.Sig, ok = p.(*packet.Signature)
|
|
||||||
if !ok {
|
|
||||||
return errors.StructuralError("subkey packet not followed by signature")
|
|
||||||
}
|
|
||||||
if subKey.Sig.SigType != packet.SigTypeSubkeyBinding && subKey.Sig.SigType != packet.SigTypeSubkeyRevocation {
|
|
||||||
return errors.StructuralError("subkey signature with wrong type")
|
|
||||||
}
|
|
||||||
err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, subKey.Sig)
|
|
||||||
if err != nil {
|
|
||||||
return errors.StructuralError("subkey signature invalid: " + err.Error())
|
|
||||||
}
|
|
||||||
e.Subkeys = append(e.Subkeys, subKey)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultRSAKeyBits = 2048
|
|
||||||
|
|
||||||
// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a
|
|
||||||
// single identity composed of the given full name, comment and email, any of
|
|
||||||
// which may be empty but must not contain any of "()<>\x00".
|
|
||||||
// If config is nil, sensible defaults will be used.
|
|
||||||
func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) {
|
|
||||||
currentTime := config.Now()
|
|
||||||
|
|
||||||
bits := defaultRSAKeyBits
|
|
||||||
if config != nil && config.RSABits != 0 {
|
|
||||||
bits = config.RSABits
|
|
||||||
}
|
|
||||||
|
|
||||||
uid := packet.NewUserId(name, comment, email)
|
|
||||||
if uid == nil {
|
|
||||||
return nil, errors.InvalidArgumentError("user id field contained invalid characters")
|
|
||||||
}
|
|
||||||
signingPriv, err := rsa.GenerateKey(config.Random(), bits)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
encryptingPriv, err := rsa.GenerateKey(config.Random(), bits)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
e := &Entity{
|
|
||||||
PrimaryKey: packet.NewRSAPublicKey(currentTime, &signingPriv.PublicKey),
|
|
||||||
PrivateKey: packet.NewRSAPrivateKey(currentTime, signingPriv),
|
|
||||||
Identities: make(map[string]*Identity),
|
|
||||||
}
|
|
||||||
isPrimaryId := true
|
|
||||||
e.Identities[uid.Id] = &Identity{
|
|
||||||
Name: uid.Name,
|
|
||||||
UserId: uid,
|
|
||||||
SelfSignature: &packet.Signature{
|
|
||||||
CreationTime: currentTime,
|
|
||||||
SigType: packet.SigTypePositiveCert,
|
|
||||||
PubKeyAlgo: packet.PubKeyAlgoRSA,
|
|
||||||
Hash: config.Hash(),
|
|
||||||
IsPrimaryId: &isPrimaryId,
|
|
||||||
FlagsValid: true,
|
|
||||||
FlagSign: true,
|
|
||||||
FlagCertify: true,
|
|
||||||
IssuerKeyId: &e.PrimaryKey.KeyId,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
e.Subkeys = make([]Subkey, 1)
|
|
||||||
e.Subkeys[0] = Subkey{
|
|
||||||
PublicKey: packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey),
|
|
||||||
PrivateKey: packet.NewRSAPrivateKey(currentTime, encryptingPriv),
|
|
||||||
Sig: &packet.Signature{
|
|
||||||
CreationTime: currentTime,
|
|
||||||
SigType: packet.SigTypeSubkeyBinding,
|
|
||||||
PubKeyAlgo: packet.PubKeyAlgoRSA,
|
|
||||||
Hash: config.Hash(),
|
|
||||||
FlagsValid: true,
|
|
||||||
FlagEncryptStorage: true,
|
|
||||||
FlagEncryptCommunications: true,
|
|
||||||
IssuerKeyId: &e.PrimaryKey.KeyId,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
e.Subkeys[0].PublicKey.IsSubkey = true
|
|
||||||
e.Subkeys[0].PrivateKey.IsSubkey = true
|
|
||||||
|
|
||||||
return e, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SerializePrivate serializes an Entity, including private key material, to
|
|
||||||
// the given Writer. For now, it must only be used on an Entity returned from
|
|
||||||
// NewEntity.
|
|
||||||
// If config is nil, sensible defaults will be used.
|
|
||||||
func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) {
|
|
||||||
err = e.PrivateKey.Serialize(w)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, ident := range e.Identities {
|
|
||||||
err = ident.UserId.Serialize(w)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = ident.SelfSignature.Serialize(w)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, subkey := range e.Subkeys {
|
|
||||||
err = subkey.PrivateKey.Serialize(w)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = subkey.Sig.Serialize(w)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize writes the public part of the given Entity to w. (No private
|
|
||||||
// key material will be output).
|
|
||||||
func (e *Entity) Serialize(w io.Writer) error {
|
|
||||||
err := e.PrimaryKey.Serialize(w)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, ident := range e.Identities {
|
|
||||||
err = ident.UserId.Serialize(w)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = ident.SelfSignature.Serialize(w)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, sig := range ident.Signatures {
|
|
||||||
err = sig.Serialize(w)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, subkey := range e.Subkeys {
|
|
||||||
err = subkey.PublicKey.Serialize(w)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = subkey.Sig.Serialize(w)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignIdentity adds a signature to e, from signer, attesting that identity is
|
|
||||||
// associated with e. The provided identity must already be an element of
|
|
||||||
// e.Identities and the private key of signer must have been decrypted if
|
|
||||||
// necessary.
|
|
||||||
// If config is nil, sensible defaults will be used.
|
|
||||||
func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error {
|
|
||||||
if signer.PrivateKey == nil {
|
|
||||||
return errors.InvalidArgumentError("signing Entity must have a private key")
|
|
||||||
}
|
|
||||||
if signer.PrivateKey.Encrypted {
|
|
||||||
return errors.InvalidArgumentError("signing Entity's private key must be decrypted")
|
|
||||||
}
|
|
||||||
ident, ok := e.Identities[identity]
|
|
||||||
if !ok {
|
|
||||||
return errors.InvalidArgumentError("given identity string not found in Entity")
|
|
||||||
}
|
|
||||||
|
|
||||||
sig := &packet.Signature{
|
|
||||||
SigType: packet.SigTypeGenericCert,
|
|
||||||
PubKeyAlgo: signer.PrivateKey.PubKeyAlgo,
|
|
||||||
Hash: config.Hash(),
|
|
||||||
CreationTime: config.Now(),
|
|
||||||
IssuerKeyId: &signer.PrivateKey.KeyId,
|
|
||||||
}
|
|
||||||
if err := sig.SignUserId(identity, e.PrimaryKey, signer.PrivateKey, config); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
ident.Signatures = append(ident.Signatures, sig)
|
|
||||||
return nil
|
|
||||||
}
|
|
370
vendor/golang.org/x/crypto/openpgp/keys_test.go
generated
vendored
370
vendor/golang.org/x/crypto/openpgp/keys_test.go
generated
vendored
File diff suppressed because one or more lines are too long
123
vendor/golang.org/x/crypto/openpgp/packet/compressed.go
generated
vendored
123
vendor/golang.org/x/crypto/openpgp/packet/compressed.go
generated
vendored
|
@ -1,123 +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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"compress/bzip2"
|
|
||||||
"compress/flate"
|
|
||||||
"compress/zlib"
|
|
||||||
"golang.org/x/crypto/openpgp/errors"
|
|
||||||
"io"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Compressed represents a compressed OpenPGP packet. The decompressed contents
|
|
||||||
// will contain more OpenPGP packets. See RFC 4880, section 5.6.
|
|
||||||
type Compressed struct {
|
|
||||||
Body io.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
NoCompression = flate.NoCompression
|
|
||||||
BestSpeed = flate.BestSpeed
|
|
||||||
BestCompression = flate.BestCompression
|
|
||||||
DefaultCompression = flate.DefaultCompression
|
|
||||||
)
|
|
||||||
|
|
||||||
// CompressionConfig contains compressor configuration settings.
|
|
||||||
type CompressionConfig struct {
|
|
||||||
// Level is the compression level to use. It must be set to
|
|
||||||
// between -1 and 9, with -1 causing the compressor to use the
|
|
||||||
// default compression level, 0 causing the compressor to use
|
|
||||||
// no compression and 1 to 9 representing increasing (better,
|
|
||||||
// slower) compression levels. If Level is less than -1 or
|
|
||||||
// more then 9, a non-nil error will be returned during
|
|
||||||
// encryption. See the constants above for convenient common
|
|
||||||
// settings for Level.
|
|
||||||
Level int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Compressed) parse(r io.Reader) error {
|
|
||||||
var buf [1]byte
|
|
||||||
_, err := readFull(r, buf[:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch buf[0] {
|
|
||||||
case 1:
|
|
||||||
c.Body = flate.NewReader(r)
|
|
||||||
case 2:
|
|
||||||
c.Body, err = zlib.NewReader(r)
|
|
||||||
case 3:
|
|
||||||
c.Body = bzip2.NewReader(r)
|
|
||||||
default:
|
|
||||||
err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0])))
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// compressedWriterCloser represents the serialized compression stream
|
|
||||||
// header and the compressor. Its Close() method ensures that both the
|
|
||||||
// compressor and serialized stream header are closed. Its Write()
|
|
||||||
// method writes to the compressor.
|
|
||||||
type compressedWriteCloser struct {
|
|
||||||
sh io.Closer // Stream Header
|
|
||||||
c io.WriteCloser // Compressor
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cwc compressedWriteCloser) Write(p []byte) (int, error) {
|
|
||||||
return cwc.c.Write(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cwc compressedWriteCloser) Close() (err error) {
|
|
||||||
err = cwc.c.Close()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return cwc.sh.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SerializeCompressed serializes a compressed data packet to w and
|
|
||||||
// returns a WriteCloser to which the literal data packets themselves
|
|
||||||
// can be written and which MUST be closed on completion. If cc is
|
|
||||||
// nil, sensible defaults will be used to configure the compression
|
|
||||||
// algorithm.
|
|
||||||
func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) {
|
|
||||||
compressed, err := serializeStreamHeader(w, packetTypeCompressed)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = compressed.Write([]byte{uint8(algo)})
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
level := DefaultCompression
|
|
||||||
if cc != nil {
|
|
||||||
level = cc.Level
|
|
||||||
}
|
|
||||||
|
|
||||||
var compressor io.WriteCloser
|
|
||||||
switch algo {
|
|
||||||
case CompressionZIP:
|
|
||||||
compressor, err = flate.NewWriter(compressed, level)
|
|
||||||
case CompressionZLIB:
|
|
||||||
compressor, err = zlib.NewWriterLevel(compressed, level)
|
|
||||||
default:
|
|
||||||
s := strconv.Itoa(int(algo))
|
|
||||||
err = errors.UnsupportedError("Unsupported compression algorithm: " + s)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
literaldata = compressedWriteCloser{compressed, compressor}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
41
vendor/golang.org/x/crypto/openpgp/packet/compressed_test.go
generated
vendored
41
vendor/golang.org/x/crypto/openpgp/packet/compressed_test.go
generated
vendored
|
@ -1,41 +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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCompressed(t *testing.T) {
|
|
||||||
packet, err := Read(readerFromHex(compressedHex))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("failed to read Compressed: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c, ok := packet.(*Compressed)
|
|
||||||
if !ok {
|
|
||||||
t.Error("didn't find Compressed packet")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
contents, err := ioutil.ReadAll(c.Body)
|
|
||||||
if err != nil && err != io.EOF {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
expected, _ := hex.DecodeString(compressedExpectedHex)
|
|
||||||
if !bytes.Equal(expected, contents) {
|
|
||||||
t.Errorf("got:%x want:%x", contents, expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const compressedHex = "a3013b2d90c4e02b72e25f727e5e496a5e49b11e1700"
|
|
||||||
const compressedExpectedHex = "cb1062004d14c8fe636f6e74656e74732e0a"
|
|
91
vendor/golang.org/x/crypto/openpgp/packet/config.go
generated
vendored
91
vendor/golang.org/x/crypto/openpgp/packet/config.go
generated
vendored
|
@ -1,91 +0,0 @@
|
||||||
// Copyright 2012 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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto"
|
|
||||||
"crypto/rand"
|
|
||||||
"io"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Config collects a number of parameters along with sensible defaults.
|
|
||||||
// A nil *Config is valid and results in all default values.
|
|
||||||
type Config struct {
|
|
||||||
// Rand provides the source of entropy.
|
|
||||||
// If nil, the crypto/rand Reader is used.
|
|
||||||
Rand io.Reader
|
|
||||||
// DefaultHash is the default hash function to be used.
|
|
||||||
// If zero, SHA-256 is used.
|
|
||||||
DefaultHash crypto.Hash
|
|
||||||
// DefaultCipher is the cipher to be used.
|
|
||||||
// If zero, AES-128 is used.
|
|
||||||
DefaultCipher CipherFunction
|
|
||||||
// Time returns the current time as the number of seconds since the
|
|
||||||
// epoch. If Time is nil, time.Now is used.
|
|
||||||
Time func() time.Time
|
|
||||||
// DefaultCompressionAlgo is the compression algorithm to be
|
|
||||||
// applied to the plaintext before encryption. If zero, no
|
|
||||||
// compression is done.
|
|
||||||
DefaultCompressionAlgo CompressionAlgo
|
|
||||||
// CompressionConfig configures the compression settings.
|
|
||||||
CompressionConfig *CompressionConfig
|
|
||||||
// S2KCount is only used for symmetric encryption. It
|
|
||||||
// determines the strength of the passphrase stretching when
|
|
||||||
// the said passphrase is hashed to produce a key. S2KCount
|
|
||||||
// should be between 1024 and 65011712, inclusive. If Config
|
|
||||||
// is nil or S2KCount is 0, the value 65536 used. Not all
|
|
||||||
// values in the above range can be represented. S2KCount will
|
|
||||||
// be rounded up to the next representable value if it cannot
|
|
||||||
// be encoded exactly. When set, it is strongly encrouraged to
|
|
||||||
// use a value that is at least 65536. See RFC 4880 Section
|
|
||||||
// 3.7.1.3.
|
|
||||||
S2KCount int
|
|
||||||
// RSABits is the number of bits in new RSA keys made with NewEntity.
|
|
||||||
// If zero, then 2048 bit keys are created.
|
|
||||||
RSABits int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) Random() io.Reader {
|
|
||||||
if c == nil || c.Rand == nil {
|
|
||||||
return rand.Reader
|
|
||||||
}
|
|
||||||
return c.Rand
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) Hash() crypto.Hash {
|
|
||||||
if c == nil || uint(c.DefaultHash) == 0 {
|
|
||||||
return crypto.SHA256
|
|
||||||
}
|
|
||||||
return c.DefaultHash
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) Cipher() CipherFunction {
|
|
||||||
if c == nil || uint8(c.DefaultCipher) == 0 {
|
|
||||||
return CipherAES128
|
|
||||||
}
|
|
||||||
return c.DefaultCipher
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) Now() time.Time {
|
|
||||||
if c == nil || c.Time == nil {
|
|
||||||
return time.Now()
|
|
||||||
}
|
|
||||||
return c.Time()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) Compression() CompressionAlgo {
|
|
||||||
if c == nil {
|
|
||||||
return CompressionNone
|
|
||||||
}
|
|
||||||
return c.DefaultCompressionAlgo
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) PasswordHashIterations() int {
|
|
||||||
if c == nil || c.S2KCount == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return c.S2KCount
|
|
||||||
}
|
|
199
vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go
generated
vendored
199
vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go
generated
vendored
|
@ -1,199 +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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rsa"
|
|
||||||
"encoding/binary"
|
|
||||||
"io"
|
|
||||||
"math/big"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp/elgamal"
|
|
||||||
"golang.org/x/crypto/openpgp/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
const encryptedKeyVersion = 3
|
|
||||||
|
|
||||||
// EncryptedKey represents a public-key encrypted session key. See RFC 4880,
|
|
||||||
// section 5.1.
|
|
||||||
type EncryptedKey struct {
|
|
||||||
KeyId uint64
|
|
||||||
Algo PublicKeyAlgorithm
|
|
||||||
CipherFunc CipherFunction // only valid after a successful Decrypt
|
|
||||||
Key []byte // only valid after a successful Decrypt
|
|
||||||
|
|
||||||
encryptedMPI1, encryptedMPI2 parsedMPI
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *EncryptedKey) parse(r io.Reader) (err error) {
|
|
||||||
var buf [10]byte
|
|
||||||
_, err = readFull(r, buf[:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if buf[0] != encryptedKeyVersion {
|
|
||||||
return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0])))
|
|
||||||
}
|
|
||||||
e.KeyId = binary.BigEndian.Uint64(buf[1:9])
|
|
||||||
e.Algo = PublicKeyAlgorithm(buf[9])
|
|
||||||
switch e.Algo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
|
||||||
e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r)
|
|
||||||
case PubKeyAlgoElGamal:
|
|
||||||
e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r)
|
|
||||||
}
|
|
||||||
_, err = consumeAll(r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func checksumKeyMaterial(key []byte) uint16 {
|
|
||||||
var checksum uint16
|
|
||||||
for _, v := range key {
|
|
||||||
checksum += uint16(v)
|
|
||||||
}
|
|
||||||
return checksum
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrypt decrypts an encrypted session key with the given private key. The
|
|
||||||
// private key must have been decrypted first.
|
|
||||||
// If config is nil, sensible defaults will be used.
|
|
||||||
func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
|
|
||||||
var err error
|
|
||||||
var b []byte
|
|
||||||
|
|
||||||
// TODO(agl): use session key decryption routines here to avoid
|
|
||||||
// padding oracle attacks.
|
|
||||||
switch priv.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
|
||||||
b, err = rsa.DecryptPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1.bytes)
|
|
||||||
case PubKeyAlgoElGamal:
|
|
||||||
c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes)
|
|
||||||
c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes)
|
|
||||||
b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2)
|
|
||||||
default:
|
|
||||||
err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
e.CipherFunc = CipherFunction(b[0])
|
|
||||||
e.Key = b[1 : len(b)-2]
|
|
||||||
expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1])
|
|
||||||
checksum := checksumKeyMaterial(e.Key)
|
|
||||||
if checksum != expectedChecksum {
|
|
||||||
return errors.StructuralError("EncryptedKey checksum incorrect")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize writes the encrypted key packet, e, to w.
|
|
||||||
func (e *EncryptedKey) Serialize(w io.Writer) error {
|
|
||||||
var mpiLen int
|
|
||||||
switch e.Algo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
|
||||||
mpiLen = 2 + len(e.encryptedMPI1.bytes)
|
|
||||||
case PubKeyAlgoElGamal:
|
|
||||||
mpiLen = 2 + len(e.encryptedMPI1.bytes) + 2 + len(e.encryptedMPI2.bytes)
|
|
||||||
default:
|
|
||||||
return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo)))
|
|
||||||
}
|
|
||||||
|
|
||||||
serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen)
|
|
||||||
|
|
||||||
w.Write([]byte{encryptedKeyVersion})
|
|
||||||
binary.Write(w, binary.BigEndian, e.KeyId)
|
|
||||||
w.Write([]byte{byte(e.Algo)})
|
|
||||||
|
|
||||||
switch e.Algo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
|
||||||
writeMPIs(w, e.encryptedMPI1)
|
|
||||||
case PubKeyAlgoElGamal:
|
|
||||||
writeMPIs(w, e.encryptedMPI1, e.encryptedMPI2)
|
|
||||||
default:
|
|
||||||
panic("internal error")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SerializeEncryptedKey serializes an encrypted key packet to w that contains
|
|
||||||
// key, encrypted to pub.
|
|
||||||
// If config is nil, sensible defaults will be used.
|
|
||||||
func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error {
|
|
||||||
var buf [10]byte
|
|
||||||
buf[0] = encryptedKeyVersion
|
|
||||||
binary.BigEndian.PutUint64(buf[1:9], pub.KeyId)
|
|
||||||
buf[9] = byte(pub.PubKeyAlgo)
|
|
||||||
|
|
||||||
keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */)
|
|
||||||
keyBlock[0] = byte(cipherFunc)
|
|
||||||
copy(keyBlock[1:], key)
|
|
||||||
checksum := checksumKeyMaterial(key)
|
|
||||||
keyBlock[1+len(key)] = byte(checksum >> 8)
|
|
||||||
keyBlock[1+len(key)+1] = byte(checksum)
|
|
||||||
|
|
||||||
switch pub.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
|
|
||||||
return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
|
|
||||||
case PubKeyAlgoElGamal:
|
|
||||||
return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
|
|
||||||
case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
|
|
||||||
return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error {
|
|
||||||
cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock)
|
|
||||||
if err != nil {
|
|
||||||
return errors.InvalidArgumentError("RSA encryption failed: " + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText)
|
|
||||||
|
|
||||||
err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = w.Write(header[:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return writeMPI(w, 8*uint16(len(cipherText)), cipherText)
|
|
||||||
}
|
|
||||||
|
|
||||||
func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error {
|
|
||||||
c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock)
|
|
||||||
if err != nil {
|
|
||||||
return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
packetLen := 10 /* header length */
|
|
||||||
packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8
|
|
||||||
packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8
|
|
||||||
|
|
||||||
err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = w.Write(header[:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = writeBig(w, c1)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return writeBig(w, c2)
|
|
||||||
}
|
|
146
vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go
generated
vendored
146
vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go
generated
vendored
|
@ -1,146 +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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/rsa"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"math/big"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func bigFromBase10(s string) *big.Int {
|
|
||||||
b, ok := new(big.Int).SetString(s, 10)
|
|
||||||
if !ok {
|
|
||||||
panic("bigFromBase10 failed")
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
var encryptedKeyPub = rsa.PublicKey{
|
|
||||||
E: 65537,
|
|
||||||
N: bigFromBase10("115804063926007623305902631768113868327816898845124614648849934718568541074358183759250136204762053879858102352159854352727097033322663029387610959884180306668628526686121021235757016368038585212410610742029286439607686208110250133174279811431933746643015923132833417396844716207301518956640020862630546868823"),
|
|
||||||
}
|
|
||||||
|
|
||||||
var encryptedKeyRSAPriv = &rsa.PrivateKey{
|
|
||||||
PublicKey: encryptedKeyPub,
|
|
||||||
D: bigFromBase10("32355588668219869544751561565313228297765464314098552250409557267371233892496951383426602439009993875125222579159850054973310859166139474359774543943714622292329487391199285040721944491839695981199720170366763547754915493640685849961780092241140181198779299712578774460837139360803883139311171713302987058393"),
|
|
||||||
}
|
|
||||||
|
|
||||||
var encryptedKeyPriv = &PrivateKey{
|
|
||||||
PublicKey: PublicKey{
|
|
||||||
PubKeyAlgo: PubKeyAlgoRSA,
|
|
||||||
},
|
|
||||||
PrivateKey: encryptedKeyRSAPriv,
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDecryptingEncryptedKey(t *testing.T) {
|
|
||||||
const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8"
|
|
||||||
const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b"
|
|
||||||
|
|
||||||
p, err := Read(readerFromHex(encryptedKeyHex))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error from Read: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ek, ok := p.(*EncryptedKey)
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("didn't parse an EncryptedKey, got %#v", p)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA {
|
|
||||||
t.Errorf("unexpected EncryptedKey contents: %#v", ek)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ek.Decrypt(encryptedKeyPriv, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error from Decrypt: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if ek.CipherFunc != CipherAES256 {
|
|
||||||
t.Errorf("unexpected EncryptedKey contents: %#v", ek)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
keyHex := fmt.Sprintf("%x", ek.Key)
|
|
||||||
if keyHex != expectedKeyHex {
|
|
||||||
t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEncryptingEncryptedKey(t *testing.T) {
|
|
||||||
key := []byte{1, 2, 3, 4}
|
|
||||||
const expectedKeyHex = "01020304"
|
|
||||||
const keyId = 42
|
|
||||||
|
|
||||||
pub := &PublicKey{
|
|
||||||
PublicKey: &encryptedKeyPub,
|
|
||||||
KeyId: keyId,
|
|
||||||
PubKeyAlgo: PubKeyAlgoRSAEncryptOnly,
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
err := SerializeEncryptedKey(buf, pub, CipherAES128, key, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error writing encrypted key packet: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
p, err := Read(buf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error from Read: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ek, ok := p.(*EncryptedKey)
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("didn't parse an EncryptedKey, got %#v", p)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if ek.KeyId != keyId || ek.Algo != PubKeyAlgoRSAEncryptOnly {
|
|
||||||
t.Errorf("unexpected EncryptedKey contents: %#v", ek)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ek.Decrypt(encryptedKeyPriv, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error from Decrypt: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if ek.CipherFunc != CipherAES128 {
|
|
||||||
t.Errorf("unexpected EncryptedKey contents: %#v", ek)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
keyHex := fmt.Sprintf("%x", ek.Key)
|
|
||||||
if keyHex != expectedKeyHex {
|
|
||||||
t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSerializingEncryptedKey(t *testing.T) {
|
|
||||||
const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8"
|
|
||||||
|
|
||||||
p, err := Read(readerFromHex(encryptedKeyHex))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("error from Read: %s", err)
|
|
||||||
}
|
|
||||||
ek, ok := p.(*EncryptedKey)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("didn't parse an EncryptedKey, got %#v", p)
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
ek.Serialize(&buf)
|
|
||||||
|
|
||||||
if bufHex := hex.EncodeToString(buf.Bytes()); bufHex != encryptedKeyHex {
|
|
||||||
t.Fatalf("serialization of encrypted key differed from original. Original was %s, but reserialized as %s", encryptedKeyHex, bufHex)
|
|
||||||
}
|
|
||||||
}
|
|
89
vendor/golang.org/x/crypto/openpgp/packet/literal.go
generated
vendored
89
vendor/golang.org/x/crypto/openpgp/packet/literal.go
generated
vendored
|
@ -1,89 +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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LiteralData represents an encrypted file. See RFC 4880, section 5.9.
|
|
||||||
type LiteralData struct {
|
|
||||||
IsBinary bool
|
|
||||||
FileName string
|
|
||||||
Time uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined.
|
|
||||||
Body io.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
// ForEyesOnly returns whether the contents of the LiteralData have been marked
|
|
||||||
// as especially sensitive.
|
|
||||||
func (l *LiteralData) ForEyesOnly() bool {
|
|
||||||
return l.FileName == "_CONSOLE"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LiteralData) parse(r io.Reader) (err error) {
|
|
||||||
var buf [256]byte
|
|
||||||
|
|
||||||
_, err = readFull(r, buf[:2])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
l.IsBinary = buf[0] == 'b'
|
|
||||||
fileNameLen := int(buf[1])
|
|
||||||
|
|
||||||
_, err = readFull(r, buf[:fileNameLen])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
l.FileName = string(buf[:fileNameLen])
|
|
||||||
|
|
||||||
_, err = readFull(r, buf[:4])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
l.Time = binary.BigEndian.Uint32(buf[:4])
|
|
||||||
l.Body = r
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SerializeLiteral serializes a literal data packet to w and returns a
|
|
||||||
// WriteCloser to which the data itself can be written and which MUST be closed
|
|
||||||
// on completion. The fileName is truncated to 255 bytes.
|
|
||||||
func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) {
|
|
||||||
var buf [4]byte
|
|
||||||
buf[0] = 't'
|
|
||||||
if isBinary {
|
|
||||||
buf[0] = 'b'
|
|
||||||
}
|
|
||||||
if len(fileName) > 255 {
|
|
||||||
fileName = fileName[:255]
|
|
||||||
}
|
|
||||||
buf[1] = byte(len(fileName))
|
|
||||||
|
|
||||||
inner, err := serializeStreamHeader(w, packetTypeLiteralData)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = inner.Write(buf[:2])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = inner.Write([]byte(fileName))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
binary.BigEndian.PutUint32(buf[:], time)
|
|
||||||
_, err = inner.Write(buf[:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
plaintext = inner
|
|
||||||
return
|
|
||||||
}
|
|
143
vendor/golang.org/x/crypto/openpgp/packet/ocfb.go
generated
vendored
143
vendor/golang.org/x/crypto/openpgp/packet/ocfb.go
generated
vendored
|
@ -1,143 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9
|
|
||||||
|
|
||||||
package packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/cipher"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ocfbEncrypter struct {
|
|
||||||
b cipher.Block
|
|
||||||
fre []byte
|
|
||||||
outUsed int
|
|
||||||
}
|
|
||||||
|
|
||||||
// An OCFBResyncOption determines if the "resynchronization step" of OCFB is
|
|
||||||
// performed.
|
|
||||||
type OCFBResyncOption bool
|
|
||||||
|
|
||||||
const (
|
|
||||||
OCFBResync OCFBResyncOption = true
|
|
||||||
OCFBNoResync OCFBResyncOption = false
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's
|
|
||||||
// cipher feedback mode using the given cipher.Block, and an initial amount of
|
|
||||||
// ciphertext. randData must be random bytes and be the same length as the
|
|
||||||
// cipher.Block's block size. Resync determines if the "resynchronization step"
|
|
||||||
// from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on
|
|
||||||
// this point.
|
|
||||||
func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) {
|
|
||||||
blockSize := block.BlockSize()
|
|
||||||
if len(randData) != blockSize {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
x := &ocfbEncrypter{
|
|
||||||
b: block,
|
|
||||||
fre: make([]byte, blockSize),
|
|
||||||
outUsed: 0,
|
|
||||||
}
|
|
||||||
prefix := make([]byte, blockSize+2)
|
|
||||||
|
|
||||||
block.Encrypt(x.fre, x.fre)
|
|
||||||
for i := 0; i < blockSize; i++ {
|
|
||||||
prefix[i] = randData[i] ^ x.fre[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
block.Encrypt(x.fre, prefix[:blockSize])
|
|
||||||
prefix[blockSize] = x.fre[0] ^ randData[blockSize-2]
|
|
||||||
prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1]
|
|
||||||
|
|
||||||
if resync {
|
|
||||||
block.Encrypt(x.fre, prefix[2:])
|
|
||||||
} else {
|
|
||||||
x.fre[0] = prefix[blockSize]
|
|
||||||
x.fre[1] = prefix[blockSize+1]
|
|
||||||
x.outUsed = 2
|
|
||||||
}
|
|
||||||
return x, prefix
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) {
|
|
||||||
for i := 0; i < len(src); i++ {
|
|
||||||
if x.outUsed == len(x.fre) {
|
|
||||||
x.b.Encrypt(x.fre, x.fre)
|
|
||||||
x.outUsed = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
x.fre[x.outUsed] ^= src[i]
|
|
||||||
dst[i] = x.fre[x.outUsed]
|
|
||||||
x.outUsed++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type ocfbDecrypter struct {
|
|
||||||
b cipher.Block
|
|
||||||
fre []byte
|
|
||||||
outUsed int
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's
|
|
||||||
// cipher feedback mode using the given cipher.Block. Prefix must be the first
|
|
||||||
// blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's
|
|
||||||
// block size. If an incorrect key is detected then nil is returned. On
|
|
||||||
// successful exit, blockSize+2 bytes of decrypted data are written into
|
|
||||||
// prefix. Resync determines if the "resynchronization step" from RFC 4880,
|
|
||||||
// 13.9 step 7 is performed. Different parts of OpenPGP vary on this point.
|
|
||||||
func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream {
|
|
||||||
blockSize := block.BlockSize()
|
|
||||||
if len(prefix) != blockSize+2 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
x := &ocfbDecrypter{
|
|
||||||
b: block,
|
|
||||||
fre: make([]byte, blockSize),
|
|
||||||
outUsed: 0,
|
|
||||||
}
|
|
||||||
prefixCopy := make([]byte, len(prefix))
|
|
||||||
copy(prefixCopy, prefix)
|
|
||||||
|
|
||||||
block.Encrypt(x.fre, x.fre)
|
|
||||||
for i := 0; i < blockSize; i++ {
|
|
||||||
prefixCopy[i] ^= x.fre[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
block.Encrypt(x.fre, prefix[:blockSize])
|
|
||||||
prefixCopy[blockSize] ^= x.fre[0]
|
|
||||||
prefixCopy[blockSize+1] ^= x.fre[1]
|
|
||||||
|
|
||||||
if prefixCopy[blockSize-2] != prefixCopy[blockSize] ||
|
|
||||||
prefixCopy[blockSize-1] != prefixCopy[blockSize+1] {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if resync {
|
|
||||||
block.Encrypt(x.fre, prefix[2:])
|
|
||||||
} else {
|
|
||||||
x.fre[0] = prefix[blockSize]
|
|
||||||
x.fre[1] = prefix[blockSize+1]
|
|
||||||
x.outUsed = 2
|
|
||||||
}
|
|
||||||
copy(prefix, prefixCopy)
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) {
|
|
||||||
for i := 0; i < len(src); i++ {
|
|
||||||
if x.outUsed == len(x.fre) {
|
|
||||||
x.b.Encrypt(x.fre, x.fre)
|
|
||||||
x.outUsed = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
c := src[i]
|
|
||||||
dst[i] = x.fre[x.outUsed] ^ src[i]
|
|
||||||
x.fre[x.outUsed] = c
|
|
||||||
x.outUsed++
|
|
||||||
}
|
|
||||||
}
|
|
46
vendor/golang.org/x/crypto/openpgp/packet/ocfb_test.go
generated
vendored
46
vendor/golang.org/x/crypto/openpgp/packet/ocfb_test.go
generated
vendored
|
@ -1,46 +0,0 @@
|
||||||
// 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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/aes"
|
|
||||||
"crypto/rand"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var commonKey128 = []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}
|
|
||||||
|
|
||||||
func testOCFB(t *testing.T, resync OCFBResyncOption) {
|
|
||||||
block, err := aes.NewCipher(commonKey128)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
plaintext := []byte("this is the plaintext, which is long enough to span several blocks.")
|
|
||||||
randData := make([]byte, block.BlockSize())
|
|
||||||
rand.Reader.Read(randData)
|
|
||||||
ocfb, prefix := NewOCFBEncrypter(block, randData, resync)
|
|
||||||
ciphertext := make([]byte, len(plaintext))
|
|
||||||
ocfb.XORKeyStream(ciphertext, plaintext)
|
|
||||||
|
|
||||||
ocfbdec := NewOCFBDecrypter(block, prefix, resync)
|
|
||||||
if ocfbdec == nil {
|
|
||||||
t.Errorf("NewOCFBDecrypter failed (resync: %t)", resync)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
plaintextCopy := make([]byte, len(plaintext))
|
|
||||||
ocfbdec.XORKeyStream(plaintextCopy, ciphertext)
|
|
||||||
|
|
||||||
if !bytes.Equal(plaintextCopy, plaintext) {
|
|
||||||
t.Errorf("got: %x, want: %x (resync: %t)", plaintextCopy, plaintext, resync)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOCFB(t *testing.T) {
|
|
||||||
testOCFB(t, OCFBNoResync)
|
|
||||||
testOCFB(t, OCFBResync)
|
|
||||||
}
|
|
73
vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go
generated
vendored
73
vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go
generated
vendored
|
@ -1,73 +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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto"
|
|
||||||
"encoding/binary"
|
|
||||||
"golang.org/x/crypto/openpgp/errors"
|
|
||||||
"golang.org/x/crypto/openpgp/s2k"
|
|
||||||
"io"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// OnePassSignature represents a one-pass signature packet. See RFC 4880,
|
|
||||||
// section 5.4.
|
|
||||||
type OnePassSignature struct {
|
|
||||||
SigType SignatureType
|
|
||||||
Hash crypto.Hash
|
|
||||||
PubKeyAlgo PublicKeyAlgorithm
|
|
||||||
KeyId uint64
|
|
||||||
IsLast bool
|
|
||||||
}
|
|
||||||
|
|
||||||
const onePassSignatureVersion = 3
|
|
||||||
|
|
||||||
func (ops *OnePassSignature) parse(r io.Reader) (err error) {
|
|
||||||
var buf [13]byte
|
|
||||||
|
|
||||||
_, err = readFull(r, buf[:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if buf[0] != onePassSignatureVersion {
|
|
||||||
err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0])))
|
|
||||||
}
|
|
||||||
|
|
||||||
var ok bool
|
|
||||||
ops.Hash, ok = s2k.HashIdToHash(buf[2])
|
|
||||||
if !ok {
|
|
||||||
return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2])))
|
|
||||||
}
|
|
||||||
|
|
||||||
ops.SigType = SignatureType(buf[1])
|
|
||||||
ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3])
|
|
||||||
ops.KeyId = binary.BigEndian.Uint64(buf[4:12])
|
|
||||||
ops.IsLast = buf[12] != 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize marshals the given OnePassSignature to w.
|
|
||||||
func (ops *OnePassSignature) Serialize(w io.Writer) error {
|
|
||||||
var buf [13]byte
|
|
||||||
buf[0] = onePassSignatureVersion
|
|
||||||
buf[1] = uint8(ops.SigType)
|
|
||||||
var ok bool
|
|
||||||
buf[2], ok = s2k.HashToHashId(ops.Hash)
|
|
||||||
if !ok {
|
|
||||||
return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash)))
|
|
||||||
}
|
|
||||||
buf[3] = uint8(ops.PubKeyAlgo)
|
|
||||||
binary.BigEndian.PutUint64(buf[4:12], ops.KeyId)
|
|
||||||
if ops.IsLast {
|
|
||||||
buf[12] = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := serializeHeader(w, packetTypeOnePassSignature, len(buf)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err := w.Write(buf[:])
|
|
||||||
return err
|
|
||||||
}
|
|
162
vendor/golang.org/x/crypto/openpgp/packet/opaque.go
generated
vendored
162
vendor/golang.org/x/crypto/openpgp/packet/opaque.go
generated
vendored
|
@ -1,162 +0,0 @@
|
||||||
// Copyright 2012 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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is
|
|
||||||
// useful for splitting and storing the original packet contents separately,
|
|
||||||
// handling unsupported packet types or accessing parts of the packet not yet
|
|
||||||
// implemented by this package.
|
|
||||||
type OpaquePacket struct {
|
|
||||||
// Packet type
|
|
||||||
Tag uint8
|
|
||||||
// Reason why the packet was parsed opaquely
|
|
||||||
Reason error
|
|
||||||
// Binary contents of the packet data
|
|
||||||
Contents []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (op *OpaquePacket) parse(r io.Reader) (err error) {
|
|
||||||
op.Contents, err = ioutil.ReadAll(r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize marshals the packet to a writer in its original form, including
|
|
||||||
// the packet header.
|
|
||||||
func (op *OpaquePacket) Serialize(w io.Writer) (err error) {
|
|
||||||
err = serializeHeader(w, packetType(op.Tag), len(op.Contents))
|
|
||||||
if err == nil {
|
|
||||||
_, err = w.Write(op.Contents)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse attempts to parse the opaque contents into a structure supported by
|
|
||||||
// this package. If the packet is not known then the result will be another
|
|
||||||
// OpaquePacket.
|
|
||||||
func (op *OpaquePacket) Parse() (p Packet, err error) {
|
|
||||||
hdr := bytes.NewBuffer(nil)
|
|
||||||
err = serializeHeader(hdr, packetType(op.Tag), len(op.Contents))
|
|
||||||
if err != nil {
|
|
||||||
op.Reason = err
|
|
||||||
return op, err
|
|
||||||
}
|
|
||||||
p, err = Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents)))
|
|
||||||
if err != nil {
|
|
||||||
op.Reason = err
|
|
||||||
p = op
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpaqueReader reads OpaquePackets from an io.Reader.
|
|
||||||
type OpaqueReader struct {
|
|
||||||
r io.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewOpaqueReader(r io.Reader) *OpaqueReader {
|
|
||||||
return &OpaqueReader{r: r}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the next OpaquePacket.
|
|
||||||
func (or *OpaqueReader) Next() (op *OpaquePacket, err error) {
|
|
||||||
tag, _, contents, err := readHeader(or.r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
op = &OpaquePacket{Tag: uint8(tag), Reason: err}
|
|
||||||
err = op.parse(contents)
|
|
||||||
if err != nil {
|
|
||||||
consumeAll(contents)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpaqueSubpacket represents an unparsed OpenPGP subpacket,
|
|
||||||
// as found in signature and user attribute packets.
|
|
||||||
type OpaqueSubpacket struct {
|
|
||||||
SubType uint8
|
|
||||||
Contents []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpaqueSubpackets extracts opaque, unparsed OpenPGP subpackets from
|
|
||||||
// their byte representation.
|
|
||||||
func OpaqueSubpackets(contents []byte) (result []*OpaqueSubpacket, err error) {
|
|
||||||
var (
|
|
||||||
subHeaderLen int
|
|
||||||
subPacket *OpaqueSubpacket
|
|
||||||
)
|
|
||||||
for len(contents) > 0 {
|
|
||||||
subHeaderLen, subPacket, err = nextSubpacket(contents)
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
result = append(result, subPacket)
|
|
||||||
contents = contents[subHeaderLen+len(subPacket.Contents):]
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacket, err error) {
|
|
||||||
// RFC 4880, section 5.2.3.1
|
|
||||||
var subLen uint32
|
|
||||||
if len(contents) < 1 {
|
|
||||||
goto Truncated
|
|
||||||
}
|
|
||||||
subPacket = &OpaqueSubpacket{}
|
|
||||||
switch {
|
|
||||||
case contents[0] < 192:
|
|
||||||
subHeaderLen = 2 // 1 length byte, 1 subtype byte
|
|
||||||
if len(contents) < subHeaderLen {
|
|
||||||
goto Truncated
|
|
||||||
}
|
|
||||||
subLen = uint32(contents[0])
|
|
||||||
contents = contents[1:]
|
|
||||||
case contents[0] < 255:
|
|
||||||
subHeaderLen = 3 // 2 length bytes, 1 subtype
|
|
||||||
if len(contents) < subHeaderLen {
|
|
||||||
goto Truncated
|
|
||||||
}
|
|
||||||
subLen = uint32(contents[0]-192)<<8 + uint32(contents[1]) + 192
|
|
||||||
contents = contents[2:]
|
|
||||||
default:
|
|
||||||
subHeaderLen = 6 // 5 length bytes, 1 subtype
|
|
||||||
if len(contents) < subHeaderLen {
|
|
||||||
goto Truncated
|
|
||||||
}
|
|
||||||
subLen = uint32(contents[1])<<24 |
|
|
||||||
uint32(contents[2])<<16 |
|
|
||||||
uint32(contents[3])<<8 |
|
|
||||||
uint32(contents[4])
|
|
||||||
contents = contents[5:]
|
|
||||||
}
|
|
||||||
if subLen > uint32(len(contents)) || subLen == 0 {
|
|
||||||
goto Truncated
|
|
||||||
}
|
|
||||||
subPacket.SubType = contents[0]
|
|
||||||
subPacket.Contents = contents[1:subLen]
|
|
||||||
return
|
|
||||||
Truncated:
|
|
||||||
err = errors.StructuralError("subpacket truncated")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (osp *OpaqueSubpacket) Serialize(w io.Writer) (err error) {
|
|
||||||
buf := make([]byte, 6)
|
|
||||||
n := serializeSubpacketLength(buf, len(osp.Contents)+1)
|
|
||||||
buf[n] = osp.SubType
|
|
||||||
if _, err = w.Write(buf[:n+1]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = w.Write(osp.Contents)
|
|
||||||
return
|
|
||||||
}
|
|
67
vendor/golang.org/x/crypto/openpgp/packet/opaque_test.go
generated
vendored
67
vendor/golang.org/x/crypto/openpgp/packet/opaque_test.go
generated
vendored
|
@ -1,67 +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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"io"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Test packet.Read error handling in OpaquePacket.Parse,
|
|
||||||
// which attempts to re-read an OpaquePacket as a supported
|
|
||||||
// Packet type.
|
|
||||||
func TestOpaqueParseReason(t *testing.T) {
|
|
||||||
buf, err := hex.DecodeString(UnsupportedKeyHex)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
or := NewOpaqueReader(bytes.NewBuffer(buf))
|
|
||||||
count := 0
|
|
||||||
badPackets := 0
|
|
||||||
var uid *UserId
|
|
||||||
for {
|
|
||||||
op, err := or.Next()
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
} else if err != nil {
|
|
||||||
t.Errorf("#%d: opaque read error: %v", count, err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
// try to parse opaque packet
|
|
||||||
p, err := op.Parse()
|
|
||||||
switch pkt := p.(type) {
|
|
||||||
case *UserId:
|
|
||||||
uid = pkt
|
|
||||||
case *OpaquePacket:
|
|
||||||
// If an OpaquePacket can't re-parse, packet.Read
|
|
||||||
// certainly had its reasons.
|
|
||||||
if pkt.Reason == nil {
|
|
||||||
t.Errorf("#%d: opaque packet, no reason", count)
|
|
||||||
} else {
|
|
||||||
badPackets++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
|
|
||||||
const expectedBad = 3
|
|
||||||
// Test post-conditions, make sure we actually parsed packets as expected.
|
|
||||||
if badPackets != expectedBad {
|
|
||||||
t.Errorf("unexpected # unparseable packets: %d (want %d)", badPackets, expectedBad)
|
|
||||||
}
|
|
||||||
if uid == nil {
|
|
||||||
t.Errorf("failed to find expected UID in unsupported keyring")
|
|
||||||
} else if uid.Id != "Armin M. Warda <warda@nephilim.ruhr.de>" {
|
|
||||||
t.Errorf("unexpected UID: %v", uid.Id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This key material has public key and signature packet versions modified to
|
|
||||||
// an unsupported value (1), so that trying to parse the OpaquePacket to
|
|
||||||
// a typed packet will get an error. It also contains a GnuPG trust packet.
|
|
||||||
// (Created with: od -An -t x1 pubring.gpg | xargs | sed 's/ //g')
|
|
||||||
const UnsupportedKeyHex = `988d012e7a18a20000010400d6ac00d92b89c1f4396c243abb9b76d2e9673ad63483291fed88e22b82e255e441c078c6abbbf7d2d195e50b62eeaa915b85b0ec20c225ce2c64c167cacb6e711daf2e45da4a8356a059b8160e3b3628ac0dd8437b31f06d53d6e8ea4214d4a26406a6b63e1001406ef23e0bb3069fac9a99a91f77dfafd5de0f188a5da5e3c9000511b42741726d696e204d2e205761726461203c7761726461406e657068696c696d2e727568722e64653e8900950105102e8936c705d1eb399e58489901013f0e03ff5a0c4f421e34fcfa388129166420c08cd76987bcdec6f01bd0271459a85cc22048820dd4e44ac2c7d23908d540f54facf1b36b0d9c20488781ce9dca856531e76e2e846826e9951338020a03a09b57aa5faa82e9267458bd76105399885ac35af7dc1cbb6aaed7c39e1039f3b5beda2c0e916bd38560509bab81235d1a0ead83b0020000`
|
|
539
vendor/golang.org/x/crypto/openpgp/packet/packet.go
generated
vendored
539
vendor/golang.org/x/crypto/openpgp/packet/packet.go
generated
vendored
|
@ -1,539 +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 packet implements parsing and serialization of OpenPGP packets, as
|
|
||||||
// specified in RFC 4880.
|
|
||||||
package packet // import "golang.org/x/crypto/openpgp/packet"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"crypto/aes"
|
|
||||||
"crypto/cipher"
|
|
||||||
"crypto/des"
|
|
||||||
"golang.org/x/crypto/cast5"
|
|
||||||
"golang.org/x/crypto/openpgp/errors"
|
|
||||||
"io"
|
|
||||||
"math/big"
|
|
||||||
)
|
|
||||||
|
|
||||||
// readFull is the same as io.ReadFull except that reading zero bytes returns
|
|
||||||
// ErrUnexpectedEOF rather than EOF.
|
|
||||||
func readFull(r io.Reader, buf []byte) (n int, err error) {
|
|
||||||
n, err = io.ReadFull(r, buf)
|
|
||||||
if err == io.EOF {
|
|
||||||
err = io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2.
|
|
||||||
func readLength(r io.Reader) (length int64, isPartial bool, err error) {
|
|
||||||
var buf [4]byte
|
|
||||||
_, err = readFull(r, buf[:1])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch {
|
|
||||||
case buf[0] < 192:
|
|
||||||
length = int64(buf[0])
|
|
||||||
case buf[0] < 224:
|
|
||||||
length = int64(buf[0]-192) << 8
|
|
||||||
_, err = readFull(r, buf[0:1])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
length += int64(buf[0]) + 192
|
|
||||||
case buf[0] < 255:
|
|
||||||
length = int64(1) << (buf[0] & 0x1f)
|
|
||||||
isPartial = true
|
|
||||||
default:
|
|
||||||
_, err = readFull(r, buf[0:4])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
length = int64(buf[0])<<24 |
|
|
||||||
int64(buf[1])<<16 |
|
|
||||||
int64(buf[2])<<8 |
|
|
||||||
int64(buf[3])
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths.
|
|
||||||
// The continuation lengths are parsed and removed from the stream and EOF is
|
|
||||||
// returned at the end of the packet. See RFC 4880, section 4.2.2.4.
|
|
||||||
type partialLengthReader struct {
|
|
||||||
r io.Reader
|
|
||||||
remaining int64
|
|
||||||
isPartial bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *partialLengthReader) Read(p []byte) (n int, err error) {
|
|
||||||
for r.remaining == 0 {
|
|
||||||
if !r.isPartial {
|
|
||||||
return 0, io.EOF
|
|
||||||
}
|
|
||||||
r.remaining, r.isPartial, err = readLength(r.r)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toRead := int64(len(p))
|
|
||||||
if toRead > r.remaining {
|
|
||||||
toRead = r.remaining
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err = r.r.Read(p[:int(toRead)])
|
|
||||||
r.remaining -= int64(n)
|
|
||||||
if n < int(toRead) && err == io.EOF {
|
|
||||||
err = io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// partialLengthWriter writes a stream of data using OpenPGP partial lengths.
|
|
||||||
// See RFC 4880, section 4.2.2.4.
|
|
||||||
type partialLengthWriter struct {
|
|
||||||
w io.WriteCloser
|
|
||||||
lengthByte [1]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *partialLengthWriter) Write(p []byte) (n int, err error) {
|
|
||||||
for len(p) > 0 {
|
|
||||||
for power := uint(14); power < 32; power-- {
|
|
||||||
l := 1 << power
|
|
||||||
if len(p) >= l {
|
|
||||||
w.lengthByte[0] = 224 + uint8(power)
|
|
||||||
_, err = w.w.Write(w.lengthByte[:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var m int
|
|
||||||
m, err = w.w.Write(p[:l])
|
|
||||||
n += m
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p = p[l:]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *partialLengthWriter) Close() error {
|
|
||||||
w.lengthByte[0] = 0
|
|
||||||
_, err := w.w.Write(w.lengthByte[:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return w.w.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the
|
|
||||||
// underlying Reader returns EOF before the limit has been reached.
|
|
||||||
type spanReader struct {
|
|
||||||
r io.Reader
|
|
||||||
n int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *spanReader) Read(p []byte) (n int, err error) {
|
|
||||||
if l.n <= 0 {
|
|
||||||
return 0, io.EOF
|
|
||||||
}
|
|
||||||
if int64(len(p)) > l.n {
|
|
||||||
p = p[0:l.n]
|
|
||||||
}
|
|
||||||
n, err = l.r.Read(p)
|
|
||||||
l.n -= int64(n)
|
|
||||||
if l.n > 0 && err == io.EOF {
|
|
||||||
err = io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// readHeader parses a packet header and returns an io.Reader which will return
|
|
||||||
// the contents of the packet. See RFC 4880, section 4.2.
|
|
||||||
func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) {
|
|
||||||
var buf [4]byte
|
|
||||||
_, err = io.ReadFull(r, buf[:1])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if buf[0]&0x80 == 0 {
|
|
||||||
err = errors.StructuralError("tag byte does not have MSB set")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if buf[0]&0x40 == 0 {
|
|
||||||
// Old format packet
|
|
||||||
tag = packetType((buf[0] & 0x3f) >> 2)
|
|
||||||
lengthType := buf[0] & 3
|
|
||||||
if lengthType == 3 {
|
|
||||||
length = -1
|
|
||||||
contents = r
|
|
||||||
return
|
|
||||||
}
|
|
||||||
lengthBytes := 1 << lengthType
|
|
||||||
_, err = readFull(r, buf[0:lengthBytes])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := 0; i < lengthBytes; i++ {
|
|
||||||
length <<= 8
|
|
||||||
length |= int64(buf[i])
|
|
||||||
}
|
|
||||||
contents = &spanReader{r, length}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// New format packet
|
|
||||||
tag = packetType(buf[0] & 0x3f)
|
|
||||||
length, isPartial, err := readLength(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if isPartial {
|
|
||||||
contents = &partialLengthReader{
|
|
||||||
remaining: length,
|
|
||||||
isPartial: true,
|
|
||||||
r: r,
|
|
||||||
}
|
|
||||||
length = -1
|
|
||||||
} else {
|
|
||||||
contents = &spanReader{r, length}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section
|
|
||||||
// 4.2.
|
|
||||||
func serializeHeader(w io.Writer, ptype packetType, length int) (err error) {
|
|
||||||
var buf [6]byte
|
|
||||||
var n int
|
|
||||||
|
|
||||||
buf[0] = 0x80 | 0x40 | byte(ptype)
|
|
||||||
if length < 192 {
|
|
||||||
buf[1] = byte(length)
|
|
||||||
n = 2
|
|
||||||
} else if length < 8384 {
|
|
||||||
length -= 192
|
|
||||||
buf[1] = 192 + byte(length>>8)
|
|
||||||
buf[2] = byte(length)
|
|
||||||
n = 3
|
|
||||||
} else {
|
|
||||||
buf[1] = 255
|
|
||||||
buf[2] = byte(length >> 24)
|
|
||||||
buf[3] = byte(length >> 16)
|
|
||||||
buf[4] = byte(length >> 8)
|
|
||||||
buf[5] = byte(length)
|
|
||||||
n = 6
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = w.Write(buf[:n])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// serializeStreamHeader writes an OpenPGP packet header to w where the
|
|
||||||
// length of the packet is unknown. It returns a io.WriteCloser which can be
|
|
||||||
// used to write the contents of the packet. See RFC 4880, section 4.2.
|
|
||||||
func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) {
|
|
||||||
var buf [1]byte
|
|
||||||
buf[0] = 0x80 | 0x40 | byte(ptype)
|
|
||||||
_, err = w.Write(buf[:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
out = &partialLengthWriter{w: w}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Packet represents an OpenPGP packet. Users are expected to try casting
|
|
||||||
// instances of this interface to specific packet types.
|
|
||||||
type Packet interface {
|
|
||||||
parse(io.Reader) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// consumeAll reads from the given Reader until error, returning the number of
|
|
||||||
// bytes read.
|
|
||||||
func consumeAll(r io.Reader) (n int64, err error) {
|
|
||||||
var m int
|
|
||||||
var buf [1024]byte
|
|
||||||
|
|
||||||
for {
|
|
||||||
m, err = r.Read(buf[:])
|
|
||||||
n += int64(m)
|
|
||||||
if err == io.EOF {
|
|
||||||
err = nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
// packetType represents the numeric ids of the different OpenPGP packet types. See
|
|
||||||
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2
|
|
||||||
type packetType uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
packetTypeEncryptedKey packetType = 1
|
|
||||||
packetTypeSignature packetType = 2
|
|
||||||
packetTypeSymmetricKeyEncrypted packetType = 3
|
|
||||||
packetTypeOnePassSignature packetType = 4
|
|
||||||
packetTypePrivateKey packetType = 5
|
|
||||||
packetTypePublicKey packetType = 6
|
|
||||||
packetTypePrivateSubkey packetType = 7
|
|
||||||
packetTypeCompressed packetType = 8
|
|
||||||
packetTypeSymmetricallyEncrypted packetType = 9
|
|
||||||
packetTypeLiteralData packetType = 11
|
|
||||||
packetTypeUserId packetType = 13
|
|
||||||
packetTypePublicSubkey packetType = 14
|
|
||||||
packetTypeUserAttribute packetType = 17
|
|
||||||
packetTypeSymmetricallyEncryptedMDC packetType = 18
|
|
||||||
)
|
|
||||||
|
|
||||||
// peekVersion detects the version of a public key packet about to
|
|
||||||
// be read. A bufio.Reader at the original position of the io.Reader
|
|
||||||
// is returned.
|
|
||||||
func peekVersion(r io.Reader) (bufr *bufio.Reader, ver byte, err error) {
|
|
||||||
bufr = bufio.NewReader(r)
|
|
||||||
var verBuf []byte
|
|
||||||
if verBuf, err = bufr.Peek(1); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ver = verBuf[0]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read reads a single OpenPGP packet from the given io.Reader. If there is an
|
|
||||||
// error parsing a packet, the whole packet is consumed from the input.
|
|
||||||
func Read(r io.Reader) (p Packet, err error) {
|
|
||||||
tag, _, contents, err := readHeader(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch tag {
|
|
||||||
case packetTypeEncryptedKey:
|
|
||||||
p = new(EncryptedKey)
|
|
||||||
case packetTypeSignature:
|
|
||||||
var version byte
|
|
||||||
// Detect signature version
|
|
||||||
if contents, version, err = peekVersion(contents); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if version < 4 {
|
|
||||||
p = new(SignatureV3)
|
|
||||||
} else {
|
|
||||||
p = new(Signature)
|
|
||||||
}
|
|
||||||
case packetTypeSymmetricKeyEncrypted:
|
|
||||||
p = new(SymmetricKeyEncrypted)
|
|
||||||
case packetTypeOnePassSignature:
|
|
||||||
p = new(OnePassSignature)
|
|
||||||
case packetTypePrivateKey, packetTypePrivateSubkey:
|
|
||||||
pk := new(PrivateKey)
|
|
||||||
if tag == packetTypePrivateSubkey {
|
|
||||||
pk.IsSubkey = true
|
|
||||||
}
|
|
||||||
p = pk
|
|
||||||
case packetTypePublicKey, packetTypePublicSubkey:
|
|
||||||
var version byte
|
|
||||||
if contents, version, err = peekVersion(contents); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
isSubkey := tag == packetTypePublicSubkey
|
|
||||||
if version < 4 {
|
|
||||||
p = &PublicKeyV3{IsSubkey: isSubkey}
|
|
||||||
} else {
|
|
||||||
p = &PublicKey{IsSubkey: isSubkey}
|
|
||||||
}
|
|
||||||
case packetTypeCompressed:
|
|
||||||
p = new(Compressed)
|
|
||||||
case packetTypeSymmetricallyEncrypted:
|
|
||||||
p = new(SymmetricallyEncrypted)
|
|
||||||
case packetTypeLiteralData:
|
|
||||||
p = new(LiteralData)
|
|
||||||
case packetTypeUserId:
|
|
||||||
p = new(UserId)
|
|
||||||
case packetTypeUserAttribute:
|
|
||||||
p = new(UserAttribute)
|
|
||||||
case packetTypeSymmetricallyEncryptedMDC:
|
|
||||||
se := new(SymmetricallyEncrypted)
|
|
||||||
se.MDC = true
|
|
||||||
p = se
|
|
||||||
default:
|
|
||||||
err = errors.UnknownPacketTypeError(tag)
|
|
||||||
}
|
|
||||||
if p != nil {
|
|
||||||
err = p.parse(contents)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
consumeAll(contents)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignatureType represents the different semantic meanings of an OpenPGP
|
|
||||||
// signature. See RFC 4880, section 5.2.1.
|
|
||||||
type SignatureType uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
SigTypeBinary SignatureType = 0
|
|
||||||
SigTypeText = 1
|
|
||||||
SigTypeGenericCert = 0x10
|
|
||||||
SigTypePersonaCert = 0x11
|
|
||||||
SigTypeCasualCert = 0x12
|
|
||||||
SigTypePositiveCert = 0x13
|
|
||||||
SigTypeSubkeyBinding = 0x18
|
|
||||||
SigTypePrimaryKeyBinding = 0x19
|
|
||||||
SigTypeDirectSignature = 0x1F
|
|
||||||
SigTypeKeyRevocation = 0x20
|
|
||||||
SigTypeSubkeyRevocation = 0x28
|
|
||||||
)
|
|
||||||
|
|
||||||
// PublicKeyAlgorithm represents the different public key system specified for
|
|
||||||
// OpenPGP. See
|
|
||||||
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12
|
|
||||||
type PublicKeyAlgorithm uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
PubKeyAlgoRSA PublicKeyAlgorithm = 1
|
|
||||||
PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2
|
|
||||||
PubKeyAlgoRSASignOnly PublicKeyAlgorithm = 3
|
|
||||||
PubKeyAlgoElGamal PublicKeyAlgorithm = 16
|
|
||||||
PubKeyAlgoDSA PublicKeyAlgorithm = 17
|
|
||||||
// RFC 6637, Section 5.
|
|
||||||
PubKeyAlgoECDH PublicKeyAlgorithm = 18
|
|
||||||
PubKeyAlgoECDSA PublicKeyAlgorithm = 19
|
|
||||||
)
|
|
||||||
|
|
||||||
// CanEncrypt returns true if it's possible to encrypt a message to a public
|
|
||||||
// key of the given type.
|
|
||||||
func (pka PublicKeyAlgorithm) CanEncrypt() bool {
|
|
||||||
switch pka {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// CanSign returns true if it's possible for a public key of the given type to
|
|
||||||
// sign a message.
|
|
||||||
func (pka PublicKeyAlgorithm) CanSign() bool {
|
|
||||||
switch pka {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// CipherFunction represents the different block ciphers specified for OpenPGP. See
|
|
||||||
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13
|
|
||||||
type CipherFunction uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
Cipher3DES CipherFunction = 2
|
|
||||||
CipherCAST5 CipherFunction = 3
|
|
||||||
CipherAES128 CipherFunction = 7
|
|
||||||
CipherAES192 CipherFunction = 8
|
|
||||||
CipherAES256 CipherFunction = 9
|
|
||||||
)
|
|
||||||
|
|
||||||
// KeySize returns the key size, in bytes, of cipher.
|
|
||||||
func (cipher CipherFunction) KeySize() int {
|
|
||||||
switch cipher {
|
|
||||||
case Cipher3DES:
|
|
||||||
return 24
|
|
||||||
case CipherCAST5:
|
|
||||||
return cast5.KeySize
|
|
||||||
case CipherAES128:
|
|
||||||
return 16
|
|
||||||
case CipherAES192:
|
|
||||||
return 24
|
|
||||||
case CipherAES256:
|
|
||||||
return 32
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// blockSize returns the block size, in bytes, of cipher.
|
|
||||||
func (cipher CipherFunction) blockSize() int {
|
|
||||||
switch cipher {
|
|
||||||
case Cipher3DES:
|
|
||||||
return des.BlockSize
|
|
||||||
case CipherCAST5:
|
|
||||||
return 8
|
|
||||||
case CipherAES128, CipherAES192, CipherAES256:
|
|
||||||
return 16
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// new returns a fresh instance of the given cipher.
|
|
||||||
func (cipher CipherFunction) new(key []byte) (block cipher.Block) {
|
|
||||||
switch cipher {
|
|
||||||
case Cipher3DES:
|
|
||||||
block, _ = des.NewTripleDESCipher(key)
|
|
||||||
case CipherCAST5:
|
|
||||||
block, _ = cast5.NewCipher(key)
|
|
||||||
case CipherAES128, CipherAES192, CipherAES256:
|
|
||||||
block, _ = aes.NewCipher(key)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// readMPI reads a big integer from r. The bit length returned is the bit
|
|
||||||
// length that was specified in r. This is preserved so that the integer can be
|
|
||||||
// reserialized exactly.
|
|
||||||
func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) {
|
|
||||||
var buf [2]byte
|
|
||||||
_, err = readFull(r, buf[0:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
bitLength = uint16(buf[0])<<8 | uint16(buf[1])
|
|
||||||
numBytes := (int(bitLength) + 7) / 8
|
|
||||||
mpi = make([]byte, numBytes)
|
|
||||||
_, err = readFull(r, mpi)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// mpiLength returns the length of the given *big.Int when serialized as an
|
|
||||||
// MPI.
|
|
||||||
func mpiLength(n *big.Int) (mpiLengthInBytes int) {
|
|
||||||
mpiLengthInBytes = 2 /* MPI length */
|
|
||||||
mpiLengthInBytes += (n.BitLen() + 7) / 8
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeMPI serializes a big integer to w.
|
|
||||||
func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) {
|
|
||||||
_, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)})
|
|
||||||
if err == nil {
|
|
||||||
_, err = w.Write(mpiBytes)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeBig serializes a *big.Int to w.
|
|
||||||
func writeBig(w io.Writer, i *big.Int) error {
|
|
||||||
return writeMPI(w, uint16(i.BitLen()), i.Bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
// CompressionAlgo Represents the different compression algorithms
|
|
||||||
// supported by OpenPGP (except for BZIP2, which is not currently
|
|
||||||
// supported). See Section 9.3 of RFC 4880.
|
|
||||||
type CompressionAlgo uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
CompressionNone CompressionAlgo = 0
|
|
||||||
CompressionZIP CompressionAlgo = 1
|
|
||||||
CompressionZLIB CompressionAlgo = 2
|
|
||||||
)
|
|
255
vendor/golang.org/x/crypto/openpgp/packet/packet_test.go
generated
vendored
255
vendor/golang.org/x/crypto/openpgp/packet/packet_test.go
generated
vendored
|
@ -1,255 +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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"golang.org/x/crypto/openpgp/errors"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestReadFull(t *testing.T) {
|
|
||||||
var out [4]byte
|
|
||||||
|
|
||||||
b := bytes.NewBufferString("foo")
|
|
||||||
n, err := readFull(b, out[:3])
|
|
||||||
if n != 3 || err != nil {
|
|
||||||
t.Errorf("full read failed n:%d err:%s", n, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
b = bytes.NewBufferString("foo")
|
|
||||||
n, err = readFull(b, out[:4])
|
|
||||||
if n != 3 || err != io.ErrUnexpectedEOF {
|
|
||||||
t.Errorf("partial read failed n:%d err:%s", n, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
b = bytes.NewBuffer(nil)
|
|
||||||
n, err = readFull(b, out[:3])
|
|
||||||
if n != 0 || err != io.ErrUnexpectedEOF {
|
|
||||||
t.Errorf("empty read failed n:%d err:%s", n, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func readerFromHex(s string) io.Reader {
|
|
||||||
data, err := hex.DecodeString(s)
|
|
||||||
if err != nil {
|
|
||||||
panic("readerFromHex: bad input")
|
|
||||||
}
|
|
||||||
return bytes.NewBuffer(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
var readLengthTests = []struct {
|
|
||||||
hexInput string
|
|
||||||
length int64
|
|
||||||
isPartial bool
|
|
||||||
err error
|
|
||||||
}{
|
|
||||||
{"", 0, false, io.ErrUnexpectedEOF},
|
|
||||||
{"1f", 31, false, nil},
|
|
||||||
{"c0", 0, false, io.ErrUnexpectedEOF},
|
|
||||||
{"c101", 256 + 1 + 192, false, nil},
|
|
||||||
{"e0", 1, true, nil},
|
|
||||||
{"e1", 2, true, nil},
|
|
||||||
{"e2", 4, true, nil},
|
|
||||||
{"ff", 0, false, io.ErrUnexpectedEOF},
|
|
||||||
{"ff00", 0, false, io.ErrUnexpectedEOF},
|
|
||||||
{"ff0000", 0, false, io.ErrUnexpectedEOF},
|
|
||||||
{"ff000000", 0, false, io.ErrUnexpectedEOF},
|
|
||||||
{"ff00000000", 0, false, nil},
|
|
||||||
{"ff01020304", 16909060, false, nil},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReadLength(t *testing.T) {
|
|
||||||
for i, test := range readLengthTests {
|
|
||||||
length, isPartial, err := readLength(readerFromHex(test.hexInput))
|
|
||||||
if test.err != nil {
|
|
||||||
if err != test.err {
|
|
||||||
t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%d: unexpected error: %s", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if length != test.length || isPartial != test.isPartial {
|
|
||||||
t.Errorf("%d: bad result got:(%d,%t) want:(%d,%t)", i, length, isPartial, test.length, test.isPartial)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var partialLengthReaderTests = []struct {
|
|
||||||
hexInput string
|
|
||||||
err error
|
|
||||||
hexOutput string
|
|
||||||
}{
|
|
||||||
{"e0", io.ErrUnexpectedEOF, ""},
|
|
||||||
{"e001", io.ErrUnexpectedEOF, ""},
|
|
||||||
{"e0010102", nil, "0102"},
|
|
||||||
{"ff00000000", nil, ""},
|
|
||||||
{"e10102e1030400", nil, "01020304"},
|
|
||||||
{"e101", io.ErrUnexpectedEOF, ""},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPartialLengthReader(t *testing.T) {
|
|
||||||
for i, test := range partialLengthReaderTests {
|
|
||||||
r := &partialLengthReader{readerFromHex(test.hexInput), 0, true}
|
|
||||||
out, err := ioutil.ReadAll(r)
|
|
||||||
if test.err != nil {
|
|
||||||
if err != test.err {
|
|
||||||
t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%d: unexpected error: %s", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
got := fmt.Sprintf("%x", out)
|
|
||||||
if got != test.hexOutput {
|
|
||||||
t.Errorf("%d: got:%s want:%s", i, test.hexOutput, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var readHeaderTests = []struct {
|
|
||||||
hexInput string
|
|
||||||
structuralError bool
|
|
||||||
unexpectedEOF bool
|
|
||||||
tag int
|
|
||||||
length int64
|
|
||||||
hexOutput string
|
|
||||||
}{
|
|
||||||
{"", false, false, 0, 0, ""},
|
|
||||||
{"7f", true, false, 0, 0, ""},
|
|
||||||
|
|
||||||
// Old format headers
|
|
||||||
{"80", false, true, 0, 0, ""},
|
|
||||||
{"8001", false, true, 0, 1, ""},
|
|
||||||
{"800102", false, false, 0, 1, "02"},
|
|
||||||
{"81000102", false, false, 0, 1, "02"},
|
|
||||||
{"820000000102", false, false, 0, 1, "02"},
|
|
||||||
{"860000000102", false, false, 1, 1, "02"},
|
|
||||||
{"83010203", false, false, 0, -1, "010203"},
|
|
||||||
|
|
||||||
// New format headers
|
|
||||||
{"c0", false, true, 0, 0, ""},
|
|
||||||
{"c000", false, false, 0, 0, ""},
|
|
||||||
{"c00102", false, false, 0, 1, "02"},
|
|
||||||
{"c0020203", false, false, 0, 2, "0203"},
|
|
||||||
{"c00202", false, true, 0, 2, ""},
|
|
||||||
{"c3020203", false, false, 3, 2, "0203"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReadHeader(t *testing.T) {
|
|
||||||
for i, test := range readHeaderTests {
|
|
||||||
tag, length, contents, err := readHeader(readerFromHex(test.hexInput))
|
|
||||||
if test.structuralError {
|
|
||||||
if _, ok := err.(errors.StructuralError); ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
t.Errorf("%d: expected StructuralError, got:%s", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
if len(test.hexInput) == 0 && err == io.EOF {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !test.unexpectedEOF || err != io.ErrUnexpectedEOF {
|
|
||||||
t.Errorf("%d: unexpected error from readHeader: %s", i, err)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if int(tag) != test.tag || length != test.length {
|
|
||||||
t.Errorf("%d: got:(%d,%d) want:(%d,%d)", i, int(tag), length, test.tag, test.length)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(contents)
|
|
||||||
if err != nil {
|
|
||||||
if !test.unexpectedEOF || err != io.ErrUnexpectedEOF {
|
|
||||||
t.Errorf("%d: unexpected error from contents: %s", i, err)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if test.unexpectedEOF {
|
|
||||||
t.Errorf("%d: expected ErrUnexpectedEOF from contents but got no error", i)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
got := fmt.Sprintf("%x", body)
|
|
||||||
if got != test.hexOutput {
|
|
||||||
t.Errorf("%d: got:%s want:%s", i, got, test.hexOutput)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSerializeHeader(t *testing.T) {
|
|
||||||
tag := packetTypePublicKey
|
|
||||||
lengths := []int{0, 1, 2, 64, 192, 193, 8000, 8384, 8385, 10000}
|
|
||||||
|
|
||||||
for _, length := range lengths {
|
|
||||||
buf := bytes.NewBuffer(nil)
|
|
||||||
serializeHeader(buf, tag, length)
|
|
||||||
tag2, length2, _, err := readHeader(buf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("length %d, err: %s", length, err)
|
|
||||||
}
|
|
||||||
if tag2 != tag {
|
|
||||||
t.Errorf("length %d, tag incorrect (got %d, want %d)", length, tag2, tag)
|
|
||||||
}
|
|
||||||
if int(length2) != length {
|
|
||||||
t.Errorf("length %d, length incorrect (got %d)", length, length2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPartialLengths(t *testing.T) {
|
|
||||||
buf := bytes.NewBuffer(nil)
|
|
||||||
w := new(partialLengthWriter)
|
|
||||||
w.w = noOpCloser{buf}
|
|
||||||
|
|
||||||
const maxChunkSize = 64
|
|
||||||
|
|
||||||
var b [maxChunkSize]byte
|
|
||||||
var n uint8
|
|
||||||
for l := 1; l <= maxChunkSize; l++ {
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
b[i] = n
|
|
||||||
n++
|
|
||||||
}
|
|
||||||
m, err := w.Write(b[:l])
|
|
||||||
if m != l {
|
|
||||||
t.Errorf("short write got: %d want: %d", m, l)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error from write: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.Close()
|
|
||||||
|
|
||||||
want := (maxChunkSize * (maxChunkSize + 1)) / 2
|
|
||||||
copyBuf := bytes.NewBuffer(nil)
|
|
||||||
r := &partialLengthReader{buf, 0, true}
|
|
||||||
m, err := io.Copy(copyBuf, r)
|
|
||||||
if m != int64(want) {
|
|
||||||
t.Errorf("short copy got: %d want: %d", m, want)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error from copy: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
copyBytes := copyBuf.Bytes()
|
|
||||||
for i := 0; i < want; i++ {
|
|
||||||
if copyBytes[i] != uint8(i) {
|
|
||||||
t.Errorf("bad pattern in copy at %d", i)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
362
vendor/golang.org/x/crypto/openpgp/packet/private_key.go
generated
vendored
362
vendor/golang.org/x/crypto/openpgp/packet/private_key.go
generated
vendored
|
@ -1,362 +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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/cipher"
|
|
||||||
"crypto/dsa"
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/rsa"
|
|
||||||
"crypto/sha1"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"math/big"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp/elgamal"
|
|
||||||
"golang.org/x/crypto/openpgp/errors"
|
|
||||||
"golang.org/x/crypto/openpgp/s2k"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PrivateKey represents a possibly encrypted private key. See RFC 4880,
|
|
||||||
// section 5.5.3.
|
|
||||||
type PrivateKey struct {
|
|
||||||
PublicKey
|
|
||||||
Encrypted bool // if true then the private key is unavailable until Decrypt has been called.
|
|
||||||
encryptedData []byte
|
|
||||||
cipher CipherFunction
|
|
||||||
s2k func(out, in []byte)
|
|
||||||
PrivateKey interface{} // An *rsa.PrivateKey or *dsa.PrivateKey.
|
|
||||||
sha1Checksum bool
|
|
||||||
iv []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
|
|
||||||
pk := new(PrivateKey)
|
|
||||||
pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey)
|
|
||||||
pk.PrivateKey = priv
|
|
||||||
return pk
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDSAPrivateKey(currentTime time.Time, priv *dsa.PrivateKey) *PrivateKey {
|
|
||||||
pk := new(PrivateKey)
|
|
||||||
pk.PublicKey = *NewDSAPublicKey(currentTime, &priv.PublicKey)
|
|
||||||
pk.PrivateKey = priv
|
|
||||||
return pk
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewElGamalPrivateKey(currentTime time.Time, priv *elgamal.PrivateKey) *PrivateKey {
|
|
||||||
pk := new(PrivateKey)
|
|
||||||
pk.PublicKey = *NewElGamalPublicKey(currentTime, &priv.PublicKey)
|
|
||||||
pk.PrivateKey = priv
|
|
||||||
return pk
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewECDSAPrivateKey(currentTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey {
|
|
||||||
pk := new(PrivateKey)
|
|
||||||
pk.PublicKey = *NewECDSAPublicKey(currentTime, &priv.PublicKey)
|
|
||||||
pk.PrivateKey = priv
|
|
||||||
return pk
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pk *PrivateKey) parse(r io.Reader) (err error) {
|
|
||||||
err = (&pk.PublicKey).parse(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var buf [1]byte
|
|
||||||
_, err = readFull(r, buf[:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
s2kType := buf[0]
|
|
||||||
|
|
||||||
switch s2kType {
|
|
||||||
case 0:
|
|
||||||
pk.s2k = nil
|
|
||||||
pk.Encrypted = false
|
|
||||||
case 254, 255:
|
|
||||||
_, err = readFull(r, buf[:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pk.cipher = CipherFunction(buf[0])
|
|
||||||
pk.Encrypted = true
|
|
||||||
pk.s2k, err = s2k.Parse(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if s2kType == 254 {
|
|
||||||
pk.sha1Checksum = true
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return errors.UnsupportedError("deprecated s2k function in private key")
|
|
||||||
}
|
|
||||||
|
|
||||||
if pk.Encrypted {
|
|
||||||
blockSize := pk.cipher.blockSize()
|
|
||||||
if blockSize == 0 {
|
|
||||||
return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
|
|
||||||
}
|
|
||||||
pk.iv = make([]byte, blockSize)
|
|
||||||
_, err = readFull(r, pk.iv)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pk.encryptedData, err = ioutil.ReadAll(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !pk.Encrypted {
|
|
||||||
return pk.parsePrivateKey(pk.encryptedData)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func mod64kHash(d []byte) uint16 {
|
|
||||||
var h uint16
|
|
||||||
for _, b := range d {
|
|
||||||
h += uint16(b)
|
|
||||||
}
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
|
|
||||||
// TODO(agl): support encrypted private keys
|
|
||||||
buf := bytes.NewBuffer(nil)
|
|
||||||
err = pk.PublicKey.serializeWithoutHeaders(buf)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
buf.WriteByte(0 /* no encryption */)
|
|
||||||
|
|
||||||
privateKeyBuf := bytes.NewBuffer(nil)
|
|
||||||
|
|
||||||
switch priv := pk.PrivateKey.(type) {
|
|
||||||
case *rsa.PrivateKey:
|
|
||||||
err = serializeRSAPrivateKey(privateKeyBuf, priv)
|
|
||||||
case *dsa.PrivateKey:
|
|
||||||
err = serializeDSAPrivateKey(privateKeyBuf, priv)
|
|
||||||
case *elgamal.PrivateKey:
|
|
||||||
err = serializeElGamalPrivateKey(privateKeyBuf, priv)
|
|
||||||
case *ecdsa.PrivateKey:
|
|
||||||
err = serializeECDSAPrivateKey(privateKeyBuf, priv)
|
|
||||||
default:
|
|
||||||
err = errors.InvalidArgumentError("unknown private key type")
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ptype := packetTypePrivateKey
|
|
||||||
contents := buf.Bytes()
|
|
||||||
privateKeyBytes := privateKeyBuf.Bytes()
|
|
||||||
if pk.IsSubkey {
|
|
||||||
ptype = packetTypePrivateSubkey
|
|
||||||
}
|
|
||||||
err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = w.Write(contents)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = w.Write(privateKeyBytes)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
checksum := mod64kHash(privateKeyBytes)
|
|
||||||
var checksumBytes [2]byte
|
|
||||||
checksumBytes[0] = byte(checksum >> 8)
|
|
||||||
checksumBytes[1] = byte(checksum)
|
|
||||||
_, err = w.Write(checksumBytes[:])
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error {
|
|
||||||
err := writeBig(w, priv.D)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = writeBig(w, priv.Primes[1])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = writeBig(w, priv.Primes[0])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return writeBig(w, priv.Precomputed.Qinv)
|
|
||||||
}
|
|
||||||
|
|
||||||
func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error {
|
|
||||||
return writeBig(w, priv.X)
|
|
||||||
}
|
|
||||||
|
|
||||||
func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error {
|
|
||||||
return writeBig(w, priv.X)
|
|
||||||
}
|
|
||||||
|
|
||||||
func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error {
|
|
||||||
return writeBig(w, priv.D)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrypt decrypts an encrypted private key using a passphrase.
|
|
||||||
func (pk *PrivateKey) Decrypt(passphrase []byte) error {
|
|
||||||
if !pk.Encrypted {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
key := make([]byte, pk.cipher.KeySize())
|
|
||||||
pk.s2k(key, passphrase)
|
|
||||||
block := pk.cipher.new(key)
|
|
||||||
cfb := cipher.NewCFBDecrypter(block, pk.iv)
|
|
||||||
|
|
||||||
data := make([]byte, len(pk.encryptedData))
|
|
||||||
cfb.XORKeyStream(data, pk.encryptedData)
|
|
||||||
|
|
||||||
if pk.sha1Checksum {
|
|
||||||
if len(data) < sha1.Size {
|
|
||||||
return errors.StructuralError("truncated private key data")
|
|
||||||
}
|
|
||||||
h := sha1.New()
|
|
||||||
h.Write(data[:len(data)-sha1.Size])
|
|
||||||
sum := h.Sum(nil)
|
|
||||||
if !bytes.Equal(sum, data[len(data)-sha1.Size:]) {
|
|
||||||
return errors.StructuralError("private key checksum failure")
|
|
||||||
}
|
|
||||||
data = data[:len(data)-sha1.Size]
|
|
||||||
} else {
|
|
||||||
if len(data) < 2 {
|
|
||||||
return errors.StructuralError("truncated private key data")
|
|
||||||
}
|
|
||||||
var sum uint16
|
|
||||||
for i := 0; i < len(data)-2; i++ {
|
|
||||||
sum += uint16(data[i])
|
|
||||||
}
|
|
||||||
if data[len(data)-2] != uint8(sum>>8) ||
|
|
||||||
data[len(data)-1] != uint8(sum) {
|
|
||||||
return errors.StructuralError("private key checksum failure")
|
|
||||||
}
|
|
||||||
data = data[:len(data)-2]
|
|
||||||
}
|
|
||||||
|
|
||||||
return pk.parsePrivateKey(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
|
|
||||||
switch pk.PublicKey.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly:
|
|
||||||
return pk.parseRSAPrivateKey(data)
|
|
||||||
case PubKeyAlgoDSA:
|
|
||||||
return pk.parseDSAPrivateKey(data)
|
|
||||||
case PubKeyAlgoElGamal:
|
|
||||||
return pk.parseElGamalPrivateKey(data)
|
|
||||||
case PubKeyAlgoECDSA:
|
|
||||||
return pk.parseECDSAPrivateKey(data)
|
|
||||||
}
|
|
||||||
panic("impossible")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) {
|
|
||||||
rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey)
|
|
||||||
rsaPriv := new(rsa.PrivateKey)
|
|
||||||
rsaPriv.PublicKey = *rsaPub
|
|
||||||
|
|
||||||
buf := bytes.NewBuffer(data)
|
|
||||||
d, _, err := readMPI(buf)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p, _, err := readMPI(buf)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
q, _, err := readMPI(buf)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rsaPriv.D = new(big.Int).SetBytes(d)
|
|
||||||
rsaPriv.Primes = make([]*big.Int, 2)
|
|
||||||
rsaPriv.Primes[0] = new(big.Int).SetBytes(p)
|
|
||||||
rsaPriv.Primes[1] = new(big.Int).SetBytes(q)
|
|
||||||
if err := rsaPriv.Validate(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rsaPriv.Precompute()
|
|
||||||
pk.PrivateKey = rsaPriv
|
|
||||||
pk.Encrypted = false
|
|
||||||
pk.encryptedData = nil
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) {
|
|
||||||
dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey)
|
|
||||||
dsaPriv := new(dsa.PrivateKey)
|
|
||||||
dsaPriv.PublicKey = *dsaPub
|
|
||||||
|
|
||||||
buf := bytes.NewBuffer(data)
|
|
||||||
x, _, err := readMPI(buf)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dsaPriv.X = new(big.Int).SetBytes(x)
|
|
||||||
pk.PrivateKey = dsaPriv
|
|
||||||
pk.Encrypted = false
|
|
||||||
pk.encryptedData = nil
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) {
|
|
||||||
pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey)
|
|
||||||
priv := new(elgamal.PrivateKey)
|
|
||||||
priv.PublicKey = *pub
|
|
||||||
|
|
||||||
buf := bytes.NewBuffer(data)
|
|
||||||
x, _, err := readMPI(buf)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
priv.X = new(big.Int).SetBytes(x)
|
|
||||||
pk.PrivateKey = priv
|
|
||||||
pk.Encrypted = false
|
|
||||||
pk.encryptedData = nil
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) {
|
|
||||||
ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey)
|
|
||||||
|
|
||||||
buf := bytes.NewBuffer(data)
|
|
||||||
d, _, err := readMPI(buf)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pk.PrivateKey = &ecdsa.PrivateKey{
|
|
||||||
PublicKey: *ecdsaPub,
|
|
||||||
D: new(big.Int).SetBytes(d),
|
|
||||||
}
|
|
||||||
pk.Encrypted = false
|
|
||||||
pk.encryptedData = nil
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
126
vendor/golang.org/x/crypto/openpgp/packet/private_key_test.go
generated
vendored
126
vendor/golang.org/x/crypto/openpgp/packet/private_key_test.go
generated
vendored
|
@ -1,126 +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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto"
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/elliptic"
|
|
||||||
"crypto/rand"
|
|
||||||
"hash"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var privateKeyTests = []struct {
|
|
||||||
privateKeyHex string
|
|
||||||
creationTime time.Time
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
privKeyRSAHex,
|
|
||||||
time.Unix(0x4cc349a8, 0),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
privKeyElGamalHex,
|
|
||||||
time.Unix(0x4df9ee1a, 0),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrivateKeyRead(t *testing.T) {
|
|
||||||
for i, test := range privateKeyTests {
|
|
||||||
packet, err := Read(readerFromHex(test.privateKeyHex))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("#%d: failed to parse: %s", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
privKey := packet.(*PrivateKey)
|
|
||||||
|
|
||||||
if !privKey.Encrypted {
|
|
||||||
t.Errorf("#%d: private key isn't encrypted", i)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
err = privKey.Decrypt([]byte("wrong password"))
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("#%d: decrypted with incorrect key", i)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
err = privKey.Decrypt([]byte("testing"))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("#%d: failed to decrypt: %s", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !privKey.CreationTime.Equal(test.creationTime) || privKey.Encrypted {
|
|
||||||
t.Errorf("#%d: bad result, got: %#v", i, privKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func populateHash(hashFunc crypto.Hash, msg []byte) (hash.Hash, error) {
|
|
||||||
h := hashFunc.New()
|
|
||||||
if _, err := h.Write(msg); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return h, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestECDSAPrivateKey(t *testing.T) {
|
|
||||||
ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
if err := NewECDSAPrivateKey(time.Now(), ecdsaPriv).Serialize(&buf); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
p, err := Read(&buf)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
priv, ok := p.(*PrivateKey)
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("didn't parse private key")
|
|
||||||
}
|
|
||||||
|
|
||||||
sig := &Signature{
|
|
||||||
PubKeyAlgo: PubKeyAlgoECDSA,
|
|
||||||
Hash: crypto.SHA256,
|
|
||||||
}
|
|
||||||
msg := []byte("Hello World!")
|
|
||||||
|
|
||||||
h, err := populateHash(sig.Hash, msg)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if err := sig.Sign(h, priv, nil); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if h, err = populateHash(sig.Hash, msg); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if err := priv.VerifySignature(h, sig); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIssue11505(t *testing.T) {
|
|
||||||
// parsing a rsa private key with p or q == 1 used to panic due to a divide by zero
|
|
||||||
_, _ = Read(readerFromHex("9c3004303030300100000011303030000000000000010130303030303030303030303030303030303030303030303030303030303030303030303030303030303030"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generated with `gpg --export-secret-keys "Test Key 2"`
|
|
||||||
const privKeyRSAHex = "9501fe044cc349a8010400b70ca0010e98c090008d45d1ee8f9113bd5861fd57b88bacb7c68658747663f1e1a3b5a98f32fda6472373c024b97359cd2efc88ff60f77751adfbf6af5e615e6a1408cfad8bf0cea30b0d5f53aa27ad59089ba9b15b7ebc2777a25d7b436144027e3bcd203909f147d0e332b240cf63d3395f5dfe0df0a6c04e8655af7eacdf0011010001fe0303024a252e7d475fd445607de39a265472aa74a9320ba2dac395faa687e9e0336aeb7e9a7397e511b5afd9dc84557c80ac0f3d4d7bfec5ae16f20d41c8c84a04552a33870b930420e230e179564f6d19bb153145e76c33ae993886c388832b0fa042ddda7f133924f3854481533e0ede31d51278c0519b29abc3bf53da673e13e3e1214b52413d179d7f66deee35cac8eacb060f78379d70ef4af8607e68131ff529439668fc39c9ce6dfef8a5ac234d234802cbfb749a26107db26406213ae5c06d4673253a3cbee1fcbae58d6ab77e38d6e2c0e7c6317c48e054edadb5a40d0d48acb44643d998139a8a66bb820be1f3f80185bc777d14b5954b60effe2448a036d565c6bc0b915fcea518acdd20ab07bc1529f561c58cd044f723109b93f6fd99f876ff891d64306b5d08f48bab59f38695e9109c4dec34013ba3153488ce070268381ba923ee1eb77125b36afcb4347ec3478c8f2735b06ef17351d872e577fa95d0c397c88c71b59629a36aec"
|
|
||||||
|
|
||||||
// Generated by `gpg --export-secret-keys` followed by a manual extraction of
|
|
||||||
// the ElGamal subkey from the packets.
|
|
||||||
const privKeyElGamalHex = "9d0157044df9ee1a100400eb8e136a58ec39b582629cdadf830bc64e0a94ed8103ca8bb247b27b11b46d1d25297ef4bcc3071785ba0c0bedfe89eabc5287fcc0edf81ab5896c1c8e4b20d27d79813c7aede75320b33eaeeaa586edc00fd1036c10133e6ba0ff277245d0d59d04b2b3421b7244aca5f4a8d870c6f1c1fbff9e1c26699a860b9504f35ca1d700030503fd1ededd3b840795be6d9ccbe3c51ee42e2f39233c432b831ddd9c4e72b7025a819317e47bf94f9ee316d7273b05d5fcf2999c3a681f519b1234bbfa6d359b4752bd9c3f77d6b6456cde152464763414ca130f4e91d91041432f90620fec0e6d6b5116076c2985d5aeaae13be492b9b329efcaf7ee25120159a0a30cd976b42d7afe030302dae7eb80db744d4960c4df930d57e87fe81412eaace9f900e6c839817a614ddb75ba6603b9417c33ea7b6c93967dfa2bcff3fa3c74a5ce2c962db65b03aece14c96cbd0038fc"
|
|
750
vendor/golang.org/x/crypto/openpgp/packet/public_key.go
generated
vendored
750
vendor/golang.org/x/crypto/openpgp/packet/public_key.go
generated
vendored
|
@ -1,750 +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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto"
|
|
||||||
"crypto/dsa"
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/elliptic"
|
|
||||||
"crypto/rsa"
|
|
||||||
"crypto/sha1"
|
|
||||||
_ "crypto/sha256"
|
|
||||||
_ "crypto/sha512"
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"hash"
|
|
||||||
"io"
|
|
||||||
"math/big"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp/elgamal"
|
|
||||||
"golang.org/x/crypto/openpgp/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// NIST curve P-256
|
|
||||||
oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}
|
|
||||||
// NIST curve P-384
|
|
||||||
oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22}
|
|
||||||
// NIST curve P-521
|
|
||||||
oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23}
|
|
||||||
)
|
|
||||||
|
|
||||||
const maxOIDLength = 8
|
|
||||||
|
|
||||||
// ecdsaKey stores the algorithm-specific fields for ECDSA keys.
|
|
||||||
// as defined in RFC 6637, Section 9.
|
|
||||||
type ecdsaKey struct {
|
|
||||||
// oid contains the OID byte sequence identifying the elliptic curve used
|
|
||||||
oid []byte
|
|
||||||
// p contains the elliptic curve point that represents the public key
|
|
||||||
p parsedMPI
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseOID reads the OID for the curve as defined in RFC 6637, Section 9.
|
|
||||||
func parseOID(r io.Reader) (oid []byte, err error) {
|
|
||||||
buf := make([]byte, maxOIDLength)
|
|
||||||
if _, err = readFull(r, buf[:1]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
oidLen := buf[0]
|
|
||||||
if int(oidLen) > len(buf) {
|
|
||||||
err = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int(oidLen)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
oid = buf[:oidLen]
|
|
||||||
_, err = readFull(r, oid)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *ecdsaKey) parse(r io.Reader) (err error) {
|
|
||||||
if f.oid, err = parseOID(r); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
f.p.bytes, f.p.bitLength, err = readMPI(r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *ecdsaKey) serialize(w io.Writer) (err error) {
|
|
||||||
buf := make([]byte, maxOIDLength+1)
|
|
||||||
buf[0] = byte(len(f.oid))
|
|
||||||
copy(buf[1:], f.oid)
|
|
||||||
if _, err = w.Write(buf[:len(f.oid)+1]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return writeMPIs(w, f.p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) {
|
|
||||||
var c elliptic.Curve
|
|
||||||
if bytes.Equal(f.oid, oidCurveP256) {
|
|
||||||
c = elliptic.P256()
|
|
||||||
} else if bytes.Equal(f.oid, oidCurveP384) {
|
|
||||||
c = elliptic.P384()
|
|
||||||
} else if bytes.Equal(f.oid, oidCurveP521) {
|
|
||||||
c = elliptic.P521()
|
|
||||||
} else {
|
|
||||||
return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid))
|
|
||||||
}
|
|
||||||
x, y := elliptic.Unmarshal(c, f.p.bytes)
|
|
||||||
if x == nil {
|
|
||||||
return nil, errors.UnsupportedError("failed to parse EC point")
|
|
||||||
}
|
|
||||||
return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *ecdsaKey) byteLen() int {
|
|
||||||
return 1 + len(f.oid) + 2 + len(f.p.bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
type kdfHashFunction byte
|
|
||||||
type kdfAlgorithm byte
|
|
||||||
|
|
||||||
// ecdhKdf stores key derivation function parameters
|
|
||||||
// used for ECDH encryption. See RFC 6637, Section 9.
|
|
||||||
type ecdhKdf struct {
|
|
||||||
KdfHash kdfHashFunction
|
|
||||||
KdfAlgo kdfAlgorithm
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *ecdhKdf) parse(r io.Reader) (err error) {
|
|
||||||
buf := make([]byte, 1)
|
|
||||||
if _, err = readFull(r, buf); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
kdfLen := int(buf[0])
|
|
||||||
if kdfLen < 3 {
|
|
||||||
return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa(kdfLen))
|
|
||||||
}
|
|
||||||
buf = make([]byte, kdfLen)
|
|
||||||
if _, err = readFull(r, buf); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
reserved := int(buf[0])
|
|
||||||
f.KdfHash = kdfHashFunction(buf[1])
|
|
||||||
f.KdfAlgo = kdfAlgorithm(buf[2])
|
|
||||||
if reserved != 0x01 {
|
|
||||||
return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa(reserved))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *ecdhKdf) serialize(w io.Writer) (err error) {
|
|
||||||
buf := make([]byte, 4)
|
|
||||||
// See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys.
|
|
||||||
buf[0] = byte(0x03) // Length of the following fields
|
|
||||||
buf[1] = byte(0x01) // Reserved for future extensions, must be 1 for now
|
|
||||||
buf[2] = byte(f.KdfHash)
|
|
||||||
buf[3] = byte(f.KdfAlgo)
|
|
||||||
_, err = w.Write(buf[:])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *ecdhKdf) byteLen() int {
|
|
||||||
return 4
|
|
||||||
}
|
|
||||||
|
|
||||||
// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
|
|
||||||
type PublicKey struct {
|
|
||||||
CreationTime time.Time
|
|
||||||
PubKeyAlgo PublicKeyAlgorithm
|
|
||||||
PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey
|
|
||||||
Fingerprint [20]byte
|
|
||||||
KeyId uint64
|
|
||||||
IsSubkey bool
|
|
||||||
|
|
||||||
n, e, p, q, g, y parsedMPI
|
|
||||||
|
|
||||||
// RFC 6637 fields
|
|
||||||
ec *ecdsaKey
|
|
||||||
ecdh *ecdhKdf
|
|
||||||
}
|
|
||||||
|
|
||||||
// signingKey provides a convenient abstraction over signature verification
|
|
||||||
// for v3 and v4 public keys.
|
|
||||||
type signingKey interface {
|
|
||||||
SerializeSignaturePrefix(io.Writer)
|
|
||||||
serializeWithoutHeaders(io.Writer) error
|
|
||||||
}
|
|
||||||
|
|
||||||
func fromBig(n *big.Int) parsedMPI {
|
|
||||||
return parsedMPI{
|
|
||||||
bytes: n.Bytes(),
|
|
||||||
bitLength: uint16(n.BitLen()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
|
|
||||||
func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey {
|
|
||||||
pk := &PublicKey{
|
|
||||||
CreationTime: creationTime,
|
|
||||||
PubKeyAlgo: PubKeyAlgoRSA,
|
|
||||||
PublicKey: pub,
|
|
||||||
n: fromBig(pub.N),
|
|
||||||
e: fromBig(big.NewInt(int64(pub.E))),
|
|
||||||
}
|
|
||||||
|
|
||||||
pk.setFingerPrintAndKeyId()
|
|
||||||
return pk
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey.
|
|
||||||
func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey {
|
|
||||||
pk := &PublicKey{
|
|
||||||
CreationTime: creationTime,
|
|
||||||
PubKeyAlgo: PubKeyAlgoDSA,
|
|
||||||
PublicKey: pub,
|
|
||||||
p: fromBig(pub.P),
|
|
||||||
q: fromBig(pub.Q),
|
|
||||||
g: fromBig(pub.G),
|
|
||||||
y: fromBig(pub.Y),
|
|
||||||
}
|
|
||||||
|
|
||||||
pk.setFingerPrintAndKeyId()
|
|
||||||
return pk
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey.
|
|
||||||
func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey {
|
|
||||||
pk := &PublicKey{
|
|
||||||
CreationTime: creationTime,
|
|
||||||
PubKeyAlgo: PubKeyAlgoElGamal,
|
|
||||||
PublicKey: pub,
|
|
||||||
p: fromBig(pub.P),
|
|
||||||
g: fromBig(pub.G),
|
|
||||||
y: fromBig(pub.Y),
|
|
||||||
}
|
|
||||||
|
|
||||||
pk.setFingerPrintAndKeyId()
|
|
||||||
return pk
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey {
|
|
||||||
pk := &PublicKey{
|
|
||||||
CreationTime: creationTime,
|
|
||||||
PubKeyAlgo: PubKeyAlgoECDSA,
|
|
||||||
PublicKey: pub,
|
|
||||||
ec: new(ecdsaKey),
|
|
||||||
}
|
|
||||||
|
|
||||||
switch pub.Curve {
|
|
||||||
case elliptic.P256():
|
|
||||||
pk.ec.oid = oidCurveP256
|
|
||||||
case elliptic.P384():
|
|
||||||
pk.ec.oid = oidCurveP384
|
|
||||||
case elliptic.P521():
|
|
||||||
pk.ec.oid = oidCurveP521
|
|
||||||
default:
|
|
||||||
panic("unknown elliptic curve")
|
|
||||||
}
|
|
||||||
|
|
||||||
pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
|
|
||||||
pk.ec.p.bitLength = uint16(8 * len(pk.ec.p.bytes))
|
|
||||||
|
|
||||||
pk.setFingerPrintAndKeyId()
|
|
||||||
return pk
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pk *PublicKey) parse(r io.Reader) (err error) {
|
|
||||||
// RFC 4880, section 5.5.2
|
|
||||||
var buf [6]byte
|
|
||||||
_, err = readFull(r, buf[:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if buf[0] != 4 {
|
|
||||||
return errors.UnsupportedError("public key version")
|
|
||||||
}
|
|
||||||
pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
|
|
||||||
pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
|
|
||||||
switch pk.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
|
|
||||||
err = pk.parseRSA(r)
|
|
||||||
case PubKeyAlgoDSA:
|
|
||||||
err = pk.parseDSA(r)
|
|
||||||
case PubKeyAlgoElGamal:
|
|
||||||
err = pk.parseElGamal(r)
|
|
||||||
case PubKeyAlgoECDSA:
|
|
||||||
pk.ec = new(ecdsaKey)
|
|
||||||
if err = pk.ec.parse(r); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
pk.PublicKey, err = pk.ec.newECDSA()
|
|
||||||
case PubKeyAlgoECDH:
|
|
||||||
pk.ec = new(ecdsaKey)
|
|
||||||
if err = pk.ec.parse(r); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pk.ecdh = new(ecdhKdf)
|
|
||||||
if err = pk.ecdh.parse(r); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// The ECDH key is stored in an ecdsa.PublicKey for convenience.
|
|
||||||
pk.PublicKey, err = pk.ec.newECDSA()
|
|
||||||
default:
|
|
||||||
err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pk.setFingerPrintAndKeyId()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pk *PublicKey) setFingerPrintAndKeyId() {
|
|
||||||
// RFC 4880, section 12.2
|
|
||||||
fingerPrint := sha1.New()
|
|
||||||
pk.SerializeSignaturePrefix(fingerPrint)
|
|
||||||
pk.serializeWithoutHeaders(fingerPrint)
|
|
||||||
copy(pk.Fingerprint[:], fingerPrint.Sum(nil))
|
|
||||||
pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
|
|
||||||
// section 5.5.2.
|
|
||||||
func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
|
|
||||||
pk.n.bytes, pk.n.bitLength, err = readMPI(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pk.e.bytes, pk.e.bitLength, err = readMPI(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(pk.e.bytes) > 3 {
|
|
||||||
err = errors.UnsupportedError("large public exponent")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rsa := &rsa.PublicKey{
|
|
||||||
N: new(big.Int).SetBytes(pk.n.bytes),
|
|
||||||
E: 0,
|
|
||||||
}
|
|
||||||
for i := 0; i < len(pk.e.bytes); i++ {
|
|
||||||
rsa.E <<= 8
|
|
||||||
rsa.E |= int(pk.e.bytes[i])
|
|
||||||
}
|
|
||||||
pk.PublicKey = rsa
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseDSA parses DSA public key material from the given Reader. See RFC 4880,
|
|
||||||
// section 5.5.2.
|
|
||||||
func (pk *PublicKey) parseDSA(r io.Reader) (err error) {
|
|
||||||
pk.p.bytes, pk.p.bitLength, err = readMPI(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pk.q.bytes, pk.q.bitLength, err = readMPI(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pk.g.bytes, pk.g.bitLength, err = readMPI(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pk.y.bytes, pk.y.bitLength, err = readMPI(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dsa := new(dsa.PublicKey)
|
|
||||||
dsa.P = new(big.Int).SetBytes(pk.p.bytes)
|
|
||||||
dsa.Q = new(big.Int).SetBytes(pk.q.bytes)
|
|
||||||
dsa.G = new(big.Int).SetBytes(pk.g.bytes)
|
|
||||||
dsa.Y = new(big.Int).SetBytes(pk.y.bytes)
|
|
||||||
pk.PublicKey = dsa
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseElGamal parses ElGamal public key material from the given Reader. See
|
|
||||||
// RFC 4880, section 5.5.2.
|
|
||||||
func (pk *PublicKey) parseElGamal(r io.Reader) (err error) {
|
|
||||||
pk.p.bytes, pk.p.bitLength, err = readMPI(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pk.g.bytes, pk.g.bitLength, err = readMPI(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pk.y.bytes, pk.y.bitLength, err = readMPI(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
elgamal := new(elgamal.PublicKey)
|
|
||||||
elgamal.P = new(big.Int).SetBytes(pk.p.bytes)
|
|
||||||
elgamal.G = new(big.Int).SetBytes(pk.g.bytes)
|
|
||||||
elgamal.Y = new(big.Int).SetBytes(pk.y.bytes)
|
|
||||||
pk.PublicKey = elgamal
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
|
|
||||||
// The prefix is used when calculating a signature over this public key. See
|
|
||||||
// RFC 4880, section 5.2.4.
|
|
||||||
func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) {
|
|
||||||
var pLength uint16
|
|
||||||
switch pk.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
|
|
||||||
pLength += 2 + uint16(len(pk.n.bytes))
|
|
||||||
pLength += 2 + uint16(len(pk.e.bytes))
|
|
||||||
case PubKeyAlgoDSA:
|
|
||||||
pLength += 2 + uint16(len(pk.p.bytes))
|
|
||||||
pLength += 2 + uint16(len(pk.q.bytes))
|
|
||||||
pLength += 2 + uint16(len(pk.g.bytes))
|
|
||||||
pLength += 2 + uint16(len(pk.y.bytes))
|
|
||||||
case PubKeyAlgoElGamal:
|
|
||||||
pLength += 2 + uint16(len(pk.p.bytes))
|
|
||||||
pLength += 2 + uint16(len(pk.g.bytes))
|
|
||||||
pLength += 2 + uint16(len(pk.y.bytes))
|
|
||||||
case PubKeyAlgoECDSA:
|
|
||||||
pLength += uint16(pk.ec.byteLen())
|
|
||||||
case PubKeyAlgoECDH:
|
|
||||||
pLength += uint16(pk.ec.byteLen())
|
|
||||||
pLength += uint16(pk.ecdh.byteLen())
|
|
||||||
default:
|
|
||||||
panic("unknown public key algorithm")
|
|
||||||
}
|
|
||||||
pLength += 6
|
|
||||||
h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pk *PublicKey) Serialize(w io.Writer) (err error) {
|
|
||||||
length := 6 // 6 byte header
|
|
||||||
|
|
||||||
switch pk.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
|
|
||||||
length += 2 + len(pk.n.bytes)
|
|
||||||
length += 2 + len(pk.e.bytes)
|
|
||||||
case PubKeyAlgoDSA:
|
|
||||||
length += 2 + len(pk.p.bytes)
|
|
||||||
length += 2 + len(pk.q.bytes)
|
|
||||||
length += 2 + len(pk.g.bytes)
|
|
||||||
length += 2 + len(pk.y.bytes)
|
|
||||||
case PubKeyAlgoElGamal:
|
|
||||||
length += 2 + len(pk.p.bytes)
|
|
||||||
length += 2 + len(pk.g.bytes)
|
|
||||||
length += 2 + len(pk.y.bytes)
|
|
||||||
case PubKeyAlgoECDSA:
|
|
||||||
length += pk.ec.byteLen()
|
|
||||||
case PubKeyAlgoECDH:
|
|
||||||
length += pk.ec.byteLen()
|
|
||||||
length += pk.ecdh.byteLen()
|
|
||||||
default:
|
|
||||||
panic("unknown public key algorithm")
|
|
||||||
}
|
|
||||||
|
|
||||||
packetType := packetTypePublicKey
|
|
||||||
if pk.IsSubkey {
|
|
||||||
packetType = packetTypePublicSubkey
|
|
||||||
}
|
|
||||||
err = serializeHeader(w, packetType, length)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return pk.serializeWithoutHeaders(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
// serializeWithoutHeaders marshals the PublicKey to w in the form of an
|
|
||||||
// OpenPGP public key packet, not including the packet header.
|
|
||||||
func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
|
|
||||||
var buf [6]byte
|
|
||||||
buf[0] = 4
|
|
||||||
t := uint32(pk.CreationTime.Unix())
|
|
||||||
buf[1] = byte(t >> 24)
|
|
||||||
buf[2] = byte(t >> 16)
|
|
||||||
buf[3] = byte(t >> 8)
|
|
||||||
buf[4] = byte(t)
|
|
||||||
buf[5] = byte(pk.PubKeyAlgo)
|
|
||||||
|
|
||||||
_, err = w.Write(buf[:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch pk.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
|
|
||||||
return writeMPIs(w, pk.n, pk.e)
|
|
||||||
case PubKeyAlgoDSA:
|
|
||||||
return writeMPIs(w, pk.p, pk.q, pk.g, pk.y)
|
|
||||||
case PubKeyAlgoElGamal:
|
|
||||||
return writeMPIs(w, pk.p, pk.g, pk.y)
|
|
||||||
case PubKeyAlgoECDSA:
|
|
||||||
return pk.ec.serialize(w)
|
|
||||||
case PubKeyAlgoECDH:
|
|
||||||
if err = pk.ec.serialize(w); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return pk.ecdh.serialize(w)
|
|
||||||
}
|
|
||||||
return errors.InvalidArgumentError("bad public-key algorithm")
|
|
||||||
}
|
|
||||||
|
|
||||||
// CanSign returns true iff this public key can generate signatures
|
|
||||||
func (pk *PublicKey) CanSign() bool {
|
|
||||||
return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifySignature returns nil iff sig is a valid signature, made by this
|
|
||||||
// public key, of the data hashed into signed. signed is mutated by this call.
|
|
||||||
func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) {
|
|
||||||
if !pk.CanSign() {
|
|
||||||
return errors.InvalidArgumentError("public key cannot generate signatures")
|
|
||||||
}
|
|
||||||
|
|
||||||
signed.Write(sig.HashSuffix)
|
|
||||||
hashBytes := signed.Sum(nil)
|
|
||||||
|
|
||||||
if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
|
|
||||||
return errors.SignatureError("hash tag doesn't match")
|
|
||||||
}
|
|
||||||
|
|
||||||
if pk.PubKeyAlgo != sig.PubKeyAlgo {
|
|
||||||
return errors.InvalidArgumentError("public key and signature use different algorithms")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch pk.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
|
|
||||||
rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
|
|
||||||
err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes)
|
|
||||||
if err != nil {
|
|
||||||
return errors.SignatureError("RSA verification failure")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
case PubKeyAlgoDSA:
|
|
||||||
dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey)
|
|
||||||
// Need to truncate hashBytes to match FIPS 186-3 section 4.6.
|
|
||||||
subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
|
|
||||||
if len(hashBytes) > subgroupSize {
|
|
||||||
hashBytes = hashBytes[:subgroupSize]
|
|
||||||
}
|
|
||||||
if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
|
|
||||||
return errors.SignatureError("DSA verification failure")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
case PubKeyAlgoECDSA:
|
|
||||||
ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey)
|
|
||||||
if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) {
|
|
||||||
return errors.SignatureError("ECDSA verification failure")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
return errors.SignatureError("Unsupported public key algorithm used in signature")
|
|
||||||
}
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifySignatureV3 returns nil iff sig is a valid signature, made by this
|
|
||||||
// public key, of the data hashed into signed. signed is mutated by this call.
|
|
||||||
func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) {
|
|
||||||
if !pk.CanSign() {
|
|
||||||
return errors.InvalidArgumentError("public key cannot generate signatures")
|
|
||||||
}
|
|
||||||
|
|
||||||
suffix := make([]byte, 5)
|
|
||||||
suffix[0] = byte(sig.SigType)
|
|
||||||
binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix()))
|
|
||||||
signed.Write(suffix)
|
|
||||||
hashBytes := signed.Sum(nil)
|
|
||||||
|
|
||||||
if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
|
|
||||||
return errors.SignatureError("hash tag doesn't match")
|
|
||||||
}
|
|
||||||
|
|
||||||
if pk.PubKeyAlgo != sig.PubKeyAlgo {
|
|
||||||
return errors.InvalidArgumentError("public key and signature use different algorithms")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch pk.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
|
|
||||||
rsaPublicKey := pk.PublicKey.(*rsa.PublicKey)
|
|
||||||
if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil {
|
|
||||||
return errors.SignatureError("RSA verification failure")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
case PubKeyAlgoDSA:
|
|
||||||
dsaPublicKey := pk.PublicKey.(*dsa.PublicKey)
|
|
||||||
// Need to truncate hashBytes to match FIPS 186-3 section 4.6.
|
|
||||||
subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
|
|
||||||
if len(hashBytes) > subgroupSize {
|
|
||||||
hashBytes = hashBytes[:subgroupSize]
|
|
||||||
}
|
|
||||||
if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
|
|
||||||
return errors.SignatureError("DSA verification failure")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
panic("shouldn't happen")
|
|
||||||
}
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
// keySignatureHash returns a Hash of the message that needs to be signed for
|
|
||||||
// pk to assert a subkey relationship to signed.
|
|
||||||
func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
|
|
||||||
if !hashFunc.Available() {
|
|
||||||
return nil, errors.UnsupportedError("hash function")
|
|
||||||
}
|
|
||||||
h = hashFunc.New()
|
|
||||||
|
|
||||||
// RFC 4880, section 5.2.4
|
|
||||||
pk.SerializeSignaturePrefix(h)
|
|
||||||
pk.serializeWithoutHeaders(h)
|
|
||||||
signed.SerializeSignaturePrefix(h)
|
|
||||||
signed.serializeWithoutHeaders(h)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyKeySignature returns nil iff sig is a valid signature, made by this
|
|
||||||
// public key, of signed.
|
|
||||||
func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error {
|
|
||||||
h, err := keySignatureHash(pk, signed, sig.Hash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err = pk.VerifySignature(h, sig); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if sig.FlagSign {
|
|
||||||
// Signing subkeys must be cross-signed. See
|
|
||||||
// https://www.gnupg.org/faq/subkey-cross-certify.html.
|
|
||||||
if sig.EmbeddedSignature == nil {
|
|
||||||
return errors.StructuralError("signing subkey is missing cross-signature")
|
|
||||||
}
|
|
||||||
// Verify the cross-signature. This is calculated over the same
|
|
||||||
// data as the main signature, so we cannot just recursively
|
|
||||||
// call signed.VerifyKeySignature(...)
|
|
||||||
if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil {
|
|
||||||
return errors.StructuralError("error while hashing for cross-signature: " + err.Error())
|
|
||||||
}
|
|
||||||
if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil {
|
|
||||||
return errors.StructuralError("error while verifying cross-signature: " + err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
|
|
||||||
if !hashFunc.Available() {
|
|
||||||
return nil, errors.UnsupportedError("hash function")
|
|
||||||
}
|
|
||||||
h = hashFunc.New()
|
|
||||||
|
|
||||||
// RFC 4880, section 5.2.4
|
|
||||||
pk.SerializeSignaturePrefix(h)
|
|
||||||
pk.serializeWithoutHeaders(h)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this
|
|
||||||
// public key.
|
|
||||||
func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) {
|
|
||||||
h, err := keyRevocationHash(pk, sig.Hash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return pk.VerifySignature(h, sig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// userIdSignatureHash returns a Hash of the message that needs to be signed
|
|
||||||
// to assert that pk is a valid key for id.
|
|
||||||
func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
|
|
||||||
if !hashFunc.Available() {
|
|
||||||
return nil, errors.UnsupportedError("hash function")
|
|
||||||
}
|
|
||||||
h = hashFunc.New()
|
|
||||||
|
|
||||||
// RFC 4880, section 5.2.4
|
|
||||||
pk.SerializeSignaturePrefix(h)
|
|
||||||
pk.serializeWithoutHeaders(h)
|
|
||||||
|
|
||||||
var buf [5]byte
|
|
||||||
buf[0] = 0xb4
|
|
||||||
buf[1] = byte(len(id) >> 24)
|
|
||||||
buf[2] = byte(len(id) >> 16)
|
|
||||||
buf[3] = byte(len(id) >> 8)
|
|
||||||
buf[4] = byte(len(id))
|
|
||||||
h.Write(buf[:])
|
|
||||||
h.Write([]byte(id))
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this
|
|
||||||
// public key, that id is the identity of pub.
|
|
||||||
func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) {
|
|
||||||
h, err := userIdSignatureHash(id, pub, sig.Hash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return pk.VerifySignature(h, sig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this
|
|
||||||
// public key, that id is the identity of pub.
|
|
||||||
func (pk *PublicKey) VerifyUserIdSignatureV3(id string, pub *PublicKey, sig *SignatureV3) (err error) {
|
|
||||||
h, err := userIdSignatureV3Hash(id, pub, sig.Hash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return pk.VerifySignatureV3(h, sig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// KeyIdString returns the public key's fingerprint in capital hex
|
|
||||||
// (e.g. "6C7EE1B8621CC013").
|
|
||||||
func (pk *PublicKey) KeyIdString() string {
|
|
||||||
return fmt.Sprintf("%X", pk.Fingerprint[12:20])
|
|
||||||
}
|
|
||||||
|
|
||||||
// KeyIdShortString returns the short form of public key's fingerprint
|
|
||||||
// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
|
|
||||||
func (pk *PublicKey) KeyIdShortString() string {
|
|
||||||
return fmt.Sprintf("%X", pk.Fingerprint[16:20])
|
|
||||||
}
|
|
||||||
|
|
||||||
// A parsedMPI is used to store the contents of a big integer, along with the
|
|
||||||
// bit length that was specified in the original input. This allows the MPI to
|
|
||||||
// be reserialized exactly.
|
|
||||||
type parsedMPI struct {
|
|
||||||
bytes []byte
|
|
||||||
bitLength uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeMPIs is a utility function for serializing several big integers to the
|
|
||||||
// given Writer.
|
|
||||||
func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) {
|
|
||||||
for _, mpi := range mpis {
|
|
||||||
err = writeMPI(w, mpi.bitLength, mpi.bytes)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// BitLength returns the bit length for the given public key.
|
|
||||||
func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
|
|
||||||
switch pk.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
|
|
||||||
bitLength = pk.n.bitLength
|
|
||||||
case PubKeyAlgoDSA:
|
|
||||||
bitLength = pk.p.bitLength
|
|
||||||
case PubKeyAlgoElGamal:
|
|
||||||
bitLength = pk.p.bitLength
|
|
||||||
default:
|
|
||||||
err = errors.InvalidArgumentError("bad public-key algorithm")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
202
vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go
generated
vendored
202
vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go
generated
vendored
|
@ -1,202 +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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var pubKeyTests = []struct {
|
|
||||||
hexData string
|
|
||||||
hexFingerprint string
|
|
||||||
creationTime time.Time
|
|
||||||
pubKeyAlgo PublicKeyAlgorithm
|
|
||||||
keyId uint64
|
|
||||||
keyIdString string
|
|
||||||
keyIdShort string
|
|
||||||
}{
|
|
||||||
{rsaPkDataHex, rsaFingerprintHex, time.Unix(0x4d3c5c10, 0), PubKeyAlgoRSA, 0xa34d7e18c20c31bb, "A34D7E18C20C31BB", "C20C31BB"},
|
|
||||||
{dsaPkDataHex, dsaFingerprintHex, time.Unix(0x4d432f89, 0), PubKeyAlgoDSA, 0x8e8fbe54062f19ed, "8E8FBE54062F19ED", "062F19ED"},
|
|
||||||
{ecdsaPkDataHex, ecdsaFingerprintHex, time.Unix(0x5071c294, 0), PubKeyAlgoECDSA, 0x43fe956c542ca00b, "43FE956C542CA00B", "542CA00B"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPublicKeyRead(t *testing.T) {
|
|
||||||
for i, test := range pubKeyTests {
|
|
||||||
packet, err := Read(readerFromHex(test.hexData))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("#%d: Read error: %s", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
pk, ok := packet.(*PublicKey)
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("#%d: failed to parse, got: %#v", i, packet)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if pk.PubKeyAlgo != test.pubKeyAlgo {
|
|
||||||
t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo)
|
|
||||||
}
|
|
||||||
if !pk.CreationTime.Equal(test.creationTime) {
|
|
||||||
t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime)
|
|
||||||
}
|
|
||||||
expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint)
|
|
||||||
if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) {
|
|
||||||
t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint)
|
|
||||||
}
|
|
||||||
if pk.KeyId != test.keyId {
|
|
||||||
t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId)
|
|
||||||
}
|
|
||||||
if g, e := pk.KeyIdString(), test.keyIdString; g != e {
|
|
||||||
t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e)
|
|
||||||
}
|
|
||||||
if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e {
|
|
||||||
t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPublicKeySerialize(t *testing.T) {
|
|
||||||
for i, test := range pubKeyTests {
|
|
||||||
packet, err := Read(readerFromHex(test.hexData))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("#%d: Read error: %s", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
pk, ok := packet.(*PublicKey)
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("#%d: failed to parse, got: %#v", i, packet)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
serializeBuf := bytes.NewBuffer(nil)
|
|
||||||
err = pk.Serialize(serializeBuf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("#%d: failed to serialize: %s", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
packet, err = Read(serializeBuf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("#%d: Read error (from serialized data): %s", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
pk, ok = packet.(*PublicKey)
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("#%d: failed to parse serialized data, got: %#v", i, packet)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEcc384Serialize(t *testing.T) {
|
|
||||||
r := readerFromHex(ecc384PubHex)
|
|
||||||
var w bytes.Buffer
|
|
||||||
for i := 0; i < 2; i++ {
|
|
||||||
// Public key
|
|
||||||
p, err := Read(r)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
pubkey := p.(*PublicKey)
|
|
||||||
if !bytes.Equal(pubkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) {
|
|
||||||
t.Errorf("Unexpected pubkey OID: %x", pubkey.ec.oid)
|
|
||||||
}
|
|
||||||
if !bytes.Equal(pubkey.ec.p.bytes[:5], []byte{0x04, 0xf6, 0xb8, 0xc5, 0xac}) {
|
|
||||||
t.Errorf("Unexpected pubkey P[:5]: %x", pubkey.ec.p.bytes)
|
|
||||||
}
|
|
||||||
if pubkey.KeyId != 0x098033880F54719F {
|
|
||||||
t.Errorf("Unexpected pubkey ID: %x", pubkey.KeyId)
|
|
||||||
}
|
|
||||||
err = pubkey.Serialize(&w)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
// User ID
|
|
||||||
p, err = Read(r)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
uid := p.(*UserId)
|
|
||||||
if uid.Id != "ec_dsa_dh_384 <openpgp@brainhub.org>" {
|
|
||||||
t.Error("Unexpected UID:", uid.Id)
|
|
||||||
}
|
|
||||||
err = uid.Serialize(&w)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
// User ID Sig
|
|
||||||
p, err = Read(r)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
uidSig := p.(*Signature)
|
|
||||||
err = pubkey.VerifyUserIdSignature(uid.Id, pubkey, uidSig)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err, ": UID")
|
|
||||||
}
|
|
||||||
err = uidSig.Serialize(&w)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
// Subkey
|
|
||||||
p, err = Read(r)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
subkey := p.(*PublicKey)
|
|
||||||
if !bytes.Equal(subkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) {
|
|
||||||
t.Errorf("Unexpected subkey OID: %x", subkey.ec.oid)
|
|
||||||
}
|
|
||||||
if !bytes.Equal(subkey.ec.p.bytes[:5], []byte{0x04, 0x2f, 0xaa, 0x84, 0x02}) {
|
|
||||||
t.Errorf("Unexpected subkey P[:5]: %x", subkey.ec.p.bytes)
|
|
||||||
}
|
|
||||||
if subkey.ecdh.KdfHash != 0x09 {
|
|
||||||
t.Error("Expected KDF hash function SHA384 (0x09), got", subkey.ecdh.KdfHash)
|
|
||||||
}
|
|
||||||
if subkey.ecdh.KdfAlgo != 0x09 {
|
|
||||||
t.Error("Expected KDF symmetric alg AES256 (0x09), got", subkey.ecdh.KdfAlgo)
|
|
||||||
}
|
|
||||||
if subkey.KeyId != 0xAA8B938F9A201946 {
|
|
||||||
t.Errorf("Unexpected subkey ID: %x", subkey.KeyId)
|
|
||||||
}
|
|
||||||
err = subkey.Serialize(&w)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
// Subkey Sig
|
|
||||||
p, err = Read(r)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
subkeySig := p.(*Signature)
|
|
||||||
err = pubkey.VerifyKeySignature(subkey, subkeySig)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
err = subkeySig.Serialize(&w)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
// Now read back what we've written again
|
|
||||||
r = bytes.NewBuffer(w.Bytes())
|
|
||||||
w.Reset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb"
|
|
||||||
|
|
||||||
const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001"
|
|
||||||
|
|
||||||
const dsaFingerprintHex = "eece4c094db002103714c63c8e8fbe54062f19ed"
|
|
||||||
|
|
||||||
const dsaPkDataHex = "9901a2044d432f89110400cd581334f0d7a1e1bdc8b9d6d8c0baf68793632735d2bb0903224cbaa1dfbf35a60ee7a13b92643421e1eb41aa8d79bea19a115a677f6b8ba3c7818ce53a6c2a24a1608bd8b8d6e55c5090cbde09dd26e356267465ae25e69ec8bdd57c7bbb2623e4d73336f73a0a9098f7f16da2e25252130fd694c0e8070c55a812a423ae7f00a0ebf50e70c2f19c3520a551bd4b08d30f23530d3d03ff7d0bf4a53a64a09dc5e6e6e35854b7d70c882b0c60293401958b1bd9e40abec3ea05ba87cf64899299d4bd6aa7f459c201d3fbbd6c82004bdc5e8a9eb8082d12054cc90fa9d4ec251a843236a588bf49552441817436c4f43326966fe85447d4e6d0acf8fa1ef0f014730770603ad7634c3088dc52501c237328417c31c89ed70400b2f1a98b0bf42f11fefc430704bebbaa41d9f355600c3facee1e490f64208e0e094ea55e3a598a219a58500bf78ac677b670a14f4e47e9cf8eab4f368cc1ddcaa18cc59309d4cc62dd4f680e73e6cc3e1ce87a84d0925efbcb26c575c093fc42eecf45135fabf6403a25c2016e1774c0484e440a18319072c617cc97ac0a3bb0"
|
|
||||||
|
|
||||||
const ecdsaFingerprintHex = "9892270b38b8980b05c8d56d43fe956c542ca00b"
|
|
||||||
|
|
||||||
const ecdsaPkDataHex = "9893045071c29413052b8104002304230401f4867769cedfa52c325018896245443968e52e51d0c2df8d939949cb5b330f2921711fbee1c9b9dddb95d15cb0255e99badeddda7cc23d9ddcaacbc290969b9f24019375d61c2e4e3b36953a28d8b2bc95f78c3f1d592fb24499be348656a7b17e3963187b4361afe497bc5f9f81213f04069f8e1fb9e6a6290ae295ca1a92b894396cb4"
|
|
||||||
|
|
||||||
// Source: https://sites.google.com/site/brainhub/pgpecckeys#TOC-ECC-NIST-P-384-key
|
|
||||||
const ecc384PubHex = `99006f044d53059213052b81040022030304f6b8c5aced5b84ef9f4a209db2e4a9dfb70d28cb8c10ecd57674a9fa5a67389942b62d5e51367df4c7bfd3f8e500feecf07ed265a621a8ebbbe53e947ec78c677eba143bd1533c2b350e1c29f82313e1e1108eba063be1e64b10e6950e799c2db42465635f6473615f64685f333834203c6f70656e70677040627261696e6875622e6f72673e8900cb04101309005305024d530592301480000000002000077072656665727265642d656d61696c2d656e636f64696e67407067702e636f6d7067706d696d65040b090807021901051b03000000021602051e010000000415090a08000a0910098033880f54719fca2b0180aa37350968bd5f115afd8ce7bc7b103822152dbff06d0afcda835329510905b98cb469ba208faab87c7412b799e7b633017f58364ea480e8a1a3f253a0c5f22c446e8be9a9fce6210136ee30811abbd49139de28b5bdf8dc36d06ae748579e9ff503b90073044d53059212052b810400220303042faa84024a20b6735c4897efa5bfb41bf85b7eefeab5ca0cb9ffc8ea04a46acb25534a577694f9e25340a4ab5223a9dd1eda530c8aa2e6718db10d7e672558c7736fe09369ea5739a2a3554bf16d41faa50562f11c6d39bbd5dffb6b9a9ec9180301090989008404181309000c05024d530592051b0c000000000a0910098033880f54719f80970180eee7a6d8fcee41ee4f9289df17f9bcf9d955dca25c583b94336f3a2b2d4986dc5cf417b8d2dc86f741a9e1a6d236c0e3017d1c76575458a0cfb93ae8a2b274fcc65ceecd7a91eec83656ba13219969f06945b48c56bd04152c3a0553c5f2f4bd1267`
|
|
280
vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go
generated
vendored
280
vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go
generated
vendored
|
@ -1,280 +0,0 @@
|
||||||
// Copyright 2013 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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto"
|
|
||||||
"crypto/md5"
|
|
||||||
"crypto/rsa"
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"hash"
|
|
||||||
"io"
|
|
||||||
"math/big"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PublicKeyV3 represents older, version 3 public keys. These keys are less secure and
|
|
||||||
// should not be used for signing or encrypting. They are supported here only for
|
|
||||||
// parsing version 3 key material and validating signatures.
|
|
||||||
// See RFC 4880, section 5.5.2.
|
|
||||||
type PublicKeyV3 struct {
|
|
||||||
CreationTime time.Time
|
|
||||||
DaysToExpire uint16
|
|
||||||
PubKeyAlgo PublicKeyAlgorithm
|
|
||||||
PublicKey *rsa.PublicKey
|
|
||||||
Fingerprint [16]byte
|
|
||||||
KeyId uint64
|
|
||||||
IsSubkey bool
|
|
||||||
|
|
||||||
n, e parsedMPI
|
|
||||||
}
|
|
||||||
|
|
||||||
// newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey.
|
|
||||||
// Included here for testing purposes only. RFC 4880, section 5.5.2:
|
|
||||||
// "an implementation MUST NOT generate a V3 key, but MAY accept it."
|
|
||||||
func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 {
|
|
||||||
pk := &PublicKeyV3{
|
|
||||||
CreationTime: creationTime,
|
|
||||||
PublicKey: pub,
|
|
||||||
n: fromBig(pub.N),
|
|
||||||
e: fromBig(big.NewInt(int64(pub.E))),
|
|
||||||
}
|
|
||||||
|
|
||||||
pk.setFingerPrintAndKeyId()
|
|
||||||
return pk
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pk *PublicKeyV3) parse(r io.Reader) (err error) {
|
|
||||||
// RFC 4880, section 5.5.2
|
|
||||||
var buf [8]byte
|
|
||||||
if _, err = readFull(r, buf[:]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if buf[0] < 2 || buf[0] > 3 {
|
|
||||||
return errors.UnsupportedError("public key version")
|
|
||||||
}
|
|
||||||
pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
|
|
||||||
pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7])
|
|
||||||
pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7])
|
|
||||||
switch pk.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
|
|
||||||
err = pk.parseRSA(r)
|
|
||||||
default:
|
|
||||||
err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pk.setFingerPrintAndKeyId()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pk *PublicKeyV3) setFingerPrintAndKeyId() {
|
|
||||||
// RFC 4880, section 12.2
|
|
||||||
fingerPrint := md5.New()
|
|
||||||
fingerPrint.Write(pk.n.bytes)
|
|
||||||
fingerPrint.Write(pk.e.bytes)
|
|
||||||
fingerPrint.Sum(pk.Fingerprint[:0])
|
|
||||||
pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
|
|
||||||
// section 5.5.2.
|
|
||||||
func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) {
|
|
||||||
if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// RFC 4880 Section 12.2 requires the low 8 bytes of the
|
|
||||||
// modulus to form the key id.
|
|
||||||
if len(pk.n.bytes) < 8 {
|
|
||||||
return errors.StructuralError("v3 public key modulus is too short")
|
|
||||||
}
|
|
||||||
if len(pk.e.bytes) > 3 {
|
|
||||||
err = errors.UnsupportedError("large public exponent")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)}
|
|
||||||
for i := 0; i < len(pk.e.bytes); i++ {
|
|
||||||
rsa.E <<= 8
|
|
||||||
rsa.E |= int(pk.e.bytes[i])
|
|
||||||
}
|
|
||||||
pk.PublicKey = rsa
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
|
|
||||||
// The prefix is used when calculating a signature over this public key. See
|
|
||||||
// RFC 4880, section 5.2.4.
|
|
||||||
func (pk *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) {
|
|
||||||
var pLength uint16
|
|
||||||
switch pk.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
|
|
||||||
pLength += 2 + uint16(len(pk.n.bytes))
|
|
||||||
pLength += 2 + uint16(len(pk.e.bytes))
|
|
||||||
default:
|
|
||||||
panic("unknown public key algorithm")
|
|
||||||
}
|
|
||||||
pLength += 6
|
|
||||||
w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) {
|
|
||||||
length := 8 // 8 byte header
|
|
||||||
|
|
||||||
switch pk.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
|
|
||||||
length += 2 + len(pk.n.bytes)
|
|
||||||
length += 2 + len(pk.e.bytes)
|
|
||||||
default:
|
|
||||||
panic("unknown public key algorithm")
|
|
||||||
}
|
|
||||||
|
|
||||||
packetType := packetTypePublicKey
|
|
||||||
if pk.IsSubkey {
|
|
||||||
packetType = packetTypePublicSubkey
|
|
||||||
}
|
|
||||||
if err = serializeHeader(w, packetType, length); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return pk.serializeWithoutHeaders(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
// serializeWithoutHeaders marshals the PublicKey to w in the form of an
|
|
||||||
// OpenPGP public key packet, not including the packet header.
|
|
||||||
func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) {
|
|
||||||
var buf [8]byte
|
|
||||||
// Version 3
|
|
||||||
buf[0] = 3
|
|
||||||
// Creation time
|
|
||||||
t := uint32(pk.CreationTime.Unix())
|
|
||||||
buf[1] = byte(t >> 24)
|
|
||||||
buf[2] = byte(t >> 16)
|
|
||||||
buf[3] = byte(t >> 8)
|
|
||||||
buf[4] = byte(t)
|
|
||||||
// Days to expire
|
|
||||||
buf[5] = byte(pk.DaysToExpire >> 8)
|
|
||||||
buf[6] = byte(pk.DaysToExpire)
|
|
||||||
// Public key algorithm
|
|
||||||
buf[7] = byte(pk.PubKeyAlgo)
|
|
||||||
|
|
||||||
if _, err = w.Write(buf[:]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch pk.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
|
|
||||||
return writeMPIs(w, pk.n, pk.e)
|
|
||||||
}
|
|
||||||
return errors.InvalidArgumentError("bad public-key algorithm")
|
|
||||||
}
|
|
||||||
|
|
||||||
// CanSign returns true iff this public key can generate signatures
|
|
||||||
func (pk *PublicKeyV3) CanSign() bool {
|
|
||||||
return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifySignatureV3 returns nil iff sig is a valid signature, made by this
|
|
||||||
// public key, of the data hashed into signed. signed is mutated by this call.
|
|
||||||
func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) {
|
|
||||||
if !pk.CanSign() {
|
|
||||||
return errors.InvalidArgumentError("public key cannot generate signatures")
|
|
||||||
}
|
|
||||||
|
|
||||||
suffix := make([]byte, 5)
|
|
||||||
suffix[0] = byte(sig.SigType)
|
|
||||||
binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix()))
|
|
||||||
signed.Write(suffix)
|
|
||||||
hashBytes := signed.Sum(nil)
|
|
||||||
|
|
||||||
if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
|
|
||||||
return errors.SignatureError("hash tag doesn't match")
|
|
||||||
}
|
|
||||||
|
|
||||||
if pk.PubKeyAlgo != sig.PubKeyAlgo {
|
|
||||||
return errors.InvalidArgumentError("public key and signature use different algorithms")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch pk.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
|
|
||||||
if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil {
|
|
||||||
return errors.SignatureError("RSA verification failure")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
// V3 public keys only support RSA.
|
|
||||||
panic("shouldn't happen")
|
|
||||||
}
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this
|
|
||||||
// public key, that id is the identity of pub.
|
|
||||||
func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) {
|
|
||||||
h, err := userIdSignatureV3Hash(id, pk, sig.Hash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return pk.VerifySignatureV3(h, sig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this
|
|
||||||
// public key, of signed.
|
|
||||||
func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) {
|
|
||||||
h, err := keySignatureHash(pk, signed, sig.Hash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return pk.VerifySignatureV3(h, sig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// userIdSignatureV3Hash returns a Hash of the message that needs to be signed
|
|
||||||
// to assert that pk is a valid key for id.
|
|
||||||
func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) {
|
|
||||||
if !hfn.Available() {
|
|
||||||
return nil, errors.UnsupportedError("hash function")
|
|
||||||
}
|
|
||||||
h = hfn.New()
|
|
||||||
|
|
||||||
// RFC 4880, section 5.2.4
|
|
||||||
pk.SerializeSignaturePrefix(h)
|
|
||||||
pk.serializeWithoutHeaders(h)
|
|
||||||
|
|
||||||
h.Write([]byte(id))
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// KeyIdString returns the public key's fingerprint in capital hex
|
|
||||||
// (e.g. "6C7EE1B8621CC013").
|
|
||||||
func (pk *PublicKeyV3) KeyIdString() string {
|
|
||||||
return fmt.Sprintf("%X", pk.KeyId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// KeyIdShortString returns the short form of public key's fingerprint
|
|
||||||
// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
|
|
||||||
func (pk *PublicKeyV3) KeyIdShortString() string {
|
|
||||||
return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BitLength returns the bit length for the given public key.
|
|
||||||
func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) {
|
|
||||||
switch pk.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
|
|
||||||
bitLength = pk.n.bitLength
|
|
||||||
default:
|
|
||||||
err = errors.InvalidArgumentError("bad public-key algorithm")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
82
vendor/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go
generated
vendored
82
vendor/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go
generated
vendored
|
@ -1,82 +0,0 @@
|
||||||
// Copyright 2013 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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var pubKeyV3Test = struct {
|
|
||||||
hexFingerprint string
|
|
||||||
creationTime time.Time
|
|
||||||
pubKeyAlgo PublicKeyAlgorithm
|
|
||||||
keyId uint64
|
|
||||||
keyIdString string
|
|
||||||
keyIdShort string
|
|
||||||
}{
|
|
||||||
"103BECF5BD1E837C89D19E98487767F7",
|
|
||||||
time.Unix(779753634, 0),
|
|
||||||
PubKeyAlgoRSA,
|
|
||||||
0xDE0F188A5DA5E3C9,
|
|
||||||
"DE0F188A5DA5E3C9",
|
|
||||||
"5DA5E3C9"}
|
|
||||||
|
|
||||||
func TestPublicKeyV3Read(t *testing.T) {
|
|
||||||
i, test := 0, pubKeyV3Test
|
|
||||||
packet, err := Read(v3KeyReader(t))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("#%d: Read error: %s", i, err)
|
|
||||||
}
|
|
||||||
pk, ok := packet.(*PublicKeyV3)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("#%d: failed to parse, got: %#v", i, packet)
|
|
||||||
}
|
|
||||||
if pk.PubKeyAlgo != test.pubKeyAlgo {
|
|
||||||
t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo)
|
|
||||||
}
|
|
||||||
if !pk.CreationTime.Equal(test.creationTime) {
|
|
||||||
t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime)
|
|
||||||
}
|
|
||||||
expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint)
|
|
||||||
if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) {
|
|
||||||
t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint)
|
|
||||||
}
|
|
||||||
if pk.KeyId != test.keyId {
|
|
||||||
t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId)
|
|
||||||
}
|
|
||||||
if g, e := pk.KeyIdString(), test.keyIdString; g != e {
|
|
||||||
t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e)
|
|
||||||
}
|
|
||||||
if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e {
|
|
||||||
t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPublicKeyV3Serialize(t *testing.T) {
|
|
||||||
//for i, test := range pubKeyV3Tests {
|
|
||||||
i := 0
|
|
||||||
packet, err := Read(v3KeyReader(t))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("#%d: Read error: %s", i, err)
|
|
||||||
}
|
|
||||||
pk, ok := packet.(*PublicKeyV3)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("#%d: failed to parse, got: %#v", i, packet)
|
|
||||||
}
|
|
||||||
var serializeBuf bytes.Buffer
|
|
||||||
if err = pk.Serialize(&serializeBuf); err != nil {
|
|
||||||
t.Fatalf("#%d: failed to serialize: %s", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if packet, err = Read(bytes.NewBuffer(serializeBuf.Bytes())); err != nil {
|
|
||||||
t.Fatalf("#%d: Read error (from serialized data): %s", i, err)
|
|
||||||
}
|
|
||||||
if pk, ok = packet.(*PublicKeyV3); !ok {
|
|
||||||
t.Fatalf("#%d: failed to parse serialized data, got: %#v", i, packet)
|
|
||||||
}
|
|
||||||
}
|
|
76
vendor/golang.org/x/crypto/openpgp/packet/reader.go
generated
vendored
76
vendor/golang.org/x/crypto/openpgp/packet/reader.go
generated
vendored
|
@ -1,76 +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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"golang.org/x/crypto/openpgp/errors"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Reader reads packets from an io.Reader and allows packets to be 'unread' so
|
|
||||||
// that they result from the next call to Next.
|
|
||||||
type Reader struct {
|
|
||||||
q []Packet
|
|
||||||
readers []io.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
// New io.Readers are pushed when a compressed or encrypted packet is processed
|
|
||||||
// and recursively treated as a new source of packets. However, a carefully
|
|
||||||
// crafted packet can trigger an infinite recursive sequence of packets. See
|
|
||||||
// http://mumble.net/~campbell/misc/pgp-quine
|
|
||||||
// https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4402
|
|
||||||
// This constant limits the number of recursive packets that may be pushed.
|
|
||||||
const maxReaders = 32
|
|
||||||
|
|
||||||
// Next returns the most recently unread Packet, or reads another packet from
|
|
||||||
// the top-most io.Reader. Unknown packet types are skipped.
|
|
||||||
func (r *Reader) Next() (p Packet, err error) {
|
|
||||||
if len(r.q) > 0 {
|
|
||||||
p = r.q[len(r.q)-1]
|
|
||||||
r.q = r.q[:len(r.q)-1]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for len(r.readers) > 0 {
|
|
||||||
p, err = Read(r.readers[len(r.readers)-1])
|
|
||||||
if err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err == io.EOF {
|
|
||||||
r.readers = r.readers[:len(r.readers)-1]
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, ok := err.(errors.UnknownPacketTypeError); !ok {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, io.EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push causes the Reader to start reading from a new io.Reader. When an EOF
|
|
||||||
// error is seen from the new io.Reader, it is popped and the Reader continues
|
|
||||||
// to read from the next most recent io.Reader. Push returns a StructuralError
|
|
||||||
// if pushing the reader would exceed the maximum recursion level, otherwise it
|
|
||||||
// returns nil.
|
|
||||||
func (r *Reader) Push(reader io.Reader) (err error) {
|
|
||||||
if len(r.readers) >= maxReaders {
|
|
||||||
return errors.StructuralError("too many layers of packets")
|
|
||||||
}
|
|
||||||
r.readers = append(r.readers, reader)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unread causes the given Packet to be returned from the next call to Next.
|
|
||||||
func (r *Reader) Unread(p Packet) {
|
|
||||||
r.q = append(r.q, p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewReader(r io.Reader) *Reader {
|
|
||||||
return &Reader{
|
|
||||||
q: nil,
|
|
||||||
readers: []io.Reader{r},
|
|
||||||
}
|
|
||||||
}
|
|
706
vendor/golang.org/x/crypto/openpgp/packet/signature.go
generated
vendored
706
vendor/golang.org/x/crypto/openpgp/packet/signature.go
generated
vendored
|
@ -1,706 +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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto"
|
|
||||||
"crypto/dsa"
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/rsa"
|
|
||||||
"encoding/binary"
|
|
||||||
"hash"
|
|
||||||
"io"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp/errors"
|
|
||||||
"golang.org/x/crypto/openpgp/s2k"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// See RFC 4880, section 5.2.3.21 for details.
|
|
||||||
KeyFlagCertify = 1 << iota
|
|
||||||
KeyFlagSign
|
|
||||||
KeyFlagEncryptCommunications
|
|
||||||
KeyFlagEncryptStorage
|
|
||||||
)
|
|
||||||
|
|
||||||
// Signature represents a signature. See RFC 4880, section 5.2.
|
|
||||||
type Signature struct {
|
|
||||||
SigType SignatureType
|
|
||||||
PubKeyAlgo PublicKeyAlgorithm
|
|
||||||
Hash crypto.Hash
|
|
||||||
|
|
||||||
// HashSuffix is extra data that is hashed in after the signed data.
|
|
||||||
HashSuffix []byte
|
|
||||||
// HashTag contains the first two bytes of the hash for fast rejection
|
|
||||||
// of bad signed data.
|
|
||||||
HashTag [2]byte
|
|
||||||
CreationTime time.Time
|
|
||||||
|
|
||||||
RSASignature parsedMPI
|
|
||||||
DSASigR, DSASigS parsedMPI
|
|
||||||
ECDSASigR, ECDSASigS parsedMPI
|
|
||||||
|
|
||||||
// rawSubpackets contains the unparsed subpackets, in order.
|
|
||||||
rawSubpackets []outputSubpacket
|
|
||||||
|
|
||||||
// The following are optional so are nil when not included in the
|
|
||||||
// signature.
|
|
||||||
|
|
||||||
SigLifetimeSecs, KeyLifetimeSecs *uint32
|
|
||||||
PreferredSymmetric, PreferredHash, PreferredCompression []uint8
|
|
||||||
IssuerKeyId *uint64
|
|
||||||
IsPrimaryId *bool
|
|
||||||
|
|
||||||
// FlagsValid is set if any flags were given. See RFC 4880, section
|
|
||||||
// 5.2.3.21 for details.
|
|
||||||
FlagsValid bool
|
|
||||||
FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool
|
|
||||||
|
|
||||||
// RevocationReason is set if this signature has been revoked.
|
|
||||||
// See RFC 4880, section 5.2.3.23 for details.
|
|
||||||
RevocationReason *uint8
|
|
||||||
RevocationReasonText string
|
|
||||||
|
|
||||||
// MDC is set if this signature has a feature packet that indicates
|
|
||||||
// support for MDC subpackets.
|
|
||||||
MDC bool
|
|
||||||
|
|
||||||
// EmbeddedSignature, if non-nil, is a signature of the parent key, by
|
|
||||||
// this key. This prevents an attacker from claiming another's signing
|
|
||||||
// subkey as their own.
|
|
||||||
EmbeddedSignature *Signature
|
|
||||||
|
|
||||||
outSubpackets []outputSubpacket
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sig *Signature) parse(r io.Reader) (err error) {
|
|
||||||
// RFC 4880, section 5.2.3
|
|
||||||
var buf [5]byte
|
|
||||||
_, err = readFull(r, buf[:1])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if buf[0] != 4 {
|
|
||||||
err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = readFull(r, buf[:5])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig.SigType = SignatureType(buf[0])
|
|
||||||
sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1])
|
|
||||||
switch sig.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
|
|
||||||
default:
|
|
||||||
err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var ok bool
|
|
||||||
sig.Hash, ok = s2k.HashIdToHash(buf[2])
|
|
||||||
if !ok {
|
|
||||||
return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
|
|
||||||
}
|
|
||||||
|
|
||||||
hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4])
|
|
||||||
l := 6 + hashedSubpacketsLength
|
|
||||||
sig.HashSuffix = make([]byte, l+6)
|
|
||||||
sig.HashSuffix[0] = 4
|
|
||||||
copy(sig.HashSuffix[1:], buf[:5])
|
|
||||||
hashedSubpackets := sig.HashSuffix[6:l]
|
|
||||||
_, err = readFull(r, hashedSubpackets)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// See RFC 4880, section 5.2.4
|
|
||||||
trailer := sig.HashSuffix[l:]
|
|
||||||
trailer[0] = 4
|
|
||||||
trailer[1] = 0xff
|
|
||||||
trailer[2] = uint8(l >> 24)
|
|
||||||
trailer[3] = uint8(l >> 16)
|
|
||||||
trailer[4] = uint8(l >> 8)
|
|
||||||
trailer[5] = uint8(l)
|
|
||||||
|
|
||||||
err = parseSignatureSubpackets(sig, hashedSubpackets, true)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = readFull(r, buf[:2])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1])
|
|
||||||
unhashedSubpackets := make([]byte, unhashedSubpacketsLength)
|
|
||||||
_, err = readFull(r, unhashedSubpackets)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = parseSignatureSubpackets(sig, unhashedSubpackets, false)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = readFull(r, sig.HashTag[:2])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch sig.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
|
|
||||||
sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
|
|
||||||
case PubKeyAlgoDSA:
|
|
||||||
sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r)
|
|
||||||
if err == nil {
|
|
||||||
sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
|
|
||||||
}
|
|
||||||
case PubKeyAlgoECDSA:
|
|
||||||
sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r)
|
|
||||||
if err == nil {
|
|
||||||
sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseSignatureSubpackets parses subpackets of the main signature packet. See
|
|
||||||
// RFC 4880, section 5.2.3.1.
|
|
||||||
func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) {
|
|
||||||
for len(subpackets) > 0 {
|
|
||||||
subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if sig.CreationTime.IsZero() {
|
|
||||||
err = errors.StructuralError("no creation time in signature")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type signatureSubpacketType uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
creationTimeSubpacket signatureSubpacketType = 2
|
|
||||||
signatureExpirationSubpacket signatureSubpacketType = 3
|
|
||||||
keyExpirationSubpacket signatureSubpacketType = 9
|
|
||||||
prefSymmetricAlgosSubpacket signatureSubpacketType = 11
|
|
||||||
issuerSubpacket signatureSubpacketType = 16
|
|
||||||
prefHashAlgosSubpacket signatureSubpacketType = 21
|
|
||||||
prefCompressionSubpacket signatureSubpacketType = 22
|
|
||||||
primaryUserIdSubpacket signatureSubpacketType = 25
|
|
||||||
keyFlagsSubpacket signatureSubpacketType = 27
|
|
||||||
reasonForRevocationSubpacket signatureSubpacketType = 29
|
|
||||||
featuresSubpacket signatureSubpacketType = 30
|
|
||||||
embeddedSignatureSubpacket signatureSubpacketType = 32
|
|
||||||
)
|
|
||||||
|
|
||||||
// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
|
|
||||||
func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) {
|
|
||||||
// RFC 4880, section 5.2.3.1
|
|
||||||
var (
|
|
||||||
length uint32
|
|
||||||
packetType signatureSubpacketType
|
|
||||||
isCritical bool
|
|
||||||
)
|
|
||||||
switch {
|
|
||||||
case subpacket[0] < 192:
|
|
||||||
length = uint32(subpacket[0])
|
|
||||||
subpacket = subpacket[1:]
|
|
||||||
case subpacket[0] < 255:
|
|
||||||
if len(subpacket) < 2 {
|
|
||||||
goto Truncated
|
|
||||||
}
|
|
||||||
length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192
|
|
||||||
subpacket = subpacket[2:]
|
|
||||||
default:
|
|
||||||
if len(subpacket) < 5 {
|
|
||||||
goto Truncated
|
|
||||||
}
|
|
||||||
length = uint32(subpacket[1])<<24 |
|
|
||||||
uint32(subpacket[2])<<16 |
|
|
||||||
uint32(subpacket[3])<<8 |
|
|
||||||
uint32(subpacket[4])
|
|
||||||
subpacket = subpacket[5:]
|
|
||||||
}
|
|
||||||
if length > uint32(len(subpacket)) {
|
|
||||||
goto Truncated
|
|
||||||
}
|
|
||||||
rest = subpacket[length:]
|
|
||||||
subpacket = subpacket[:length]
|
|
||||||
if len(subpacket) == 0 {
|
|
||||||
err = errors.StructuralError("zero length signature subpacket")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
packetType = signatureSubpacketType(subpacket[0] & 0x7f)
|
|
||||||
isCritical = subpacket[0]&0x80 == 0x80
|
|
||||||
subpacket = subpacket[1:]
|
|
||||||
sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket})
|
|
||||||
switch packetType {
|
|
||||||
case creationTimeSubpacket:
|
|
||||||
if !isHashed {
|
|
||||||
err = errors.StructuralError("signature creation time in non-hashed area")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(subpacket) != 4 {
|
|
||||||
err = errors.StructuralError("signature creation time not four bytes")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t := binary.BigEndian.Uint32(subpacket)
|
|
||||||
sig.CreationTime = time.Unix(int64(t), 0)
|
|
||||||
case signatureExpirationSubpacket:
|
|
||||||
// Signature expiration time, section 5.2.3.10
|
|
||||||
if !isHashed {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(subpacket) != 4 {
|
|
||||||
err = errors.StructuralError("expiration subpacket with bad length")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig.SigLifetimeSecs = new(uint32)
|
|
||||||
*sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket)
|
|
||||||
case keyExpirationSubpacket:
|
|
||||||
// Key expiration time, section 5.2.3.6
|
|
||||||
if !isHashed {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(subpacket) != 4 {
|
|
||||||
err = errors.StructuralError("key expiration subpacket with bad length")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig.KeyLifetimeSecs = new(uint32)
|
|
||||||
*sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket)
|
|
||||||
case prefSymmetricAlgosSubpacket:
|
|
||||||
// Preferred symmetric algorithms, section 5.2.3.7
|
|
||||||
if !isHashed {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig.PreferredSymmetric = make([]byte, len(subpacket))
|
|
||||||
copy(sig.PreferredSymmetric, subpacket)
|
|
||||||
case issuerSubpacket:
|
|
||||||
// Issuer, section 5.2.3.5
|
|
||||||
if len(subpacket) != 8 {
|
|
||||||
err = errors.StructuralError("issuer subpacket with bad length")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig.IssuerKeyId = new(uint64)
|
|
||||||
*sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket)
|
|
||||||
case prefHashAlgosSubpacket:
|
|
||||||
// Preferred hash algorithms, section 5.2.3.8
|
|
||||||
if !isHashed {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig.PreferredHash = make([]byte, len(subpacket))
|
|
||||||
copy(sig.PreferredHash, subpacket)
|
|
||||||
case prefCompressionSubpacket:
|
|
||||||
// Preferred compression algorithms, section 5.2.3.9
|
|
||||||
if !isHashed {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig.PreferredCompression = make([]byte, len(subpacket))
|
|
||||||
copy(sig.PreferredCompression, subpacket)
|
|
||||||
case primaryUserIdSubpacket:
|
|
||||||
// Primary User ID, section 5.2.3.19
|
|
||||||
if !isHashed {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(subpacket) != 1 {
|
|
||||||
err = errors.StructuralError("primary user id subpacket with bad length")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig.IsPrimaryId = new(bool)
|
|
||||||
if subpacket[0] > 0 {
|
|
||||||
*sig.IsPrimaryId = true
|
|
||||||
}
|
|
||||||
case keyFlagsSubpacket:
|
|
||||||
// Key flags, section 5.2.3.21
|
|
||||||
if !isHashed {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(subpacket) == 0 {
|
|
||||||
err = errors.StructuralError("empty key flags subpacket")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig.FlagsValid = true
|
|
||||||
if subpacket[0]&KeyFlagCertify != 0 {
|
|
||||||
sig.FlagCertify = true
|
|
||||||
}
|
|
||||||
if subpacket[0]&KeyFlagSign != 0 {
|
|
||||||
sig.FlagSign = true
|
|
||||||
}
|
|
||||||
if subpacket[0]&KeyFlagEncryptCommunications != 0 {
|
|
||||||
sig.FlagEncryptCommunications = true
|
|
||||||
}
|
|
||||||
if subpacket[0]&KeyFlagEncryptStorage != 0 {
|
|
||||||
sig.FlagEncryptStorage = true
|
|
||||||
}
|
|
||||||
case reasonForRevocationSubpacket:
|
|
||||||
// Reason For Revocation, section 5.2.3.23
|
|
||||||
if !isHashed {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(subpacket) == 0 {
|
|
||||||
err = errors.StructuralError("empty revocation reason subpacket")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig.RevocationReason = new(uint8)
|
|
||||||
*sig.RevocationReason = subpacket[0]
|
|
||||||
sig.RevocationReasonText = string(subpacket[1:])
|
|
||||||
case featuresSubpacket:
|
|
||||||
// Features subpacket, section 5.2.3.24 specifies a very general
|
|
||||||
// mechanism for OpenPGP implementations to signal support for new
|
|
||||||
// features. In practice, the subpacket is used exclusively to
|
|
||||||
// indicate support for MDC-protected encryption.
|
|
||||||
sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1
|
|
||||||
case embeddedSignatureSubpacket:
|
|
||||||
// Only usage is in signatures that cross-certify
|
|
||||||
// signing subkeys. section 5.2.3.26 describes the
|
|
||||||
// format, with its usage described in section 11.1
|
|
||||||
if sig.EmbeddedSignature != nil {
|
|
||||||
err = errors.StructuralError("Cannot have multiple embedded signatures")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig.EmbeddedSignature = new(Signature)
|
|
||||||
// Embedded signatures are required to be v4 signatures see
|
|
||||||
// section 12.1. However, we only parse v4 signatures in this
|
|
||||||
// file anyway.
|
|
||||||
if err := sig.EmbeddedSignature.parse(bytes.NewBuffer(subpacket)); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding {
|
|
||||||
return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType)))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if isCritical {
|
|
||||||
err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
|
|
||||||
Truncated:
|
|
||||||
err = errors.StructuralError("signature subpacket truncated")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// subpacketLengthLength returns the length, in bytes, of an encoded length value.
|
|
||||||
func subpacketLengthLength(length int) int {
|
|
||||||
if length < 192 {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
if length < 16320 {
|
|
||||||
return 2
|
|
||||||
}
|
|
||||||
return 5
|
|
||||||
}
|
|
||||||
|
|
||||||
// serializeSubpacketLength marshals the given length into to.
|
|
||||||
func serializeSubpacketLength(to []byte, length int) int {
|
|
||||||
// RFC 4880, Section 4.2.2.
|
|
||||||
if length < 192 {
|
|
||||||
to[0] = byte(length)
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
if length < 16320 {
|
|
||||||
length -= 192
|
|
||||||
to[0] = byte((length >> 8) + 192)
|
|
||||||
to[1] = byte(length)
|
|
||||||
return 2
|
|
||||||
}
|
|
||||||
to[0] = 255
|
|
||||||
to[1] = byte(length >> 24)
|
|
||||||
to[2] = byte(length >> 16)
|
|
||||||
to[3] = byte(length >> 8)
|
|
||||||
to[4] = byte(length)
|
|
||||||
return 5
|
|
||||||
}
|
|
||||||
|
|
||||||
// subpacketsLength returns the serialized length, in bytes, of the given
|
|
||||||
// subpackets.
|
|
||||||
func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) {
|
|
||||||
for _, subpacket := range subpackets {
|
|
||||||
if subpacket.hashed == hashed {
|
|
||||||
length += subpacketLengthLength(len(subpacket.contents) + 1)
|
|
||||||
length += 1 // type byte
|
|
||||||
length += len(subpacket.contents)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// serializeSubpackets marshals the given subpackets into to.
|
|
||||||
func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) {
|
|
||||||
for _, subpacket := range subpackets {
|
|
||||||
if subpacket.hashed == hashed {
|
|
||||||
n := serializeSubpacketLength(to, len(subpacket.contents)+1)
|
|
||||||
to[n] = byte(subpacket.subpacketType)
|
|
||||||
to = to[1+n:]
|
|
||||||
n = copy(to, subpacket.contents)
|
|
||||||
to = to[n:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// KeyExpired returns whether sig is a self-signature of a key that has
|
|
||||||
// expired.
|
|
||||||
func (sig *Signature) KeyExpired(currentTime time.Time) bool {
|
|
||||||
if sig.KeyLifetimeSecs == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second)
|
|
||||||
return currentTime.After(expiry)
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
|
|
||||||
func (sig *Signature) buildHashSuffix() (err error) {
|
|
||||||
hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
|
|
||||||
|
|
||||||
var ok bool
|
|
||||||
l := 6 + hashedSubpacketsLen
|
|
||||||
sig.HashSuffix = make([]byte, l+6)
|
|
||||||
sig.HashSuffix[0] = 4
|
|
||||||
sig.HashSuffix[1] = uint8(sig.SigType)
|
|
||||||
sig.HashSuffix[2] = uint8(sig.PubKeyAlgo)
|
|
||||||
sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash)
|
|
||||||
if !ok {
|
|
||||||
sig.HashSuffix = nil
|
|
||||||
return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash)))
|
|
||||||
}
|
|
||||||
sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8)
|
|
||||||
sig.HashSuffix[5] = byte(hashedSubpacketsLen)
|
|
||||||
serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true)
|
|
||||||
trailer := sig.HashSuffix[l:]
|
|
||||||
trailer[0] = 4
|
|
||||||
trailer[1] = 0xff
|
|
||||||
trailer[2] = byte(l >> 24)
|
|
||||||
trailer[3] = byte(l >> 16)
|
|
||||||
trailer[4] = byte(l >> 8)
|
|
||||||
trailer[5] = byte(l)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) {
|
|
||||||
err = sig.buildHashSuffix()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
h.Write(sig.HashSuffix)
|
|
||||||
digest = h.Sum(nil)
|
|
||||||
copy(sig.HashTag[:], digest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sign signs a message with a private key. The hash, h, must contain
|
|
||||||
// the hash of the message to be signed and will be mutated by this function.
|
|
||||||
// On success, the signature is stored in sig. Call Serialize to write it out.
|
|
||||||
// If config is nil, sensible defaults will be used.
|
|
||||||
func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) {
|
|
||||||
sig.outSubpackets = sig.buildSubpackets()
|
|
||||||
digest, err := sig.signPrepareHash(h)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch priv.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
|
|
||||||
sig.RSASignature.bytes, err = rsa.SignPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
|
|
||||||
sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
|
|
||||||
case PubKeyAlgoDSA:
|
|
||||||
dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)
|
|
||||||
|
|
||||||
// Need to truncate hashBytes to match FIPS 186-3 section 4.6.
|
|
||||||
subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8
|
|
||||||
if len(digest) > subgroupSize {
|
|
||||||
digest = digest[:subgroupSize]
|
|
||||||
}
|
|
||||||
r, s, err := dsa.Sign(config.Random(), dsaPriv, digest)
|
|
||||||
if err == nil {
|
|
||||||
sig.DSASigR.bytes = r.Bytes()
|
|
||||||
sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
|
|
||||||
sig.DSASigS.bytes = s.Bytes()
|
|
||||||
sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
|
|
||||||
}
|
|
||||||
case PubKeyAlgoECDSA:
|
|
||||||
r, s, err := ecdsa.Sign(config.Random(), priv.PrivateKey.(*ecdsa.PrivateKey), digest)
|
|
||||||
if err == nil {
|
|
||||||
sig.ECDSASigR = fromBig(r)
|
|
||||||
sig.ECDSASigS = fromBig(s)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignUserId computes a signature from priv, asserting that pub is a valid
|
|
||||||
// key for the identity id. On success, the signature is stored in sig. Call
|
|
||||||
// Serialize to write it out.
|
|
||||||
// If config is nil, sensible defaults will be used.
|
|
||||||
func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error {
|
|
||||||
h, err := userIdSignatureHash(id, pub, sig.Hash)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return sig.Sign(h, priv, config)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignKey computes a signature from priv, asserting that pub is a subkey. On
|
|
||||||
// success, the signature is stored in sig. Call Serialize to write it out.
|
|
||||||
// If config is nil, sensible defaults will be used.
|
|
||||||
func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error {
|
|
||||||
h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return sig.Sign(h, priv, config)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
|
|
||||||
// called first.
|
|
||||||
func (sig *Signature) Serialize(w io.Writer) (err error) {
|
|
||||||
if len(sig.outSubpackets) == 0 {
|
|
||||||
sig.outSubpackets = sig.rawSubpackets
|
|
||||||
}
|
|
||||||
if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil {
|
|
||||||
return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
|
|
||||||
}
|
|
||||||
|
|
||||||
sigLength := 0
|
|
||||||
switch sig.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
|
|
||||||
sigLength = 2 + len(sig.RSASignature.bytes)
|
|
||||||
case PubKeyAlgoDSA:
|
|
||||||
sigLength = 2 + len(sig.DSASigR.bytes)
|
|
||||||
sigLength += 2 + len(sig.DSASigS.bytes)
|
|
||||||
case PubKeyAlgoECDSA:
|
|
||||||
sigLength = 2 + len(sig.ECDSASigR.bytes)
|
|
||||||
sigLength += 2 + len(sig.ECDSASigS.bytes)
|
|
||||||
default:
|
|
||||||
panic("impossible")
|
|
||||||
}
|
|
||||||
|
|
||||||
unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false)
|
|
||||||
length := len(sig.HashSuffix) - 6 /* trailer not included */ +
|
|
||||||
2 /* length of unhashed subpackets */ + unhashedSubpacketsLen +
|
|
||||||
2 /* hash tag */ + sigLength
|
|
||||||
err = serializeHeader(w, packetTypeSignature, length)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen)
|
|
||||||
unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8)
|
|
||||||
unhashedSubpackets[1] = byte(unhashedSubpacketsLen)
|
|
||||||
serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false)
|
|
||||||
|
|
||||||
_, err = w.Write(unhashedSubpackets)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = w.Write(sig.HashTag[:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch sig.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
|
|
||||||
err = writeMPIs(w, sig.RSASignature)
|
|
||||||
case PubKeyAlgoDSA:
|
|
||||||
err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
|
|
||||||
case PubKeyAlgoECDSA:
|
|
||||||
err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS)
|
|
||||||
default:
|
|
||||||
panic("impossible")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// outputSubpacket represents a subpacket to be marshaled.
|
|
||||||
type outputSubpacket struct {
|
|
||||||
hashed bool // true if this subpacket is in the hashed area.
|
|
||||||
subpacketType signatureSubpacketType
|
|
||||||
isCritical bool
|
|
||||||
contents []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
|
|
||||||
creationTime := make([]byte, 4)
|
|
||||||
binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix()))
|
|
||||||
subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime})
|
|
||||||
|
|
||||||
if sig.IssuerKeyId != nil {
|
|
||||||
keyId := make([]byte, 8)
|
|
||||||
binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId)
|
|
||||||
subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId})
|
|
||||||
}
|
|
||||||
|
|
||||||
if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 {
|
|
||||||
sigLifetime := make([]byte, 4)
|
|
||||||
binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs)
|
|
||||||
subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Key flags may only appear in self-signatures or certification signatures.
|
|
||||||
|
|
||||||
if sig.FlagsValid {
|
|
||||||
var flags byte
|
|
||||||
if sig.FlagCertify {
|
|
||||||
flags |= KeyFlagCertify
|
|
||||||
}
|
|
||||||
if sig.FlagSign {
|
|
||||||
flags |= KeyFlagSign
|
|
||||||
}
|
|
||||||
if sig.FlagEncryptCommunications {
|
|
||||||
flags |= KeyFlagEncryptCommunications
|
|
||||||
}
|
|
||||||
if sig.FlagEncryptStorage {
|
|
||||||
flags |= KeyFlagEncryptStorage
|
|
||||||
}
|
|
||||||
subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}})
|
|
||||||
}
|
|
||||||
|
|
||||||
// The following subpackets may only appear in self-signatures
|
|
||||||
|
|
||||||
if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 {
|
|
||||||
keyLifetime := make([]byte, 4)
|
|
||||||
binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs)
|
|
||||||
subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime})
|
|
||||||
}
|
|
||||||
|
|
||||||
if sig.IsPrimaryId != nil && *sig.IsPrimaryId {
|
|
||||||
subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}})
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(sig.PreferredSymmetric) > 0 {
|
|
||||||
subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric})
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(sig.PreferredHash) > 0 {
|
|
||||||
subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash})
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(sig.PreferredCompression) > 0 {
|
|
||||||
subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression})
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
42
vendor/golang.org/x/crypto/openpgp/packet/signature_test.go
generated
vendored
42
vendor/golang.org/x/crypto/openpgp/packet/signature_test.go
generated
vendored
|
@ -1,42 +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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto"
|
|
||||||
"encoding/hex"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSignatureRead(t *testing.T) {
|
|
||||||
packet, err := Read(readerFromHex(signatureDataHex))
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig, ok := packet.(*Signature)
|
|
||||||
if !ok || sig.SigType != SigTypeBinary || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.SHA1 {
|
|
||||||
t.Errorf("failed to parse, got: %#v", packet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSignatureReserialize(t *testing.T) {
|
|
||||||
packet, _ := Read(readerFromHex(signatureDataHex))
|
|
||||||
sig := packet.(*Signature)
|
|
||||||
out := new(bytes.Buffer)
|
|
||||||
err := sig.Serialize(out)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error reserializing: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
expected, _ := hex.DecodeString(signatureDataHex)
|
|
||||||
if !bytes.Equal(expected, out.Bytes()) {
|
|
||||||
t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const signatureDataHex = "c2c05c04000102000605024cb45112000a0910ab105c91af38fb158f8d07ff5596ea368c5efe015bed6e78348c0f033c931d5f2ce5db54ce7f2a7e4b4ad64db758d65a7a71773edeab7ba2a9e0908e6a94a1175edd86c1d843279f045b021a6971a72702fcbd650efc393c5474d5b59a15f96d2eaad4c4c426797e0dcca2803ef41c6ff234d403eec38f31d610c344c06f2401c262f0993b2e66cad8a81ebc4322c723e0d4ba09fe917e8777658307ad8329adacba821420741009dfe87f007759f0982275d028a392c6ed983a0d846f890b36148c7358bdb8a516007fac760261ecd06076813831a36d0459075d1befa245ae7f7fb103d92ca759e9498fe60ef8078a39a3beda510deea251ea9f0a7f0df6ef42060f20780360686f3e400e"
|
|
146
vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go
generated
vendored
146
vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go
generated
vendored
|
@ -1,146 +0,0 @@
|
||||||
// Copyright 2013 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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto"
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp/errors"
|
|
||||||
"golang.org/x/crypto/openpgp/s2k"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SignatureV3 represents older version 3 signatures. These signatures are less secure
|
|
||||||
// than version 4 and should not be used to create new signatures. They are included
|
|
||||||
// here for backwards compatibility to read and validate with older key material.
|
|
||||||
// See RFC 4880, section 5.2.2.
|
|
||||||
type SignatureV3 struct {
|
|
||||||
SigType SignatureType
|
|
||||||
CreationTime time.Time
|
|
||||||
IssuerKeyId uint64
|
|
||||||
PubKeyAlgo PublicKeyAlgorithm
|
|
||||||
Hash crypto.Hash
|
|
||||||
HashTag [2]byte
|
|
||||||
|
|
||||||
RSASignature parsedMPI
|
|
||||||
DSASigR, DSASigS parsedMPI
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sig *SignatureV3) parse(r io.Reader) (err error) {
|
|
||||||
// RFC 4880, section 5.2.2
|
|
||||||
var buf [8]byte
|
|
||||||
if _, err = readFull(r, buf[:1]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if buf[0] < 2 || buf[0] > 3 {
|
|
||||||
err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, err = readFull(r, buf[:1]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if buf[0] != 5 {
|
|
||||||
err = errors.UnsupportedError(
|
|
||||||
"invalid hashed material length " + strconv.Itoa(int(buf[0])))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read hashed material: signature type + creation time
|
|
||||||
if _, err = readFull(r, buf[:5]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig.SigType = SignatureType(buf[0])
|
|
||||||
t := binary.BigEndian.Uint32(buf[1:5])
|
|
||||||
sig.CreationTime = time.Unix(int64(t), 0)
|
|
||||||
|
|
||||||
// Eight-octet Key ID of signer.
|
|
||||||
if _, err = readFull(r, buf[:8]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig.IssuerKeyId = binary.BigEndian.Uint64(buf[:])
|
|
||||||
|
|
||||||
// Public-key and hash algorithm
|
|
||||||
if _, err = readFull(r, buf[:2]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig.PubKeyAlgo = PublicKeyAlgorithm(buf[0])
|
|
||||||
switch sig.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA:
|
|
||||||
default:
|
|
||||||
err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var ok bool
|
|
||||||
if sig.Hash, ok = s2k.HashIdToHash(buf[1]); !ok {
|
|
||||||
return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Two-octet field holding left 16 bits of signed hash value.
|
|
||||||
if _, err = readFull(r, sig.HashTag[:2]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch sig.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
|
|
||||||
sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
|
|
||||||
case PubKeyAlgoDSA:
|
|
||||||
if sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
|
|
||||||
default:
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
|
|
||||||
// called first.
|
|
||||||
func (sig *SignatureV3) Serialize(w io.Writer) (err error) {
|
|
||||||
buf := make([]byte, 8)
|
|
||||||
|
|
||||||
// Write the sig type and creation time
|
|
||||||
buf[0] = byte(sig.SigType)
|
|
||||||
binary.BigEndian.PutUint32(buf[1:5], uint32(sig.CreationTime.Unix()))
|
|
||||||
if _, err = w.Write(buf[:5]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the issuer long key ID
|
|
||||||
binary.BigEndian.PutUint64(buf[:8], sig.IssuerKeyId)
|
|
||||||
if _, err = w.Write(buf[:8]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write public key algorithm, hash ID, and hash value
|
|
||||||
buf[0] = byte(sig.PubKeyAlgo)
|
|
||||||
hashId, ok := s2k.HashToHashId(sig.Hash)
|
|
||||||
if !ok {
|
|
||||||
return errors.UnsupportedError(fmt.Sprintf("hash function %v", sig.Hash))
|
|
||||||
}
|
|
||||||
buf[1] = hashId
|
|
||||||
copy(buf[2:4], sig.HashTag[:])
|
|
||||||
if _, err = w.Write(buf[:4]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil {
|
|
||||||
return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch sig.PubKeyAlgo {
|
|
||||||
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
|
|
||||||
err = writeMPIs(w, sig.RSASignature)
|
|
||||||
case PubKeyAlgoDSA:
|
|
||||||
err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
|
|
||||||
default:
|
|
||||||
panic("impossible")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
92
vendor/golang.org/x/crypto/openpgp/packet/signature_v3_test.go
generated
vendored
92
vendor/golang.org/x/crypto/openpgp/packet/signature_v3_test.go
generated
vendored
|
@ -1,92 +0,0 @@
|
||||||
// Copyright 2013 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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto"
|
|
||||||
"encoding/hex"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp/armor"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSignatureV3Read(t *testing.T) {
|
|
||||||
r := v3KeyReader(t)
|
|
||||||
Read(r) // Skip public key
|
|
||||||
Read(r) // Skip uid
|
|
||||||
packet, err := Read(r) // Signature
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig, ok := packet.(*SignatureV3)
|
|
||||||
if !ok || sig.SigType != SigTypeGenericCert || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.MD5 {
|
|
||||||
t.Errorf("failed to parse, got: %#v", packet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSignatureV3Reserialize(t *testing.T) {
|
|
||||||
r := v3KeyReader(t)
|
|
||||||
Read(r) // Skip public key
|
|
||||||
Read(r) // Skip uid
|
|
||||||
packet, err := Read(r)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sig := packet.(*SignatureV3)
|
|
||||||
out := new(bytes.Buffer)
|
|
||||||
if err = sig.Serialize(out); err != nil {
|
|
||||||
t.Errorf("error reserializing: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
expected, err := ioutil.ReadAll(v3KeyReader(t))
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
expected = expected[4+141+4+39:] // See pgpdump offsets below, this is where the sig starts
|
|
||||||
if !bytes.Equal(expected, out.Bytes()) {
|
|
||||||
t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func v3KeyReader(t *testing.T) io.Reader {
|
|
||||||
armorBlock, err := armor.Decode(bytes.NewBufferString(keySigV3Armor))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("armor Decode failed: %v", err)
|
|
||||||
}
|
|
||||||
return armorBlock.Body
|
|
||||||
}
|
|
||||||
|
|
||||||
// keySigV3Armor is some V3 public key I found in an SKS dump.
|
|
||||||
// Old: Public Key Packet(tag 6)(141 bytes)
|
|
||||||
// Ver 4 - new
|
|
||||||
// Public key creation time - Fri Sep 16 17:13:54 CDT 1994
|
|
||||||
// Pub alg - unknown(pub 0)
|
|
||||||
// Unknown public key(pub 0)
|
|
||||||
// Old: User ID Packet(tag 13)(39 bytes)
|
|
||||||
// User ID - Armin M. Warda <warda@nephilim.ruhr.de>
|
|
||||||
// Old: Signature Packet(tag 2)(149 bytes)
|
|
||||||
// Ver 4 - new
|
|
||||||
// Sig type - unknown(05)
|
|
||||||
// Pub alg - ElGamal Encrypt-Only(pub 16)
|
|
||||||
// Hash alg - unknown(hash 46)
|
|
||||||
// Hashed Sub: unknown(sub 81, critical)(1988 bytes)
|
|
||||||
const keySigV3Armor = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
|
||||||
Version: SKS 1.0.10
|
|
||||||
|
|
||||||
mI0CLnoYogAAAQQA1qwA2SuJwfQ5bCQ6u5t20ulnOtY0gykf7YjiK4LiVeRBwHjGq7v30tGV
|
|
||||||
5Qti7qqRW4Ww7CDCJc4sZMFnystucR2vLkXaSoNWoFm4Fg47NiisDdhDezHwbVPW6OpCFNSi
|
|
||||||
ZAamtj4QAUBu8j4LswafrJqZqR9336/V3g8Yil2l48kABRG0J0FybWluIE0uIFdhcmRhIDx3
|
|
||||||
YXJkYUBuZXBoaWxpbS5ydWhyLmRlPoiVAgUQLok2xwXR6zmeWEiZAQE/DgP/WgxPQh40/Po4
|
|
||||||
gSkWZCDAjNdph7zexvAb0CcUWahcwiBIgg3U5ErCx9I5CNVA9U+s8bNrDZwgSIeBzp3KhWUx
|
|
||||||
524uhGgm6ZUTOAIKA6CbV6pfqoLpJnRYvXYQU5mIWsNa99wcu2qu18OeEDnztb7aLA6Ra9OF
|
|
||||||
YFCbq4EjXRoOrYM=
|
|
||||||
=LPjs
|
|
||||||
-----END PGP PUBLIC KEY BLOCK-----`
|
|
155
vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go
generated
vendored
155
vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go
generated
vendored
|
@ -1,155 +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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/cipher"
|
|
||||||
"io"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp/errors"
|
|
||||||
"golang.org/x/crypto/openpgp/s2k"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This is the largest session key that we'll support. Since no 512-bit cipher
|
|
||||||
// has even been seriously used, this is comfortably large.
|
|
||||||
const maxSessionKeySizeInBytes = 64
|
|
||||||
|
|
||||||
// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC
|
|
||||||
// 4880, section 5.3.
|
|
||||||
type SymmetricKeyEncrypted struct {
|
|
||||||
CipherFunc CipherFunction
|
|
||||||
s2k func(out, in []byte)
|
|
||||||
encryptedKey []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
const symmetricKeyEncryptedVersion = 4
|
|
||||||
|
|
||||||
func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
|
|
||||||
// RFC 4880, section 5.3.
|
|
||||||
var buf [2]byte
|
|
||||||
if _, err := readFull(r, buf[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if buf[0] != symmetricKeyEncryptedVersion {
|
|
||||||
return errors.UnsupportedError("SymmetricKeyEncrypted version")
|
|
||||||
}
|
|
||||||
ske.CipherFunc = CipherFunction(buf[1])
|
|
||||||
|
|
||||||
if ske.CipherFunc.KeySize() == 0 {
|
|
||||||
return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1])))
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
ske.s2k, err = s2k.Parse(r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
encryptedKey := make([]byte, maxSessionKeySizeInBytes)
|
|
||||||
// The session key may follow. We just have to try and read to find
|
|
||||||
// out. If it exists then we limit it to maxSessionKeySizeInBytes.
|
|
||||||
n, err := readFull(r, encryptedKey)
|
|
||||||
if err != nil && err != io.ErrUnexpectedEOF {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if n != 0 {
|
|
||||||
if n == maxSessionKeySizeInBytes {
|
|
||||||
return errors.UnsupportedError("oversized encrypted session key")
|
|
||||||
}
|
|
||||||
ske.encryptedKey = encryptedKey[:n]
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrypt attempts to decrypt an encrypted session key and returns the key and
|
|
||||||
// the cipher to use when decrypting a subsequent Symmetrically Encrypted Data
|
|
||||||
// packet.
|
|
||||||
func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunction, error) {
|
|
||||||
key := make([]byte, ske.CipherFunc.KeySize())
|
|
||||||
ske.s2k(key, passphrase)
|
|
||||||
|
|
||||||
if len(ske.encryptedKey) == 0 {
|
|
||||||
return key, ske.CipherFunc, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// the IV is all zeros
|
|
||||||
iv := make([]byte, ske.CipherFunc.blockSize())
|
|
||||||
c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv)
|
|
||||||
plaintextKey := make([]byte, len(ske.encryptedKey))
|
|
||||||
c.XORKeyStream(plaintextKey, ske.encryptedKey)
|
|
||||||
cipherFunc := CipherFunction(plaintextKey[0])
|
|
||||||
if cipherFunc.blockSize() == 0 {
|
|
||||||
return nil, ske.CipherFunc, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
|
|
||||||
}
|
|
||||||
plaintextKey = plaintextKey[1:]
|
|
||||||
if l := len(plaintextKey); l == 0 || l%cipherFunc.blockSize() != 0 {
|
|
||||||
return nil, cipherFunc, errors.StructuralError("length of decrypted key not a multiple of block size")
|
|
||||||
}
|
|
||||||
|
|
||||||
return plaintextKey, cipherFunc, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The
|
|
||||||
// packet contains a random session key, encrypted by a key derived from the
|
|
||||||
// given passphrase. The session key is returned and must be passed to
|
|
||||||
// SerializeSymmetricallyEncrypted.
|
|
||||||
// If config is nil, sensible defaults will be used.
|
|
||||||
func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) {
|
|
||||||
cipherFunc := config.Cipher()
|
|
||||||
keySize := cipherFunc.KeySize()
|
|
||||||
if keySize == 0 {
|
|
||||||
return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
|
|
||||||
}
|
|
||||||
|
|
||||||
s2kBuf := new(bytes.Buffer)
|
|
||||||
keyEncryptingKey := make([]byte, keySize)
|
|
||||||
// s2k.Serialize salts and stretches the passphrase, and writes the
|
|
||||||
// resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf.
|
|
||||||
err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, &s2k.Config{Hash: config.Hash(), S2KCount: config.PasswordHashIterations()})
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s2kBytes := s2kBuf.Bytes()
|
|
||||||
|
|
||||||
packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize
|
|
||||||
err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf [2]byte
|
|
||||||
buf[0] = symmetricKeyEncryptedVersion
|
|
||||||
buf[1] = byte(cipherFunc)
|
|
||||||
_, err = w.Write(buf[:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = w.Write(s2kBytes)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sessionKey := make([]byte, keySize)
|
|
||||||
_, err = io.ReadFull(config.Random(), sessionKey)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
iv := make([]byte, cipherFunc.blockSize())
|
|
||||||
c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv)
|
|
||||||
encryptedCipherAndKey := make([]byte, keySize+1)
|
|
||||||
c.XORKeyStream(encryptedCipherAndKey, buf[1:])
|
|
||||||
c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey)
|
|
||||||
_, err = w.Write(encryptedCipherAndKey)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
key = sessionKey
|
|
||||||
return
|
|
||||||
}
|
|
103
vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go
generated
vendored
103
vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go
generated
vendored
|
@ -1,103 +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 packet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSymmetricKeyEncrypted(t *testing.T) {
|
|
||||||
buf := readerFromHex(symmetricallyEncryptedHex)
|
|
||||||
packet, err := Read(buf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("failed to read SymmetricKeyEncrypted: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ske, ok := packet.(*SymmetricKeyEncrypted)
|
|
||||||
if !ok {
|
|
||||||
t.Error("didn't find SymmetricKeyEncrypted packet")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
key, cipherFunc, err := ske.Decrypt([]byte("password"))
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
packet, err = Read(buf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("failed to read SymmetricallyEncrypted: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
se, ok := packet.(*SymmetricallyEncrypted)
|
|
||||||
if !ok {
|
|
||||||
t.Error("didn't find SymmetricallyEncrypted packet")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
r, err := se.Decrypt(cipherFunc, key)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
contents, err := ioutil.ReadAll(r)
|
|
||||||
if err != nil && err != io.EOF {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedContents, _ := hex.DecodeString(symmetricallyEncryptedContentsHex)
|
|
||||||
if !bytes.Equal(expectedContents, contents) {
|
|
||||||
t.Errorf("bad contents got:%x want:%x", contents, expectedContents)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const symmetricallyEncryptedHex = "8c0d04030302371a0b38d884f02060c91cf97c9973b8e58e028e9501708ccfe618fb92afef7fa2d80ddadd93cf"
|
|
||||||
const symmetricallyEncryptedContentsHex = "cb1062004d14c4df636f6e74656e74732e0a"
|
|
||||||
|
|
||||||
func TestSerializeSymmetricKeyEncrypted(t *testing.T) {
|
|
||||||
buf := bytes.NewBuffer(nil)
|
|
||||||
passphrase := []byte("testing")
|
|
||||||
const cipherFunc = CipherAES128
|
|
||||||
config := &Config{
|
|
||||||
DefaultCipher: cipherFunc,
|
|
||||||
}
|
|
||||||
|
|
||||||
key, err := SerializeSymmetricKeyEncrypted(buf, passphrase, config)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("failed to serialize: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
p, err := Read(buf)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("failed to reparse: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ske, ok := p.(*SymmetricKeyEncrypted)
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("parsed a different packet type: %#v", p)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if ske.CipherFunc != config.DefaultCipher {
|
|
||||||
t.Errorf("SKE cipher function is %d (expected %d)", ske.CipherFunc, config.DefaultCipher)
|
|
||||||
}
|
|
||||||
parsedKey, parsedCipherFunc, err := ske.Decrypt(passphrase)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("failed to decrypt reparsed SKE: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !bytes.Equal(key, parsedKey) {
|
|
||||||
t.Errorf("keys don't match after Decrypt: %x (original) vs %x (parsed)", key, parsedKey)
|
|
||||||
}
|
|
||||||
if parsedCipherFunc != cipherFunc {
|
|
||||||
t.Errorf("cipher function doesn't match after Decrypt: %d (original) vs %d (parsed)", cipherFunc, parsedCipherFunc)
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue