mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Switch to keybase go-crypto (for some elliptic curve key) + test (#1925)
* Switch to keybase go-crypto (for some elliptic curve key) + test
* Use assert.NoError 
and add a little more context to failing test description
* Use assert.(No)Error everywhere 🌈
and assert.Error in place of .Nil/.NotNil
			
			
This commit is contained in:
		
				
					committed by
					
						
						Lunny Xiao
					
				
			
			
				
	
			
			
			
						parent
						
							5e92b82ac6
						
					
				
				
					commit
					274149dd14
				
			@@ -19,9 +19,9 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/log"
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/go-xorm/xorm"
 | 
						"github.com/go-xorm/xorm"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp"
 | 
						"github.com/keybase/go-crypto/openpgp"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/armor"
 | 
						"github.com/keybase/go-crypto/openpgp/armor"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/packet"
 | 
						"github.com/keybase/go-crypto/openpgp/packet"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GPGKey represents a GPG key.
 | 
					// GPGKey represents a GPG key.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,7 +43,28 @@ MkM/fdpyc2hY7Dl/+qFmN5MG5yGmMpQcX+RNNR222ibNC1D3wg==
 | 
				
			|||||||
-----END PGP PUBLIC KEY BLOCK-----`
 | 
					-----END PGP PUBLIC KEY BLOCK-----`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	key, err := checkArmoredGPGKeyString(testGPGArmor)
 | 
						key, err := checkArmoredGPGKeyString(testGPGArmor)
 | 
				
			||||||
	assert.Nil(t, err, "Could not parse a valid GPG armored key", key)
 | 
						assert.NoError(t, err, "Could not parse a valid GPG public armored rsa key", key)
 | 
				
			||||||
 | 
						//TODO verify value of key
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestCheckArmoredbrainpoolP256r1GPGKeyString(t *testing.T) {
 | 
				
			||||||
 | 
						testGPGArmor := `-----BEGIN PGP PUBLIC KEY BLOCK-----
 | 
				
			||||||
 | 
					Version: GnuPG v2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mFMEV6HwkhMJKyQDAwIIAQEHAgMEUsvJO/j5dFMRRj67qeZC9fSKBsGZdOHRj2+6
 | 
				
			||||||
 | 
					8wssmbUuLTfT/ZjIbExETyY8hFnURRGpD2Ifyz0cKjXcbXfJtrQTRm9vYmFyIDxm
 | 
				
			||||||
 | 
					b29AYmFyLmRlPoh/BBMTCAAnBQJZOsDIAhsDBQkJZgGABQsJCAcCBhUICQoLAgQW
 | 
				
			||||||
 | 
					AgMBAh4BAheAAAoJEGuJTd/DBMzmNVQA/2beUrv1yU4gyvCiPDEm3pK42cSfaL5D
 | 
				
			||||||
 | 
					muCtPCUg9hlWAP4yq6M78NW8STfsXgn6oeziMYiHSTmV14nOamLuwwDWM7hXBFeh
 | 
				
			||||||
 | 
					8JISCSskAwMCCAEBBwIDBG3A+XfINAZp1CTse2mRNgeUE5DbUtEpO8ALXKA1UQsQ
 | 
				
			||||||
 | 
					DLKq27b7zTgawgXIGUGP6mWsJ5oH7MNAJ/uKTsYmX40DAQgHiGcEGBMIAA8FAleh
 | 
				
			||||||
 | 
					8JICGwwFCQlmAYAACgkQa4lN38MEzOZwKAD/QKyerAgcvzzLaqvtap3XvpYcw9tc
 | 
				
			||||||
 | 
					OyjLLnFQiVmq7kEA/0z0CQe3ZQiQIq5zrs7Nh1XRkFAo8GlU/SGC9XFFi722
 | 
				
			||||||
 | 
					=ZiSe
 | 
				
			||||||
 | 
					-----END PGP PUBLIC KEY BLOCK-----`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						key, err := checkArmoredGPGKeyString(testGPGArmor)
 | 
				
			||||||
 | 
						assert.NoError(t, err, "Could not parse a valid GPG public armored brainpoolP256r1 key", key)
 | 
				
			||||||
	//TODO verify value of key
 | 
						//TODO verify value of key
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -79,11 +100,11 @@ MkM/fdpyc2hY7Dl/+qFmN5MG5yGmMpQcX+RNNR222ibNC1D3wg==
 | 
				
			|||||||
=i9b7
 | 
					=i9b7
 | 
				
			||||||
-----END PGP PUBLIC KEY BLOCK-----`
 | 
					-----END PGP PUBLIC KEY BLOCK-----`
 | 
				
			||||||
	ekey, err := checkArmoredGPGKeyString(testGPGArmor)
 | 
						ekey, err := checkArmoredGPGKeyString(testGPGArmor)
 | 
				
			||||||
	assert.Nil(t, err, "Could not parse a valid GPG armored key", ekey)
 | 
						assert.NoError(t, err, "Could not parse a valid GPG armored key", ekey)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pubkey := ekey.PrimaryKey
 | 
						pubkey := ekey.PrimaryKey
 | 
				
			||||||
	content, err := base64EncPubKey(pubkey)
 | 
						content, err := base64EncPubKey(pubkey)
 | 
				
			||||||
	assert.Nil(t, err, "Could not base64 encode a valid PublicKey content", ekey)
 | 
						assert.NoError(t, err, "Could not base64 encode a valid PublicKey content", ekey)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	key := &GPGKey{
 | 
						key := &GPGKey{
 | 
				
			||||||
		KeyID:             pubkey.KeyIdString(),
 | 
							KeyID:             pubkey.KeyIdString(),
 | 
				
			||||||
@@ -144,21 +165,21 @@ Unknown GPG key with good email
 | 
				
			|||||||
`
 | 
					`
 | 
				
			||||||
	//Reading Sign
 | 
						//Reading Sign
 | 
				
			||||||
	goodSig, err := extractSignature(testGoodSigArmor)
 | 
						goodSig, err := extractSignature(testGoodSigArmor)
 | 
				
			||||||
	assert.Nil(t, err, "Could not parse a valid GPG armored signature", testGoodSigArmor)
 | 
						assert.NoError(t, err, "Could not parse a valid GPG armored signature", testGoodSigArmor)
 | 
				
			||||||
	badSig, err := extractSignature(testBadSigArmor)
 | 
						badSig, err := extractSignature(testBadSigArmor)
 | 
				
			||||||
	assert.Nil(t, err, "Could not parse a valid GPG armored signature", testBadSigArmor)
 | 
						assert.NoError(t, err, "Could not parse a valid GPG armored signature", testBadSigArmor)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//Generating hash of commit
 | 
						//Generating hash of commit
 | 
				
			||||||
	goodHash, err := populateHash(goodSig.Hash, []byte(testGoodPayload))
 | 
						goodHash, err := populateHash(goodSig.Hash, []byte(testGoodPayload))
 | 
				
			||||||
	assert.Nil(t, err, "Could not generate a valid hash of payload", testGoodPayload)
 | 
						assert.NoError(t, err, "Could not generate a valid hash of payload", testGoodPayload)
 | 
				
			||||||
	badHash, err := populateHash(badSig.Hash, []byte(testBadPayload))
 | 
						badHash, err := populateHash(badSig.Hash, []byte(testBadPayload))
 | 
				
			||||||
	assert.Nil(t, err, "Could not generate a valid hash of payload", testBadPayload)
 | 
						assert.NoError(t, err, "Could not generate a valid hash of payload", testBadPayload)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//Verify
 | 
						//Verify
 | 
				
			||||||
	err = verifySign(goodSig, goodHash, key)
 | 
						err = verifySign(goodSig, goodHash, key)
 | 
				
			||||||
	assert.Nil(t, err, "Could not validate a good signature")
 | 
						assert.NoError(t, err, "Could not validate a good signature")
 | 
				
			||||||
	err = verifySign(badSig, badHash, key)
 | 
						err = verifySign(badSig, badHash, key)
 | 
				
			||||||
	assert.NotNil(t, err, "Validate a bad signature")
 | 
						assert.Error(t, err, "Validate a bad signature")
 | 
				
			||||||
	err = verifySign(goodSig, goodHash, cannotsignkey)
 | 
						err = verifySign(goodSig, goodHash, cannotsignkey)
 | 
				
			||||||
	assert.NotNil(t, err, "Validate a bad signature with a kay that can not sign")
 | 
						assert.Error(t, err, "Validate a bad signature with a kay that can not sign")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										27
									
								
								vendor/github.com/keybase/go-crypto/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/keybase/go-crypto/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					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/github.com/keybase/go-crypto/PATENTS
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/keybase/go-crypto/PATENTS
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					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.
 | 
				
			||||||
							
								
								
									
										134
									
								
								vendor/github.com/keybase/go-crypto/brainpool/brainpool.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								vendor/github.com/keybase/go-crypto/brainpool/brainpool.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,134 @@
 | 
				
			|||||||
 | 
					// Package brainpool implements Brainpool elliptic curves.
 | 
				
			||||||
 | 
					// Implementation of rcurves is from github.com/ebfe/brainpool
 | 
				
			||||||
 | 
					// Note that these curves are implemented with naive, non-constant time operations
 | 
				
			||||||
 | 
					// and are likely not suitable for enviroments where timing attacks are a concern.
 | 
				
			||||||
 | 
					package brainpool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/elliptic"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						once                   sync.Once
 | 
				
			||||||
 | 
						p256t1, p384t1, p512t1 *elliptic.CurveParams
 | 
				
			||||||
 | 
						p256r1, p384r1, p512r1 *rcurve
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func initAll() {
 | 
				
			||||||
 | 
						initP256t1()
 | 
				
			||||||
 | 
						initP384t1()
 | 
				
			||||||
 | 
						initP512t1()
 | 
				
			||||||
 | 
						initP256r1()
 | 
				
			||||||
 | 
						initP384r1()
 | 
				
			||||||
 | 
						initP512r1()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func initP256t1() {
 | 
				
			||||||
 | 
						p256t1 = &elliptic.CurveParams{Name: "brainpoolP256t1"}
 | 
				
			||||||
 | 
						p256t1.P, _ = new(big.Int).SetString("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16)
 | 
				
			||||||
 | 
						p256t1.N, _ = new(big.Int).SetString("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16)
 | 
				
			||||||
 | 
						p256t1.B, _ = new(big.Int).SetString("662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", 16)
 | 
				
			||||||
 | 
						p256t1.Gx, _ = new(big.Int).SetString("A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4", 16)
 | 
				
			||||||
 | 
						p256t1.Gy, _ = new(big.Int).SetString("2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE", 16)
 | 
				
			||||||
 | 
						p256t1.BitSize = 256
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func initP256r1() {
 | 
				
			||||||
 | 
						twisted := p256t1
 | 
				
			||||||
 | 
						params := &elliptic.CurveParams{
 | 
				
			||||||
 | 
							Name:    "brainpoolP256r1",
 | 
				
			||||||
 | 
							P:       twisted.P,
 | 
				
			||||||
 | 
							N:       twisted.N,
 | 
				
			||||||
 | 
							BitSize: twisted.BitSize,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						params.Gx, _ = new(big.Int).SetString("8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", 16)
 | 
				
			||||||
 | 
						params.Gy, _ = new(big.Int).SetString("547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", 16)
 | 
				
			||||||
 | 
						z, _ := new(big.Int).SetString("3E2D4BD9597B58639AE7AA669CAB9837CF5CF20A2C852D10F655668DFC150EF0", 16)
 | 
				
			||||||
 | 
						p256r1 = newrcurve(twisted, params, z)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func initP384t1() {
 | 
				
			||||||
 | 
						p384t1 = &elliptic.CurveParams{Name: "brainpoolP384t1"}
 | 
				
			||||||
 | 
						p384t1.P, _ = new(big.Int).SetString("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16)
 | 
				
			||||||
 | 
						p384t1.N, _ = new(big.Int).SetString("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16)
 | 
				
			||||||
 | 
						p384t1.B, _ = new(big.Int).SetString("7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", 16)
 | 
				
			||||||
 | 
						p384t1.Gx, _ = new(big.Int).SetString("18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC", 16)
 | 
				
			||||||
 | 
						p384t1.Gy, _ = new(big.Int).SetString("25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928", 16)
 | 
				
			||||||
 | 
						p384t1.BitSize = 384
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func initP384r1() {
 | 
				
			||||||
 | 
						twisted := p384t1
 | 
				
			||||||
 | 
						params := &elliptic.CurveParams{
 | 
				
			||||||
 | 
							Name:    "brainpoolP384r1",
 | 
				
			||||||
 | 
							P:       twisted.P,
 | 
				
			||||||
 | 
							N:       twisted.N,
 | 
				
			||||||
 | 
							BitSize: twisted.BitSize,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						params.Gx, _ = new(big.Int).SetString("1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", 16)
 | 
				
			||||||
 | 
						params.Gy, _ = new(big.Int).SetString("8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", 16)
 | 
				
			||||||
 | 
						z, _ := new(big.Int).SetString("41DFE8DD399331F7166A66076734A89CD0D2BCDB7D068E44E1F378F41ECBAE97D2D63DBC87BCCDDCCC5DA39E8589291C", 16)
 | 
				
			||||||
 | 
						p384r1 = newrcurve(twisted, params, z)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func initP512t1() {
 | 
				
			||||||
 | 
						p512t1 = &elliptic.CurveParams{Name: "brainpoolP512t1"}
 | 
				
			||||||
 | 
						p512t1.P, _ = new(big.Int).SetString("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16)
 | 
				
			||||||
 | 
						p512t1.N, _ = new(big.Int).SetString("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16)
 | 
				
			||||||
 | 
						p512t1.B, _ = new(big.Int).SetString("7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", 16)
 | 
				
			||||||
 | 
						p512t1.Gx, _ = new(big.Int).SetString("640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA", 16)
 | 
				
			||||||
 | 
						p512t1.Gy, _ = new(big.Int).SetString("5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332", 16)
 | 
				
			||||||
 | 
						p512t1.BitSize = 512
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func initP512r1() {
 | 
				
			||||||
 | 
						twisted := p512t1
 | 
				
			||||||
 | 
						params := &elliptic.CurveParams{
 | 
				
			||||||
 | 
							Name:    "brainpoolP512r1",
 | 
				
			||||||
 | 
							P:       twisted.P,
 | 
				
			||||||
 | 
							N:       twisted.N,
 | 
				
			||||||
 | 
							BitSize: twisted.BitSize,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						params.Gx, _ = new(big.Int).SetString("81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", 16)
 | 
				
			||||||
 | 
						params.Gy, _ = new(big.Int).SetString("7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", 16)
 | 
				
			||||||
 | 
						z, _ := new(big.Int).SetString("12EE58E6764838B69782136F0F2D3BA06E27695716054092E60A80BEDB212B64E585D90BCE13761F85C3F1D2A64E3BE8FEA2220F01EBA5EEB0F35DBD29D922AB", 16)
 | 
				
			||||||
 | 
						p512r1 = newrcurve(twisted, params, z)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// P256t1 returns a Curve which implements Brainpool P256t1 (see RFC 5639, section 3.4)
 | 
				
			||||||
 | 
					func P256t1() elliptic.Curve {
 | 
				
			||||||
 | 
						once.Do(initAll)
 | 
				
			||||||
 | 
						return p256t1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// P256r1 returns a Curve which implements Brainpool P256r1 (see RFC 5639, section 3.4)
 | 
				
			||||||
 | 
					func P256r1() elliptic.Curve {
 | 
				
			||||||
 | 
						once.Do(initAll)
 | 
				
			||||||
 | 
						return p256r1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// P384t1 returns a Curve which implements Brainpool P384t1 (see RFC 5639, section 3.6)
 | 
				
			||||||
 | 
					func P384t1() elliptic.Curve {
 | 
				
			||||||
 | 
						once.Do(initAll)
 | 
				
			||||||
 | 
						return p384t1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// P384r1 returns a Curve which implements Brainpool P384r1 (see RFC 5639, section 3.6)
 | 
				
			||||||
 | 
					func P384r1() elliptic.Curve {
 | 
				
			||||||
 | 
						once.Do(initAll)
 | 
				
			||||||
 | 
						return p384r1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// P512t1 returns a Curve which implements Brainpool P512t1 (see RFC 5639, section 3.7)
 | 
				
			||||||
 | 
					func P512t1() elliptic.Curve {
 | 
				
			||||||
 | 
						once.Do(initAll)
 | 
				
			||||||
 | 
						return p512t1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// P512r1 returns a Curve which implements Brainpool P512r1 (see RFC 5639, section 3.7)
 | 
				
			||||||
 | 
					func P512r1() elliptic.Curve {
 | 
				
			||||||
 | 
						once.Do(initAll)
 | 
				
			||||||
 | 
						return p512r1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										83
									
								
								vendor/github.com/keybase/go-crypto/brainpool/rcurve.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								vendor/github.com/keybase/go-crypto/brainpool/rcurve.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
				
			|||||||
 | 
					package brainpool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/elliptic"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ elliptic.Curve = (*rcurve)(nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type rcurve struct {
 | 
				
			||||||
 | 
						twisted elliptic.Curve
 | 
				
			||||||
 | 
						params  *elliptic.CurveParams
 | 
				
			||||||
 | 
						z       *big.Int
 | 
				
			||||||
 | 
						zinv    *big.Int
 | 
				
			||||||
 | 
						z2      *big.Int
 | 
				
			||||||
 | 
						z3      *big.Int
 | 
				
			||||||
 | 
						zinv2   *big.Int
 | 
				
			||||||
 | 
						zinv3   *big.Int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						two   = big.NewInt(2)
 | 
				
			||||||
 | 
						three = big.NewInt(3)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newrcurve(twisted elliptic.Curve, params *elliptic.CurveParams, z *big.Int) *rcurve {
 | 
				
			||||||
 | 
						zinv := new(big.Int).ModInverse(z, params.P)
 | 
				
			||||||
 | 
						return &rcurve{
 | 
				
			||||||
 | 
							twisted: twisted,
 | 
				
			||||||
 | 
							params:  params,
 | 
				
			||||||
 | 
							z:       z,
 | 
				
			||||||
 | 
							zinv:    zinv,
 | 
				
			||||||
 | 
							z2:      new(big.Int).Exp(z, two, params.P),
 | 
				
			||||||
 | 
							z3:      new(big.Int).Exp(z, three, params.P),
 | 
				
			||||||
 | 
							zinv2:   new(big.Int).Exp(zinv, two, params.P),
 | 
				
			||||||
 | 
							zinv3:   new(big.Int).Exp(zinv, three, params.P),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (curve *rcurve) toTwisted(x, y *big.Int) (*big.Int, *big.Int) {
 | 
				
			||||||
 | 
						var tx, ty big.Int
 | 
				
			||||||
 | 
						tx.Mul(x, curve.z2)
 | 
				
			||||||
 | 
						tx.Mod(&tx, curve.params.P)
 | 
				
			||||||
 | 
						ty.Mul(y, curve.z3)
 | 
				
			||||||
 | 
						ty.Mod(&ty, curve.params.P)
 | 
				
			||||||
 | 
						return &tx, &ty
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (curve *rcurve) fromTwisted(tx, ty *big.Int) (*big.Int, *big.Int) {
 | 
				
			||||||
 | 
						var x, y big.Int
 | 
				
			||||||
 | 
						x.Mul(tx, curve.zinv2)
 | 
				
			||||||
 | 
						x.Mod(&x, curve.params.P)
 | 
				
			||||||
 | 
						y.Mul(ty, curve.zinv3)
 | 
				
			||||||
 | 
						y.Mod(&y, curve.params.P)
 | 
				
			||||||
 | 
						return &x, &y
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (curve *rcurve) Params() *elliptic.CurveParams {
 | 
				
			||||||
 | 
						return curve.params
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (curve *rcurve) IsOnCurve(x, y *big.Int) bool {
 | 
				
			||||||
 | 
						return curve.twisted.IsOnCurve(curve.toTwisted(x, y))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (curve *rcurve) Add(x1, y1, x2, y2 *big.Int) (x, y *big.Int) {
 | 
				
			||||||
 | 
						tx1, ty1 := curve.toTwisted(x1, y1)
 | 
				
			||||||
 | 
						tx2, ty2 := curve.toTwisted(x2, y2)
 | 
				
			||||||
 | 
						return curve.fromTwisted(curve.twisted.Add(tx1, ty1, tx2, ty2))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (curve *rcurve) Double(x1, y1 *big.Int) (x, y *big.Int) {
 | 
				
			||||||
 | 
						return curve.fromTwisted(curve.twisted.Double(curve.toTwisted(x1, y1)))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (curve *rcurve) ScalarMult(x1, y1 *big.Int, scalar []byte) (x, y *big.Int) {
 | 
				
			||||||
 | 
						tx1, ty1 := curve.toTwisted(x1, y1)
 | 
				
			||||||
 | 
						return curve.fromTwisted(curve.twisted.ScalarMult(tx1, ty1, scalar))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (curve *rcurve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
 | 
				
			||||||
 | 
						return curve.fromTwisted(curve.twisted.ScalarBaseMult(scalar))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -4,7 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Package cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common
 | 
					// Package cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common
 | 
				
			||||||
// OpenPGP cipher.
 | 
					// OpenPGP cipher.
 | 
				
			||||||
package cast5 // import "golang.org/x/crypto/cast5"
 | 
					package cast5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "errors"
 | 
					import "errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										20
									
								
								vendor/github.com/keybase/go-crypto/curve25519/const_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/keybase/go-crypto/curve25519/const_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					// 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/github.com/keybase/go-crypto/curve25519/cswap_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								vendor/github.com/keybase/go-crypto/curve25519/cswap_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					// 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/github.com/keybase/go-crypto/curve25519/curve25519.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										841
									
								
								vendor/github.com/keybase/go-crypto/curve25519/curve25519.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,841 @@
 | 
				
			|||||||
 | 
					// 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)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										113
									
								
								vendor/github.com/keybase/go-crypto/curve25519/curve_impl.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								vendor/github.com/keybase/go-crypto/curve25519/curve_impl.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
				
			|||||||
 | 
					package curve25519
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/elliptic"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var cv25519 cv25519Curve
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type cv25519Curve struct {
 | 
				
			||||||
 | 
						*elliptic.CurveParams
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func copyReverse(dst []byte, src []byte) {
 | 
				
			||||||
 | 
						// Curve 25519 multiplication functions expect scalars in reverse
 | 
				
			||||||
 | 
						// order than PGP. To keep the curve25519Curve type consistent
 | 
				
			||||||
 | 
						// with other curves, we reverse it here.
 | 
				
			||||||
 | 
						for i, j := 0, len(src)-1; j >= 0; i, j = i+1, j-1 {
 | 
				
			||||||
 | 
							dst[i] = src[j]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (cv25519Curve) ScalarMult(x1, y1 *big.Int, scalar []byte) (x, y *big.Int) {
 | 
				
			||||||
 | 
						// Assume y1 is 0 with cv25519.
 | 
				
			||||||
 | 
						var dst [32]byte
 | 
				
			||||||
 | 
						var x1Bytes [32]byte
 | 
				
			||||||
 | 
						var scalarBytes [32]byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						copy(x1Bytes[:], x1.Bytes()[:32])
 | 
				
			||||||
 | 
						copyReverse(scalarBytes[:], scalar[:32])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						scalarMult(&dst, &scalarBytes, &x1Bytes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x = new(big.Int).SetBytes(dst[:])
 | 
				
			||||||
 | 
						y = new(big.Int)
 | 
				
			||||||
 | 
						return x, y
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (cv25519Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
 | 
				
			||||||
 | 
						var dst [32]byte
 | 
				
			||||||
 | 
						var scalarBytes [32]byte
 | 
				
			||||||
 | 
						copyReverse(scalarBytes[:], scalar[:32])
 | 
				
			||||||
 | 
						scalarMult(&dst, &scalarBytes, &basePoint)
 | 
				
			||||||
 | 
						x = new(big.Int).SetBytes(dst[:])
 | 
				
			||||||
 | 
						y = new(big.Int)
 | 
				
			||||||
 | 
						return x, y
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (cv25519Curve) IsOnCurve(bigX, bigY *big.Int) bool {
 | 
				
			||||||
 | 
						return bigY.Sign() == 0 // bigY == 0 ?
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// More information about 0x40 point format:
 | 
				
			||||||
 | 
					// https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-00#section-3
 | 
				
			||||||
 | 
					// In addition to uncompressed point format described here:
 | 
				
			||||||
 | 
					// https://tools.ietf.org/html/rfc6637#section-6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (cv25519Curve) MarshalType40(x, y *big.Int) []byte {
 | 
				
			||||||
 | 
						byteLen := 32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret := make([]byte, 1+byteLen)
 | 
				
			||||||
 | 
						ret[0] = 0x40
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xBytes := x.Bytes()
 | 
				
			||||||
 | 
						copy(ret[1+byteLen-len(xBytes):], xBytes)
 | 
				
			||||||
 | 
						return ret
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (cv25519Curve) UnmarshalType40(data []byte) (x, y *big.Int) {
 | 
				
			||||||
 | 
						if len(data) != 1+32 {
 | 
				
			||||||
 | 
							return nil, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if data[0] != 0x40 {
 | 
				
			||||||
 | 
							return nil, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						x = new(big.Int).SetBytes(data[1:])
 | 
				
			||||||
 | 
						// Any x is a valid curve point.
 | 
				
			||||||
 | 
						return x, new(big.Int)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ToCurve25519 casts given elliptic.Curve type to Curve25519 type, or
 | 
				
			||||||
 | 
					// returns nil, false if cast was unsuccessful.
 | 
				
			||||||
 | 
					func ToCurve25519(cv elliptic.Curve) (cv25519Curve, bool) {
 | 
				
			||||||
 | 
						cv2, ok := cv.(cv25519Curve)
 | 
				
			||||||
 | 
						return cv2, ok
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func initCv25519() {
 | 
				
			||||||
 | 
						cv25519.CurveParams = &elliptic.CurveParams{Name: "Curve 25519"}
 | 
				
			||||||
 | 
						// Some code relies on these parameters being available for
 | 
				
			||||||
 | 
						// checking Curve coordinate length. They should not be used
 | 
				
			||||||
 | 
						// directly for any calculations.
 | 
				
			||||||
 | 
						cv25519.P, _ = new (big.Int).SetString("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", 16)
 | 
				
			||||||
 | 
						cv25519.N, _ = new (big.Int).SetString("1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed", 16)
 | 
				
			||||||
 | 
						cv25519.Gx, _ = new (big.Int).SetString("9", 16)
 | 
				
			||||||
 | 
						cv25519.Gy, _ = new (big.Int).SetString("20ae19a1b8a086b4e01edd2c7748d14c923d4d7e6d7c61b229e9c5a27eced3d9", 16)
 | 
				
			||||||
 | 
						cv25519.BitSize = 256
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var initonce sync.Once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Cv25519 returns a Curve which (partially) implements Cv25519. Only
 | 
				
			||||||
 | 
					// ScalarMult and ScalarBaseMult are valid for this curve. Add and
 | 
				
			||||||
 | 
					// Double should not be used.
 | 
				
			||||||
 | 
					func Cv25519() elliptic.Curve {
 | 
				
			||||||
 | 
						initonce.Do(initCv25519)
 | 
				
			||||||
 | 
						return cv25519
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (curve cv25519Curve) Params() *elliptic.CurveParams {
 | 
				
			||||||
 | 
						return curve.CurveParams
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										23
									
								
								vendor/github.com/keybase/go-crypto/curve25519/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/keybase/go-crypto/curve25519/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					// 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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/github.com/keybase/go-crypto/curve25519/freeze_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								vendor/github.com/keybase/go-crypto/curve25519/freeze_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					// 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/github.com/keybase/go-crypto/curve25519/ladderstep_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1398
									
								
								vendor/github.com/keybase/go-crypto/curve25519/ladderstep_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										240
									
								
								vendor/github.com/keybase/go-crypto/curve25519/mont25519_amd64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										240
									
								
								vendor/github.com/keybase/go-crypto/curve25519/mont25519_amd64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,240 @@
 | 
				
			|||||||
 | 
					// 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/github.com/keybase/go-crypto/curve25519/mul_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/keybase/go-crypto/curve25519/mul_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,191 @@
 | 
				
			|||||||
 | 
					// 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/github.com/keybase/go-crypto/curve25519/square_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								vendor/github.com/keybase/go-crypto/curve25519/square_amd64.s
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,153 @@
 | 
				
			|||||||
 | 
					// 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/github.com/keybase/go-crypto/ed25519/ed25519.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								vendor/github.com/keybase/go-crypto/ed25519/ed25519.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,181 @@
 | 
				
			|||||||
 | 
					// 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"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/keybase/go-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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1422
									
								
								vendor/github.com/keybase/go-crypto/ed25519/internal/edwards25519/const.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1422
									
								
								vendor/github.com/keybase/go-crypto/ed25519/internal/edwards25519/const.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1771
									
								
								vendor/github.com/keybase/go-crypto/ed25519/internal/edwards25519/edwards25519.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1771
									
								
								vendor/github.com/keybase/go-crypto/ed25519/internal/edwards25519/edwards25519.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -4,14 +4,17 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
 | 
					// Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
 | 
				
			||||||
// very similar to PEM except that it has an additional CRC checksum.
 | 
					// very similar to PEM except that it has an additional CRC checksum.
 | 
				
			||||||
package armor // import "golang.org/x/crypto/openpgp/armor"
 | 
					package armor // import "github.com/keybase/go-crypto/openpgp/armor"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bufio"
 | 
						"bufio"
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
	"encoding/base64"
 | 
						"encoding/base64"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/errors"
 | 
					 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"unicode"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// A Block represents an OpenPGP armored structure.
 | 
					// A Block represents an OpenPGP armored structure.
 | 
				
			||||||
@@ -65,7 +68,14 @@ type lineReader struct {
 | 
				
			|||||||
	in  *bufio.Reader
 | 
						in  *bufio.Reader
 | 
				
			||||||
	buf []byte
 | 
						buf []byte
 | 
				
			||||||
	eof bool
 | 
						eof bool
 | 
				
			||||||
	crc uint32
 | 
						crc *uint32
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ourIsSpace checks if a rune is either space according to unicode
 | 
				
			||||||
 | 
					// package, or ZeroWidthSpace (which is not a space according to
 | 
				
			||||||
 | 
					// unicode module). Used to trim lines during header reading.
 | 
				
			||||||
 | 
					func ourIsSpace(r rune) bool {
 | 
				
			||||||
 | 
						return r == '\u200b' || unicode.IsSpace(r)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (l *lineReader) Read(p []byte) (n int, err error) {
 | 
					func (l *lineReader) Read(p []byte) (n int, err error) {
 | 
				
			||||||
@@ -79,13 +89,12 @@ func (l *lineReader) Read(p []byte) (n int, err error) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	line, isPrefix, err := l.in.ReadLine()
 | 
						line, _, err := l.in.ReadLine()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if isPrefix {
 | 
					
 | 
				
			||||||
		return 0, ArmorCorrupt
 | 
						line = bytes.TrimFunc(line, ourIsSpace)
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(line) == 5 && line[0] == '=' {
 | 
						if len(line) == 5 && line[0] == '=' {
 | 
				
			||||||
		// This is the checksum line
 | 
							// This is the checksum line
 | 
				
			||||||
@@ -95,13 +104,19 @@ func (l *lineReader) Read(p []byte) (n int, err error) {
 | 
				
			|||||||
		if m != 3 || err != nil {
 | 
							if m != 3 || err != nil {
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		l.crc = uint32(expectedBytes[0])<<16 |
 | 
							crc := uint32(expectedBytes[0])<<16 |
 | 
				
			||||||
			uint32(expectedBytes[1])<<8 |
 | 
								uint32(expectedBytes[1])<<8 |
 | 
				
			||||||
			uint32(expectedBytes[2])
 | 
								uint32(expectedBytes[2])
 | 
				
			||||||
 | 
							l.crc = &crc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		line, _, err = l.in.ReadLine()
 | 
							for {
 | 
				
			||||||
		if err != nil && err != io.EOF {
 | 
								line, _, err = l.in.ReadLine()
 | 
				
			||||||
			return
 | 
								if err != nil && err != io.EOF {
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if len(strings.TrimSpace(string(line))) > 0 {
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if !bytes.HasPrefix(line, armorEnd) {
 | 
							if !bytes.HasPrefix(line, armorEnd) {
 | 
				
			||||||
			return 0, ArmorCorrupt
 | 
								return 0, ArmorCorrupt
 | 
				
			||||||
@@ -111,8 +126,11 @@ func (l *lineReader) Read(p []byte) (n int, err error) {
 | 
				
			|||||||
		return 0, io.EOF
 | 
							return 0, io.EOF
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(line) > 96 {
 | 
						if bytes.HasPrefix(line, armorEnd) {
 | 
				
			||||||
		return 0, ArmorCorrupt
 | 
							// Unexpected ending, there was no checksum.
 | 
				
			||||||
 | 
							l.eof = true
 | 
				
			||||||
 | 
							l.crc = nil
 | 
				
			||||||
 | 
							return 0, io.EOF
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	n = copy(p, line)
 | 
						n = copy(p, line)
 | 
				
			||||||
@@ -142,7 +160,7 @@ func (r *openpgpReader) Read(p []byte) (n int, err error) {
 | 
				
			|||||||
	r.currentCRC = crc24(r.currentCRC, p[:n])
 | 
						r.currentCRC = crc24(r.currentCRC, p[:n])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err == io.EOF {
 | 
						if err == io.EOF {
 | 
				
			||||||
		if r.lReader.crc != uint32(r.currentCRC&crc24Mask) {
 | 
							if r.lReader.crc != nil && *r.lReader.crc != uint32(r.currentCRC&crc24Mask) {
 | 
				
			||||||
			return 0, ArmorCorrupt
 | 
								return 0, ArmorCorrupt
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -196,7 +214,7 @@ TryNextBlock:
 | 
				
			|||||||
			p.Header[lastKey] += string(line)
 | 
								p.Header[lastKey] += string(line)
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		line = bytes.TrimSpace(line)
 | 
							line = bytes.TrimFunc(line, ourIsSpace)
 | 
				
			||||||
		if len(line) == 0 {
 | 
							if len(line) == 0 {
 | 
				
			||||||
			break
 | 
								break
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -125,7 +125,7 @@ func (e *encoding) Close() (err error) {
 | 
				
			|||||||
	var b64ChecksumBytes [4]byte
 | 
						var b64ChecksumBytes [4]byte
 | 
				
			||||||
	base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:])
 | 
						base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine)
 | 
						return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine, []byte{'\n'})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Encode returns a WriteCloser which will encode the data written to it in
 | 
					// Encode returns a WriteCloser which will encode the data written to it in
 | 
				
			||||||
							
								
								
									
										282
									
								
								vendor/github.com/keybase/go-crypto/openpgp/ecdh/ecdh.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										282
									
								
								vendor/github.com/keybase/go-crypto/openpgp/ecdh/ecdh.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,282 @@
 | 
				
			|||||||
 | 
					package ecdh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"crypto"
 | 
				
			||||||
 | 
						"crypto/aes"
 | 
				
			||||||
 | 
						"crypto/elliptic"
 | 
				
			||||||
 | 
						"encoding/binary"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/curve25519"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PublicKey struct {
 | 
				
			||||||
 | 
						elliptic.Curve
 | 
				
			||||||
 | 
						X, Y *big.Int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PrivateKey struct {
 | 
				
			||||||
 | 
						PublicKey
 | 
				
			||||||
 | 
						X *big.Int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// KDF implements Key Derivation Function as described in
 | 
				
			||||||
 | 
					// https://tools.ietf.org/html/rfc6637#section-7
 | 
				
			||||||
 | 
					func (e *PublicKey) KDF(S []byte, kdfParams []byte, hash crypto.Hash) []byte {
 | 
				
			||||||
 | 
						sLen := (e.Curve.Params().P.BitLen() + 7) / 8
 | 
				
			||||||
 | 
						buf := new(bytes.Buffer)
 | 
				
			||||||
 | 
						buf.Write([]byte{0, 0, 0, 1})
 | 
				
			||||||
 | 
						if sLen > len(S) {
 | 
				
			||||||
 | 
							// zero-pad the S. If we got invalid S (bigger than curve's
 | 
				
			||||||
 | 
							// P), we are going to produce invalid key. Garbage in,
 | 
				
			||||||
 | 
							// garbage out.
 | 
				
			||||||
 | 
							buf.Write(make([]byte, sLen-len(S)))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						buf.Write(S)
 | 
				
			||||||
 | 
						buf.Write(kdfParams)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hashw := hash.New()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hashw.Write(buf.Bytes())
 | 
				
			||||||
 | 
						key := hashw.Sum(nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return key
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AESKeyUnwrap implements RFC 3394 Key Unwrapping. See
 | 
				
			||||||
 | 
					// http://tools.ietf.org/html/rfc3394#section-2.2.1
 | 
				
			||||||
 | 
					// Note: The second described algorithm ("index-based") is implemented
 | 
				
			||||||
 | 
					// here.
 | 
				
			||||||
 | 
					func AESKeyUnwrap(key, cipherText []byte) ([]byte, error) {
 | 
				
			||||||
 | 
						if len(cipherText)%8 != 0 {
 | 
				
			||||||
 | 
							return nil, errors.New("cipherText must by a multiple of 64 bits")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cipher, err := aes.NewCipher(key)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nblocks := len(cipherText)/8 - 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 1) Initialize variables.
 | 
				
			||||||
 | 
						// - Set A = C[0]
 | 
				
			||||||
 | 
						var A [aes.BlockSize]byte
 | 
				
			||||||
 | 
						copy(A[:8], cipherText[:8])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// For i = 1 to n
 | 
				
			||||||
 | 
						//   Set R[i] = C[i]
 | 
				
			||||||
 | 
						R := make([]byte, len(cipherText)-8)
 | 
				
			||||||
 | 
						copy(R, cipherText[8:])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 2) Compute intermediate values.
 | 
				
			||||||
 | 
						for j := 5; j >= 0; j-- {
 | 
				
			||||||
 | 
							for i := nblocks - 1; i >= 0; i-- {
 | 
				
			||||||
 | 
								// B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
 | 
				
			||||||
 | 
								// A = MSB(64, B)
 | 
				
			||||||
 | 
								t := uint64(nblocks*j + i + 1)
 | 
				
			||||||
 | 
								At := binary.BigEndian.Uint64(A[:8]) ^ t
 | 
				
			||||||
 | 
								binary.BigEndian.PutUint64(A[:8], At)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								copy(A[8:], R[i*8:i*8+8])
 | 
				
			||||||
 | 
								cipher.Decrypt(A[:], A[:])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// R[i] = LSB(B, 64)
 | 
				
			||||||
 | 
								copy(R[i*8:i*8+8], A[8:])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 3) Output results.
 | 
				
			||||||
 | 
						// If A is an appropriate initial value (see 2.2.3),
 | 
				
			||||||
 | 
						for i := 0; i < 8; i++ {
 | 
				
			||||||
 | 
							if A[i] != 0xA6 {
 | 
				
			||||||
 | 
								return nil, errors.New("Failed to unwrap key (A is not IV)")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return R, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AESKeyWrap implements RFC 3394 Key Wrapping. See
 | 
				
			||||||
 | 
					// https://tools.ietf.org/html/rfc3394#section-2.2.2
 | 
				
			||||||
 | 
					// Note: The second described algorithm ("index-based") is implemented
 | 
				
			||||||
 | 
					// here.
 | 
				
			||||||
 | 
					func AESKeyWrap(key, plainText []byte) ([]byte, error) {
 | 
				
			||||||
 | 
						if len(plainText)%8 != 0 {
 | 
				
			||||||
 | 
							return nil, errors.New("plainText must be a multiple of 64 bits")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cipher, err := aes.NewCipher(key) // NewCipher checks key size
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nblocks := len(plainText) / 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 1) Initialize variables.
 | 
				
			||||||
 | 
						var A [aes.BlockSize]byte
 | 
				
			||||||
 | 
						// Section 2.2.3.1 -- Initial Value
 | 
				
			||||||
 | 
						// http://tools.ietf.org/html/rfc3394#section-2.2.3.1
 | 
				
			||||||
 | 
						for i := 0; i < 8; i++ {
 | 
				
			||||||
 | 
							A[i] = 0xA6
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// For i = 1 to n
 | 
				
			||||||
 | 
						//   Set R[i] = P[i]
 | 
				
			||||||
 | 
						R := make([]byte, len(plainText))
 | 
				
			||||||
 | 
						copy(R, plainText)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 2) Calculate intermediate values.
 | 
				
			||||||
 | 
						for j := 0; j <= 5; j++ {
 | 
				
			||||||
 | 
							for i := 0; i < nblocks; i++ {
 | 
				
			||||||
 | 
								// B = AES(K, A | R[i])
 | 
				
			||||||
 | 
								copy(A[8:], R[i*8:i*8+8])
 | 
				
			||||||
 | 
								cipher.Encrypt(A[:], A[:])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// (Assume B = A)
 | 
				
			||||||
 | 
								// A = MSB(64, B) ^ t where t = (n*j)+1
 | 
				
			||||||
 | 
								t := uint64(j*nblocks + i + 1)
 | 
				
			||||||
 | 
								At := binary.BigEndian.Uint64(A[:8]) ^ t
 | 
				
			||||||
 | 
								binary.BigEndian.PutUint64(A[:8], At)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// R[i] = LSB(64, B)
 | 
				
			||||||
 | 
								copy(R[i*8:i*8+8], A[8:])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 3) Output results.
 | 
				
			||||||
 | 
						// Set C[0] = A
 | 
				
			||||||
 | 
						// For i = 1 to n
 | 
				
			||||||
 | 
						//   C[i] = R[i]
 | 
				
			||||||
 | 
						return append(A[:8], R...), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PadBuffer pads byte buffer buf to a length being multiple of
 | 
				
			||||||
 | 
					// blockLen. Additional bytes appended to the buffer have value of the
 | 
				
			||||||
 | 
					// number padded bytes. E.g. if the buffer is 3 bytes short of being
 | 
				
			||||||
 | 
					// 40 bytes total, the appended bytes will be [03, 03, 03].
 | 
				
			||||||
 | 
					func PadBuffer(buf []byte, blockLen int) []byte {
 | 
				
			||||||
 | 
						padding := blockLen - (len(buf) % blockLen)
 | 
				
			||||||
 | 
						if padding == 0 {
 | 
				
			||||||
 | 
							return buf
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						padBuf := make([]byte, padding)
 | 
				
			||||||
 | 
						for i := 0; i < padding; i++ {
 | 
				
			||||||
 | 
							padBuf[i] = byte(padding)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return append(buf, padBuf...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UnpadBuffer verifies that buffer contains proper padding and
 | 
				
			||||||
 | 
					// returns buffer without the padding, or nil if the padding was
 | 
				
			||||||
 | 
					// invalid.
 | 
				
			||||||
 | 
					func UnpadBuffer(buf []byte, dataLen int) []byte {
 | 
				
			||||||
 | 
						padding := len(buf) - dataLen
 | 
				
			||||||
 | 
						outBuf := buf[:dataLen]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := dataLen; i < len(buf); i++ {
 | 
				
			||||||
 | 
							if buf[i] != byte(padding) {
 | 
				
			||||||
 | 
								// Invalid padding - bail out
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return outBuf
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *PublicKey) Encrypt(random io.Reader, kdfParams []byte, plain []byte, hash crypto.Hash, kdfKeySize int) (Vx *big.Int, Vy *big.Int, C []byte, err error) {
 | 
				
			||||||
 | 
						// Vx, Vy - encryption key
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Note for Curve 25519 - curve25519 library already does key
 | 
				
			||||||
 | 
						// clamping in scalarMult, so we can use generic random scalar
 | 
				
			||||||
 | 
						// generation from elliptic.
 | 
				
			||||||
 | 
						priv, Vx, Vy, err := elliptic.GenerateKey(e.Curve, random)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Sx, Sy - shared secret
 | 
				
			||||||
 | 
						Sx, _ := e.Curve.ScalarMult(e.X, e.Y, priv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Encrypt the payload with KDF-ed S as the encryption key. Pass
 | 
				
			||||||
 | 
						// the ciphertext along with V to the recipient. Recipient can
 | 
				
			||||||
 | 
						// generate S using V and their priv key, and then KDF(S), on
 | 
				
			||||||
 | 
						// their own, to get encryption key and decrypt the ciphertext,
 | 
				
			||||||
 | 
						// revealing encryption key for symmetric encryption later.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						plain = PadBuffer(plain, 8)
 | 
				
			||||||
 | 
						key := e.KDF(Sx.Bytes(), kdfParams, hash)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Take only as many bytes from key as the key length (the hash
 | 
				
			||||||
 | 
						// result might be bigger)
 | 
				
			||||||
 | 
						encrypted, err := AESKeyWrap(key[:kdfKeySize], plain)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return Vx, Vy, encrypted, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *PrivateKey) DecryptShared(X, Y *big.Int) []byte {
 | 
				
			||||||
 | 
						Sx, _ := e.Curve.ScalarMult(X, Y, e.X.Bytes())
 | 
				
			||||||
 | 
						return Sx.Bytes()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func countBits(buffer []byte) int {
 | 
				
			||||||
 | 
						var headerLen int
 | 
				
			||||||
 | 
						switch buffer[0] {
 | 
				
			||||||
 | 
						case 0x4:
 | 
				
			||||||
 | 
							headerLen = 3
 | 
				
			||||||
 | 
						case 0x40:
 | 
				
			||||||
 | 
							headerLen = 7
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							// Unexpected header - but we can still count the bits.
 | 
				
			||||||
 | 
							val := buffer[0]
 | 
				
			||||||
 | 
							headerLen = 0
 | 
				
			||||||
 | 
							for val > 0 {
 | 
				
			||||||
 | 
								val = val / 2
 | 
				
			||||||
 | 
								headerLen++
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return headerLen + (len(buffer)-1)*8
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// elliptic.Marshal and elliptic.Unmarshal only marshals uncompressed
 | 
				
			||||||
 | 
					// 0x4 MPI types. These functions will check if the curve is cv25519,
 | 
				
			||||||
 | 
					// and if so, use 0x40 compressed type to (un)marshal. Otherwise,
 | 
				
			||||||
 | 
					// elliptic.(Un)marshal will be called.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Marshal encodes point into either 0x4 uncompressed point form, or
 | 
				
			||||||
 | 
					// 0x40 compressed point for Curve 25519.
 | 
				
			||||||
 | 
					func Marshal(curve elliptic.Curve, x, y *big.Int) (buf []byte, bitSize int) {
 | 
				
			||||||
 | 
						// NOTE: Read more about MPI encoding in the RFC:
 | 
				
			||||||
 | 
						// https://tools.ietf.org/html/rfc4880#section-3.2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We are required to encode size in bits, counting from the most-
 | 
				
			||||||
 | 
						// significant non-zero bit. So assuming that the buffer never
 | 
				
			||||||
 | 
						// starts with 0x00, we only need to count bits in the first byte
 | 
				
			||||||
 | 
						// - and in current implentation it will always be 0x4 or 0x40.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cv, ok := curve25519.ToCurve25519(curve)
 | 
				
			||||||
 | 
						if ok {
 | 
				
			||||||
 | 
							buf = cv.MarshalType40(x, y)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							buf = elliptic.Marshal(curve, x, y)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return buf, countBits(buf)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Unmarshal converts point, serialized by Marshal, into x, y pair.
 | 
				
			||||||
 | 
					// For 0x40 compressed points (for Curve 25519), y will always be 0.
 | 
				
			||||||
 | 
					// It is an error if point is not on the curve, On error, x = nil.
 | 
				
			||||||
 | 
					func Unmarshal(curve elliptic.Curve, data []byte) (x, y *big.Int) {
 | 
				
			||||||
 | 
						cv, ok := curve25519.ToCurve25519(curve)
 | 
				
			||||||
 | 
						if ok {
 | 
				
			||||||
 | 
							return cv.UnmarshalType40(data)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return elliptic.Unmarshal(curve, data)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -10,7 +10,7 @@
 | 
				
			|||||||
// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it
 | 
					// 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
 | 
					// unsuitable for other protocols. RSA should be used in preference in any
 | 
				
			||||||
// case.
 | 
					// case.
 | 
				
			||||||
package elgamal // import "golang.org/x/crypto/openpgp/elgamal"
 | 
					package elgamal // import "github.com/keybase/go-crypto/openpgp/elgamal"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"crypto/rand"
 | 
						"crypto/rand"
 | 
				
			||||||
@@ -3,7 +3,7 @@
 | 
				
			|||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Package errors contains common error types for the OpenPGP packages.
 | 
					// Package errors contains common error types for the OpenPGP packages.
 | 
				
			||||||
package errors // import "golang.org/x/crypto/openpgp/errors"
 | 
					package errors // import "github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
							
								
								
									
										902
									
								
								vendor/github.com/keybase/go-crypto/openpgp/keys.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										902
									
								
								vendor/github.com/keybase/go-crypto/openpgp/keys.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,902 @@
 | 
				
			|||||||
 | 
					// 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/hmac"
 | 
				
			||||||
 | 
						"encoding/binary"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/armor"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/packet"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/rsa"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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
 | 
				
			||||||
 | 
						// Revocations that are signed by designated revokers. Reading keys
 | 
				
			||||||
 | 
						// will not verify these revocations, because it won't have access to
 | 
				
			||||||
 | 
						// issuers' public keys, API consumers should do this instead (or
 | 
				
			||||||
 | 
						// not, and just assume that the key is probably revoked).
 | 
				
			||||||
 | 
						UnverifiedRevocations []*packet.Signature
 | 
				
			||||||
 | 
						Subkeys               []Subkey
 | 
				
			||||||
 | 
						BadSubkeys            []BadSubkey
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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
 | 
				
			||||||
 | 
						Revocation    *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
 | 
				
			||||||
 | 
						Revocation *packet.Signature
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// BadSubkey is one that failed reconstruction, but we'll keep it around for
 | 
				
			||||||
 | 
					// informational purposes.
 | 
				
			||||||
 | 
					type BadSubkey struct {
 | 
				
			||||||
 | 
						Subkey
 | 
				
			||||||
 | 
						Err error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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
 | 
				
			||||||
 | 
						KeyFlags      packet.KeyFlagBits
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A KeyRing provides access to public and private keys.
 | 
				
			||||||
 | 
					type KeyRing interface {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// KeysById returns the set of keys that have the given key id.
 | 
				
			||||||
 | 
						// fp can be optionally supplied, which is the full key fingerprint.
 | 
				
			||||||
 | 
						// If it's provided, then it must match. This comes up in the case
 | 
				
			||||||
 | 
						// of GPG subpacket 33.
 | 
				
			||||||
 | 
						KeysById(id uint64, fp []byte) []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.
 | 
				
			||||||
 | 
						// fp can be optionally supplied, which is the full key fingerprint.
 | 
				
			||||||
 | 
						// If it's provided, then it must match. This comes up in the case
 | 
				
			||||||
 | 
						// of GPG subpacket 33.
 | 
				
			||||||
 | 
						KeysByIdUsage(id uint64, fp []byte, 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 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// NOTE(maxtaco)
 | 
				
			||||||
 | 
							// If there is a Flags subpacket, then we have to follow it, and only
 | 
				
			||||||
 | 
							// use keys that are marked for Encryption of Communication.  If there
 | 
				
			||||||
 | 
							// isn't a Flags subpacket, and this is an Encrypt-Only key (right now only ElGamal
 | 
				
			||||||
 | 
							// suffices), then we implicitly use it. The check for primary below is a little
 | 
				
			||||||
 | 
							// more open-ended, but for now, let's be strict and potentially open up
 | 
				
			||||||
 | 
							// if we see bugs in the wild.
 | 
				
			||||||
 | 
							//
 | 
				
			||||||
 | 
							// One more note: old DSA/ElGamal keys tend not to have the Flags subpacket,
 | 
				
			||||||
 | 
							// so this sort of thing is pretty important for encrypting to older keys.
 | 
				
			||||||
 | 
							//
 | 
				
			||||||
 | 
							if ((subkey.Sig.FlagsValid && subkey.Sig.FlagEncryptCommunications) ||
 | 
				
			||||||
 | 
								(!subkey.Sig.FlagsValid && subkey.PublicKey.PubKeyAlgo == packet.PubKeyAlgoElGamal)) &&
 | 
				
			||||||
 | 
								subkey.PublicKey.PubKeyAlgo.CanEncrypt() &&
 | 
				
			||||||
 | 
								!subkey.Sig.KeyExpired(now) &&
 | 
				
			||||||
 | 
								subkey.Revocation == nil &&
 | 
				
			||||||
 | 
								(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, subkey.Sig.GetKeyFlags()}, 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.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// NOTE(maxtaco) - see note above, how this policy is a little too open-ended
 | 
				
			||||||
 | 
						// for my liking, but leave it for now.
 | 
				
			||||||
 | 
						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, i.SelfSignature.GetKeyFlags()}, 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.PrivateKey.PrivateKey != nil &&
 | 
				
			||||||
 | 
								subkey.PublicKey.PubKeyAlgo.CanSign() &&
 | 
				
			||||||
 | 
								subkey.Revocation == nil &&
 | 
				
			||||||
 | 
								!subkey.Sig.KeyExpired(now) {
 | 
				
			||||||
 | 
								candidateSubkey = i
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if candidateSubkey != -1 {
 | 
				
			||||||
 | 
							subkey := e.Subkeys[candidateSubkey]
 | 
				
			||||||
 | 
							return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig, subkey.Sig.GetKeyFlags()}, 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) &&
 | 
				
			||||||
 | 
							e.PrimaryKey.PubKeyAlgo.CanSign() &&
 | 
				
			||||||
 | 
							!i.SelfSignature.KeyExpired(now) &&
 | 
				
			||||||
 | 
							e.PrivateKey.PrivateKey != nil {
 | 
				
			||||||
 | 
							return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature, i.SelfSignature.GetKeyFlags()}, true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return Key{}, false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// An EntityList contains one or more Entities.
 | 
				
			||||||
 | 
					type EntityList []*Entity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func keyMatchesIdAndFingerprint(key *packet.PublicKey, id uint64, fp []byte) bool {
 | 
				
			||||||
 | 
						if key.KeyId != id {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if fp == nil {
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return hmac.Equal(fp, key.Fingerprint[:])
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// KeysById returns the set of keys that have the given key id.
 | 
				
			||||||
 | 
					// fp can be optionally supplied, which is the full key fingerprint.
 | 
				
			||||||
 | 
					// If it's provided, then it must match. This comes up in the case
 | 
				
			||||||
 | 
					// of GPG subpacket 33.
 | 
				
			||||||
 | 
					func (el EntityList) KeysById(id uint64, fp []byte) (keys []Key) {
 | 
				
			||||||
 | 
						for _, e := range el {
 | 
				
			||||||
 | 
							if keyMatchesIdAndFingerprint(e.PrimaryKey, id, fp) {
 | 
				
			||||||
 | 
								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
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var keyFlags packet.KeyFlagBits
 | 
				
			||||||
 | 
								for _, ident := range e.Identities {
 | 
				
			||||||
 | 
									keyFlags.Merge(ident.SelfSignature.GetKeyFlags())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig, keyFlags})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, subKey := range e.Subkeys {
 | 
				
			||||||
 | 
								if keyMatchesIdAndFingerprint(subKey.PublicKey, id, fp) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// If there's both a a revocation and a sig, then take the
 | 
				
			||||||
 | 
									// revocation. Otherwise, we can proceed with the sig.
 | 
				
			||||||
 | 
									sig := subKey.Revocation
 | 
				
			||||||
 | 
									if sig == nil {
 | 
				
			||||||
 | 
										sig = subKey.Sig
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, sig, sig.GetKeyFlags()})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						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.
 | 
				
			||||||
 | 
					// fp can be optionally supplied, which is the full key fingerprint.
 | 
				
			||||||
 | 
					// If it's provided, then it must match. This comes up in the case
 | 
				
			||||||
 | 
					// of GPG subpacket 33.
 | 
				
			||||||
 | 
					func (el EntityList) KeysByIdUsage(id uint64, fp []byte, requiredUsage byte) (keys []Key) {
 | 
				
			||||||
 | 
						for _, key := range el.KeysById(id, fp) {
 | 
				
			||||||
 | 
							if len(key.Entity.Revocations) > 0 {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if key.SelfSignature.RevocationReason != nil {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if requiredUsage != 0 {
 | 
				
			||||||
 | 
								var usage byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								switch {
 | 
				
			||||||
 | 
								case key.KeyFlags.Valid:
 | 
				
			||||||
 | 
									usage = key.KeyFlags.BitField
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case key.PublicKey.PubKeyAlgo == packet.PubKeyAlgoElGamal:
 | 
				
			||||||
 | 
									// We also need to handle the case where, although the sig's
 | 
				
			||||||
 | 
									// flags aren't valid, the key can is implicitly usable for
 | 
				
			||||||
 | 
									// encryption by virtue of being ElGamal. See also the comment
 | 
				
			||||||
 | 
									// in encryptionKey() above.
 | 
				
			||||||
 | 
									usage |= packet.KeyFlagEncryptCommunications
 | 
				
			||||||
 | 
									usage |= packet.KeyFlagEncryptStorage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case key.PublicKey.PubKeyAlgo == packet.PubKeyAlgoDSA ||
 | 
				
			||||||
 | 
									key.PublicKey.PubKeyAlgo == packet.PubKeyAlgoECDSA ||
 | 
				
			||||||
 | 
									key.PublicKey.PubKeyAlgo == packet.PubKeyAlgoEdDSA:
 | 
				
			||||||
 | 
									usage |= packet.KeyFlagSign
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// For a primary RSA key without any key flags, be as permissiable
 | 
				
			||||||
 | 
								// as possible.
 | 
				
			||||||
 | 
								case key.PublicKey.PubKeyAlgo == packet.PubKeyAlgoRSA &&
 | 
				
			||||||
 | 
									keyMatchesIdAndFingerprint(key.Entity.PrimaryKey, id, fp):
 | 
				
			||||||
 | 
									usage = (packet.KeyFlagCertify | packet.KeyFlagSign |
 | 
				
			||||||
 | 
										packet.KeyFlagEncryptCommunications | 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.PrivateKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) {
 | 
				
			||||||
 | 
									keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig, subKey.Sig.GetKeyFlags()})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						designatedRevokers := make(map[uint64]bool)
 | 
				
			||||||
 | 
					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:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Make a new Identity object, that we might wind up throwing away.
 | 
				
			||||||
 | 
								// We'll only add it if we get a valid self-signature over this
 | 
				
			||||||
 | 
								// userID.
 | 
				
			||||||
 | 
								current = new(Identity)
 | 
				
			||||||
 | 
								current.Name = pkt.Id
 | 
				
			||||||
 | 
								current.UserId = pkt
 | 
				
			||||||
 | 
							case *packet.Signature:
 | 
				
			||||||
 | 
								if pkt.SigType == packet.SigTypeKeyRevocation {
 | 
				
			||||||
 | 
									// These revocations won't revoke UIDs (see
 | 
				
			||||||
 | 
									// SigTypeIdentityRevocation). Handle these first,
 | 
				
			||||||
 | 
									// because key might have revocation coming from
 | 
				
			||||||
 | 
									// another key (designated revoke).
 | 
				
			||||||
 | 
									revocations = append(revocations, pkt)
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// These are signatures by other people on this key. Let's just ignore them
 | 
				
			||||||
 | 
								// from the beginning, since they shouldn't affect our key decoding one way
 | 
				
			||||||
 | 
								// or the other.
 | 
				
			||||||
 | 
								if pkt.IssuerKeyId != nil && *pkt.IssuerKeyId != e.PrimaryKey.KeyId {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// If this is a signature made by the keyholder, and the signature has stubbed out
 | 
				
			||||||
 | 
								// critical packets, then *now* we need to bail out.
 | 
				
			||||||
 | 
								if e := pkt.StubbedOutCriticalError; e != nil {
 | 
				
			||||||
 | 
									return nil, e
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Next handle the case of a self-signature. According to RFC8440,
 | 
				
			||||||
 | 
								// Section 5.2.3.3, if there are several self-signatures,
 | 
				
			||||||
 | 
								// we should take the newer one.  If they were both created
 | 
				
			||||||
 | 
								// at the same time, but one of them has keyflags specified and the
 | 
				
			||||||
 | 
								// other doesn't, keep the one with the keyflags. We have actually
 | 
				
			||||||
 | 
								// seen this in the wild (see the 'Yield' test in read_test.go).
 | 
				
			||||||
 | 
								// If there is a tie, and both have the same value for FlagsValid,
 | 
				
			||||||
 | 
								// then "last writer wins."
 | 
				
			||||||
 | 
								//
 | 
				
			||||||
 | 
								// HOWEVER! We have seen yet more keys in the wild (see the 'Spiros'
 | 
				
			||||||
 | 
								// test in read_test.go), in which the later self-signature is a bunch
 | 
				
			||||||
 | 
								// of junk, and doesn't even specify key flags. Does it really make
 | 
				
			||||||
 | 
								// sense to overwrite reasonable key flags with the empty set? I'm not
 | 
				
			||||||
 | 
								// sure what that would be trying to achieve, and plus GPG seems to be
 | 
				
			||||||
 | 
								// ok with this situation, and ignores the later (empty) keyflag set.
 | 
				
			||||||
 | 
								// So further tighten our overwrite rules, and only allow the later
 | 
				
			||||||
 | 
								// signature to overwrite the earlier signature if so doing won't
 | 
				
			||||||
 | 
								// trash the key flags.
 | 
				
			||||||
 | 
								if current != nil &&
 | 
				
			||||||
 | 
									(current.SelfSignature == nil ||
 | 
				
			||||||
 | 
										(!pkt.CreationTime.Before(current.SelfSignature.CreationTime) &&
 | 
				
			||||||
 | 
											(pkt.FlagsValid || !current.SelfSignature.FlagsValid))) &&
 | 
				
			||||||
 | 
									(pkt.SigType == packet.SigTypePositiveCert || pkt.SigType == packet.SigTypeGenericCert) &&
 | 
				
			||||||
 | 
									pkt.IssuerKeyId != nil &&
 | 
				
			||||||
 | 
									*pkt.IssuerKeyId == e.PrimaryKey.KeyId {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if err = e.PrimaryKey.VerifyUserIdSignature(current.Name, e.PrimaryKey, pkt); err == nil {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										current.SelfSignature = pkt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// NOTE(maxtaco) 2016.01.11
 | 
				
			||||||
 | 
										// Only register an identity once we've gotten a valid self-signature.
 | 
				
			||||||
 | 
										// It's possible therefore for us to throw away `current` in the case
 | 
				
			||||||
 | 
										// no valid self-signatures were found. That's OK as long as there are
 | 
				
			||||||
 | 
										// other identies that make sense.
 | 
				
			||||||
 | 
										//
 | 
				
			||||||
 | 
										// NOTE! We might later see a revocation for this very same UID, and it
 | 
				
			||||||
 | 
										// won't be undone. We've preserved this feature from the original
 | 
				
			||||||
 | 
										// Google OpenPGP we forked from.
 | 
				
			||||||
 | 
										e.Identities[current.Name] = current
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										// We really should warn that there was a failure here. Not raise an error
 | 
				
			||||||
 | 
										// since this really shouldn't be a fail-stop error.
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if current != nil && pkt.SigType == packet.SigTypeIdentityRevocation {
 | 
				
			||||||
 | 
									if err = e.PrimaryKey.VerifyUserIdSignature(current.Name, e.PrimaryKey, pkt); err == nil {
 | 
				
			||||||
 | 
										// Note: we are not removing the identity from
 | 
				
			||||||
 | 
										// e.Identities. Caller can always filter by Revocation
 | 
				
			||||||
 | 
										// field to ignore revoked identities.
 | 
				
			||||||
 | 
										current.Revocation = pkt
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if pkt.SigType == packet.SigTypeDirectSignature {
 | 
				
			||||||
 | 
									if err = e.PrimaryKey.VerifyRevocationSignature(e.PrimaryKey, pkt); err == nil {
 | 
				
			||||||
 | 
										if desig := pkt.DesignatedRevoker; desig != nil {
 | 
				
			||||||
 | 
											// If it's a designated revoker signature, take last 8 octects
 | 
				
			||||||
 | 
											// of fingerprint as Key ID and save it to designatedRevokers
 | 
				
			||||||
 | 
											// map. We consult this map later to see if a foreign
 | 
				
			||||||
 | 
											// revocation should be added to UnverifiedRevocations.
 | 
				
			||||||
 | 
											keyID := binary.BigEndian.Uint64(desig.Fingerprint[len(desig.Fingerprint)-8:])
 | 
				
			||||||
 | 
											designatedRevokers[keyID] = true
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if current == nil {
 | 
				
			||||||
 | 
									// NOTE(maxtaco)
 | 
				
			||||||
 | 
									//
 | 
				
			||||||
 | 
									// See https://github.com/keybase/client/issues/2666
 | 
				
			||||||
 | 
									//
 | 
				
			||||||
 | 
									// There might have been a user attribute picture before this signature,
 | 
				
			||||||
 | 
									// in which case this is still a valid PGP key. In the future we might
 | 
				
			||||||
 | 
									// not ignore user attributes (like picture). But either way, it doesn't
 | 
				
			||||||
 | 
									// make sense to bail out here. Keep looking for other valid signatures.
 | 
				
			||||||
 | 
									//
 | 
				
			||||||
 | 
									// Used to be:
 | 
				
			||||||
 | 
									//    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 {
 | 
				
			||||||
 | 
							if revocation.IssuerKeyId == nil || *revocation.IssuerKeyId == e.PrimaryKey.KeyId {
 | 
				
			||||||
 | 
								// Key revokes itself, something that we can verify.
 | 
				
			||||||
 | 
								err = e.PrimaryKey.VerifyRevocationSignature(e.PrimaryKey, revocation)
 | 
				
			||||||
 | 
								if err == nil {
 | 
				
			||||||
 | 
									e.Revocations = append(e.Revocations, revocation)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									return nil, errors.StructuralError("revocation signature signed by alternate key")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if revocation.IssuerKeyId != nil {
 | 
				
			||||||
 | 
								if _, ok := designatedRevokers[*revocation.IssuerKeyId]; ok {
 | 
				
			||||||
 | 
									// Revocation is done by certified designated revoker,
 | 
				
			||||||
 | 
									// but we can't verify the revocation.
 | 
				
			||||||
 | 
									e.UnverifiedRevocations = append(e.UnverifiedRevocations, revocation)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
						var lastErr error
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							p, err := packets.Next()
 | 
				
			||||||
 | 
							if err == io.EOF {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return errors.StructuralError("subkey signature invalid: " + err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							sig, ok := p.(*packet.Signature)
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								// Hit a non-signature packet, so assume we're up to the next key
 | 
				
			||||||
 | 
								packets.Unread(p)
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if st := sig.SigType; st != packet.SigTypeSubkeyBinding && st != packet.SigTypeSubkeyRevocation {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Note(maxtaco):
 | 
				
			||||||
 | 
								// We used to error out here, but instead, let's fast-forward past
 | 
				
			||||||
 | 
								// packets that are in the wrong place (like misplaced 0x13 signatures)
 | 
				
			||||||
 | 
								// until we get to one that works.  For a test case,
 | 
				
			||||||
 | 
								// see TestWithBadSubkeySignaturePackets.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, sig)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								// Non valid signature, so again, no need to abandon all hope, just continue;
 | 
				
			||||||
 | 
								// make a note of the error we hit.
 | 
				
			||||||
 | 
								lastErr = errors.StructuralError("subkey signature invalid: " + err.Error())
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							switch sig.SigType {
 | 
				
			||||||
 | 
							case packet.SigTypeSubkeyBinding:
 | 
				
			||||||
 | 
								// Does the "new" sig set expiration to later date than
 | 
				
			||||||
 | 
								// "previous" sig?
 | 
				
			||||||
 | 
								if subKey.Sig == nil || subKey.Sig.ExpiresBeforeOther(sig) {
 | 
				
			||||||
 | 
									subKey.Sig = sig
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							case packet.SigTypeSubkeyRevocation:
 | 
				
			||||||
 | 
								// First writer wins
 | 
				
			||||||
 | 
								if subKey.Revocation == nil {
 | 
				
			||||||
 | 
									subKey.Revocation = sig
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if subKey.Sig != nil {
 | 
				
			||||||
 | 
							e.Subkeys = append(e.Subkeys, subKey)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if lastErr == nil {
 | 
				
			||||||
 | 
								lastErr = errors.StructuralError("Subkey wasn't signed; expected a 'binding' signature")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							e.BadSubkeys = append(e.BadSubkeys, BadSubkey{Subkey: subKey, Err: lastErr})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if e.PrivateKey.PrivateKey != nil {
 | 
				
			||||||
 | 
								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
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// Workaround shortcoming of SignKey(), which doesn't work to reverse-sign
 | 
				
			||||||
 | 
							// sub-signing keys. So if requested, just reuse the signatures already
 | 
				
			||||||
 | 
							// available to us (if we read this key from a keyring).
 | 
				
			||||||
 | 
							if e.PrivateKey.PrivateKey != nil && !config.ReuseSignatures() {
 | 
				
			||||||
 | 
								err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if subkey.Revocation != nil {
 | 
				
			||||||
 | 
								err = subkey.Revocation.Serialize(w)
 | 
				
			||||||
 | 
								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
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if subkey.Revocation != nil {
 | 
				
			||||||
 | 
								err = subkey.Revocation.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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CopySubkeyRevocations copies subkey revocations from the src Entity over
 | 
				
			||||||
 | 
					// to the receiver entity. We need this because `gpg --export-secret-key` does
 | 
				
			||||||
 | 
					// not appear to output subkey revocations.  In this case we need to manually
 | 
				
			||||||
 | 
					// merge with the output of `gpg --export`.
 | 
				
			||||||
 | 
					func (e *Entity) CopySubkeyRevocations(src *Entity) {
 | 
				
			||||||
 | 
						m := make(map[[20]byte]*packet.Signature)
 | 
				
			||||||
 | 
						for _, subkey := range src.Subkeys {
 | 
				
			||||||
 | 
							if subkey.Revocation != nil {
 | 
				
			||||||
 | 
								m[subkey.PublicKey.Fingerprint] = subkey.Revocation
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for i, subkey := range e.Subkeys {
 | 
				
			||||||
 | 
							if r := m[subkey.PublicKey.Fingerprint]; r != nil {
 | 
				
			||||||
 | 
								e.Subkeys[i].Revocation = r
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CheckDesignatedRevokers will try to confirm any of designated
 | 
				
			||||||
 | 
					// revocation of entity. For this function to work, revocation
 | 
				
			||||||
 | 
					// issuer's key should be found in keyring. First successfully
 | 
				
			||||||
 | 
					// verified designated revocation is returned along with the key that
 | 
				
			||||||
 | 
					// verified it.
 | 
				
			||||||
 | 
					func FindVerifiedDesignatedRevoke(keyring KeyRing, entity *Entity) (*packet.Signature, *Key) {
 | 
				
			||||||
 | 
						for _, sig := range entity.UnverifiedRevocations {
 | 
				
			||||||
 | 
							if sig.IssuerKeyId == nil {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							issuerKeyId := *sig.IssuerKeyId
 | 
				
			||||||
 | 
							issuerFingerprint := sig.IssuerFingerprint
 | 
				
			||||||
 | 
							keys := keyring.KeysByIdUsage(issuerKeyId, issuerFingerprint, packet.KeyFlagSign)
 | 
				
			||||||
 | 
							if len(keys) == 0 {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for _, key := range keys {
 | 
				
			||||||
 | 
								err := key.PublicKey.VerifyRevocationSignature(entity.PrimaryKey, sig)
 | 
				
			||||||
 | 
								if err == nil {
 | 
				
			||||||
 | 
									return sig, &key
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -8,9 +8,10 @@ import (
 | 
				
			|||||||
	"compress/bzip2"
 | 
						"compress/bzip2"
 | 
				
			||||||
	"compress/flate"
 | 
						"compress/flate"
 | 
				
			||||||
	"compress/zlib"
 | 
						"compress/zlib"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/errors"
 | 
					 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Compressed represents a compressed OpenPGP packet. The decompressed contents
 | 
					// Compressed represents a compressed OpenPGP packet. The decompressed contents
 | 
				
			||||||
@@ -46,6 +46,9 @@ type Config struct {
 | 
				
			|||||||
	// RSABits is the number of bits in new RSA keys made with NewEntity.
 | 
						// RSABits is the number of bits in new RSA keys made with NewEntity.
 | 
				
			||||||
	// If zero, then 2048 bit keys are created.
 | 
						// If zero, then 2048 bit keys are created.
 | 
				
			||||||
	RSABits int
 | 
						RSABits int
 | 
				
			||||||
 | 
						// ReuseSignatures tells us to reuse existing Signatures
 | 
				
			||||||
 | 
						// on serialized output.
 | 
				
			||||||
 | 
						ReuseSignaturesOnSerialize bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Config) Random() io.Reader {
 | 
					func (c *Config) Random() io.Reader {
 | 
				
			||||||
@@ -89,3 +92,7 @@ func (c *Config) PasswordHashIterations() int {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return c.S2KCount
 | 
						return c.S2KCount
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Config) ReuseSignatures() bool {
 | 
				
			||||||
 | 
						return c != nil && c.ReuseSignaturesOnSerialize
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										104
									
								
								vendor/github.com/keybase/go-crypto/openpgp/packet/ecdh.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								vendor/github.com/keybase/go-crypto/openpgp/packet/ecdh.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,104 @@
 | 
				
			|||||||
 | 
					package packet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/ecdh"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/s2k"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ECDHKdfParams generates KDF parameters sequence for given
 | 
				
			||||||
 | 
					// PublicKey. See https://tools.ietf.org/html/rfc6637#section-8
 | 
				
			||||||
 | 
					func ECDHKdfParams(pub *PublicKey) []byte {
 | 
				
			||||||
 | 
						buf := new(bytes.Buffer)
 | 
				
			||||||
 | 
						oid := pub.ec.oid
 | 
				
			||||||
 | 
						buf.WriteByte(byte(len(oid)))
 | 
				
			||||||
 | 
						buf.Write(oid)
 | 
				
			||||||
 | 
						buf.WriteByte(18) // ECDH TYPE
 | 
				
			||||||
 | 
						pub.ecdh.serialize(buf)
 | 
				
			||||||
 | 
						buf.WriteString("Anonymous Sender    ")
 | 
				
			||||||
 | 
						buf.Write(pub.Fingerprint[:])
 | 
				
			||||||
 | 
						return buf.Bytes()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func decryptKeyECDH(priv *PrivateKey, X, Y *big.Int, C []byte) (out []byte, err error) {
 | 
				
			||||||
 | 
						ecdhpriv, ok := priv.PrivateKey.(*ecdh.PrivateKey)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return nil, errors.InvalidArgumentError("bad internal ECDH key")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Sx := ecdhpriv.DecryptShared(X, Y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						kdfParams := ECDHKdfParams(&priv.PublicKey)
 | 
				
			||||||
 | 
						hash, ok := s2k.HashIdToHash(byte(priv.ecdh.KdfHash))
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return nil, errors.InvalidArgumentError("invalid hash id in private key")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						key := ecdhpriv.KDF(Sx, kdfParams, hash)
 | 
				
			||||||
 | 
						keySize := CipherFunction(priv.ecdh.KdfAlgo).KeySize()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						decrypted, err := ecdh.AESKeyUnwrap(key[:keySize], C)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We have to "read ahead" to discover real length of the
 | 
				
			||||||
 | 
						// encryption key and properly unpad buffer.
 | 
				
			||||||
 | 
						cipherFunc := CipherFunction(decrypted[0])
 | 
				
			||||||
 | 
						// +3 bytes = 1-byte cipher id and checksum 2-byte checksum.
 | 
				
			||||||
 | 
						out = ecdh.UnpadBuffer(decrypted, cipherFunc.KeySize()+3)
 | 
				
			||||||
 | 
						if out == nil {
 | 
				
			||||||
 | 
							return nil, errors.InvalidArgumentError("invalid padding while ECDH")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return out, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func serializeEncryptedKeyECDH(w io.Writer, rand io.Reader, header [10]byte, pub *PublicKey, keyBlock []byte) error {
 | 
				
			||||||
 | 
						ecdhpub := pub.PublicKey.(*ecdh.PublicKey)
 | 
				
			||||||
 | 
						kdfParams := ECDHKdfParams(pub)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hash, ok := s2k.HashIdToHash(byte(pub.ecdh.KdfHash))
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return errors.InvalidArgumentError("invalid hash id in private key")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						kdfKeySize := CipherFunction(pub.ecdh.KdfAlgo).KeySize()
 | 
				
			||||||
 | 
						Vx, Vy, C, err := ecdhpub.Encrypt(rand, kdfParams, keyBlock, hash, kdfKeySize)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mpis, mpiBitLen := ecdh.Marshal(ecdhpub.Curve, Vx, Vy)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						packetLen := len(header) /* header length in bytes */
 | 
				
			||||||
 | 
						packetLen += 2 /* mpi length in bits */ + len(mpis)
 | 
				
			||||||
 | 
						packetLen += 1 /* ciphertext size in bytes */ + len(C)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err = w.Write(header[:])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err = w.Write([]byte{byte(mpiBitLen >> 8), byte(mpiBitLen)})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err = w.Write(mpis[:])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						w.Write([]byte{byte(len(C))})
 | 
				
			||||||
 | 
						w.Write(C[:])
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -5,14 +5,15 @@
 | 
				
			|||||||
package packet
 | 
					package packet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"crypto/rsa"
 | 
					 | 
				
			||||||
	"encoding/binary"
 | 
						"encoding/binary"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"math/big"
 | 
						"math/big"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/elgamal"
 | 
						"github.com/keybase/go-crypto/openpgp/ecdh"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/errors"
 | 
						"github.com/keybase/go-crypto/openpgp/elgamal"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/rsa"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const encryptedKeyVersion = 3
 | 
					const encryptedKeyVersion = 3
 | 
				
			||||||
@@ -26,6 +27,7 @@ type EncryptedKey struct {
 | 
				
			|||||||
	Key        []byte         // only valid after a successful Decrypt
 | 
						Key        []byte         // only valid after a successful Decrypt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	encryptedMPI1, encryptedMPI2 parsedMPI
 | 
						encryptedMPI1, encryptedMPI2 parsedMPI
 | 
				
			||||||
 | 
						ecdh_C                       []byte
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (e *EncryptedKey) parse(r io.Reader) (err error) {
 | 
					func (e *EncryptedKey) parse(r io.Reader) (err error) {
 | 
				
			||||||
@@ -48,9 +50,25 @@ func (e *EncryptedKey) parse(r io.Reader) (err error) {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r)
 | 
							e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r)
 | 
				
			||||||
 | 
						case PubKeyAlgoECDH:
 | 
				
			||||||
 | 
							e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							_, err = readFull(r, buf[:1]) // read C len (1 byte)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							e.ecdh_C = make([]byte, int(buf[0]))
 | 
				
			||||||
 | 
							_, err = readFull(r, e.ecdh_C)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = consumeAll(r)
 | 
						_, err = consumeAll(r)
 | 
				
			||||||
	return
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func checksumKeyMaterial(key []byte) uint16 {
 | 
					func checksumKeyMaterial(key []byte) uint16 {
 | 
				
			||||||
@@ -77,6 +95,13 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
 | 
				
			|||||||
		c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes)
 | 
							c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes)
 | 
				
			||||||
		c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes)
 | 
							c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes)
 | 
				
			||||||
		b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2)
 | 
							b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2)
 | 
				
			||||||
 | 
						case PubKeyAlgoECDH:
 | 
				
			||||||
 | 
							// Note: Unmarshal checks if point is on the curve.
 | 
				
			||||||
 | 
							c1, c2 := ecdh.Unmarshal(priv.PrivateKey.(*ecdh.PrivateKey).Curve, e.encryptedMPI1.bytes)
 | 
				
			||||||
 | 
							if c1 == nil {
 | 
				
			||||||
 | 
								return errors.InvalidArgumentError("failed to parse EC point for encryption key")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							b, err = decryptKeyECDH(priv, c1, c2, e.ecdh_C)
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
 | 
							err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -147,6 +172,8 @@ func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunctio
 | 
				
			|||||||
		return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
 | 
							return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
 | 
				
			||||||
	case PubKeyAlgoElGamal:
 | 
						case PubKeyAlgoElGamal:
 | 
				
			||||||
		return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
 | 
							return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
 | 
				
			||||||
 | 
						case PubKeyAlgoECDH:
 | 
				
			||||||
 | 
							return serializeEncryptedKeyECDH(w, config.Random(), buf, pub, keyBlock)
 | 
				
			||||||
	case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
 | 
						case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
 | 
				
			||||||
		return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
 | 
							return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -7,10 +7,11 @@ package packet
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"crypto"
 | 
						"crypto"
 | 
				
			||||||
	"encoding/binary"
 | 
						"encoding/binary"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/errors"
 | 
					 | 
				
			||||||
	"golang.org/x/crypto/openpgp/s2k"
 | 
					 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/s2k"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// OnePassSignature represents a one-pass signature packet. See RFC 4880,
 | 
					// OnePassSignature represents a one-pass signature packet. See RFC 4880,
 | 
				
			||||||
@@ -9,7 +9,7 @@ import (
 | 
				
			|||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/errors"
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is
 | 
					// OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is
 | 
				
			||||||
@@ -4,17 +4,19 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Package packet implements parsing and serialization of OpenPGP packets, as
 | 
					// Package packet implements parsing and serialization of OpenPGP packets, as
 | 
				
			||||||
// specified in RFC 4880.
 | 
					// specified in RFC 4880.
 | 
				
			||||||
package packet // import "golang.org/x/crypto/openpgp/packet"
 | 
					package packet // import "github.com/keybase/go-crypto/openpgp/packet"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bufio"
 | 
						"bufio"
 | 
				
			||||||
	"crypto/aes"
 | 
						"crypto/aes"
 | 
				
			||||||
	"crypto/cipher"
 | 
						"crypto/cipher"
 | 
				
			||||||
	"crypto/des"
 | 
						"crypto/des"
 | 
				
			||||||
	"golang.org/x/crypto/cast5"
 | 
						"crypto/elliptic"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/errors"
 | 
					 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"math/big"
 | 
						"math/big"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/cast5"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// readFull is the same as io.ReadFull except that reading zero bytes returns
 | 
					// readFull is the same as io.ReadFull except that reading zero bytes returns
 | 
				
			||||||
@@ -273,6 +275,8 @@ func consumeAll(r io.Reader) (n int64, err error) {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						panic("unreachable")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// packetType represents the numeric ids of the different OpenPGP packet types. See
 | 
					// packetType represents the numeric ids of the different OpenPGP packet types. See
 | 
				
			||||||
@@ -383,17 +387,18 @@ func Read(r io.Reader) (p Packet, err error) {
 | 
				
			|||||||
type SignatureType uint8
 | 
					type SignatureType uint8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	SigTypeBinary            SignatureType = 0
 | 
						SigTypeBinary             SignatureType = 0
 | 
				
			||||||
	SigTypeText                            = 1
 | 
						SigTypeText                             = 1
 | 
				
			||||||
	SigTypeGenericCert                     = 0x10
 | 
						SigTypeGenericCert                      = 0x10
 | 
				
			||||||
	SigTypePersonaCert                     = 0x11
 | 
						SigTypePersonaCert                      = 0x11
 | 
				
			||||||
	SigTypeCasualCert                      = 0x12
 | 
						SigTypeCasualCert                       = 0x12
 | 
				
			||||||
	SigTypePositiveCert                    = 0x13
 | 
						SigTypePositiveCert                     = 0x13
 | 
				
			||||||
	SigTypeSubkeyBinding                   = 0x18
 | 
						SigTypeSubkeyBinding                    = 0x18
 | 
				
			||||||
	SigTypePrimaryKeyBinding               = 0x19
 | 
						SigTypePrimaryKeyBinding                = 0x19
 | 
				
			||||||
	SigTypeDirectSignature                 = 0x1F
 | 
						SigTypeDirectSignature                  = 0x1F
 | 
				
			||||||
	SigTypeKeyRevocation                   = 0x20
 | 
						SigTypeKeyRevocation                    = 0x20
 | 
				
			||||||
	SigTypeSubkeyRevocation                = 0x28
 | 
						SigTypeSubkeyRevocation                 = 0x28
 | 
				
			||||||
 | 
						SigTypeIdentityRevocation               = 0x30
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PublicKeyAlgorithm represents the different public key system specified for
 | 
					// PublicKeyAlgorithm represents the different public key system specified for
 | 
				
			||||||
@@ -410,13 +415,15 @@ const (
 | 
				
			|||||||
	// RFC 6637, Section 5.
 | 
						// RFC 6637, Section 5.
 | 
				
			||||||
	PubKeyAlgoECDH  PublicKeyAlgorithm = 18
 | 
						PubKeyAlgoECDH  PublicKeyAlgorithm = 18
 | 
				
			||||||
	PubKeyAlgoECDSA PublicKeyAlgorithm = 19
 | 
						PubKeyAlgoECDSA PublicKeyAlgorithm = 19
 | 
				
			||||||
 | 
						// RFC -1
 | 
				
			||||||
 | 
						PubKeyAlgoEdDSA PublicKeyAlgorithm = 22
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CanEncrypt returns true if it's possible to encrypt a message to a public
 | 
					// CanEncrypt returns true if it's possible to encrypt a message to a public
 | 
				
			||||||
// key of the given type.
 | 
					// key of the given type.
 | 
				
			||||||
func (pka PublicKeyAlgorithm) CanEncrypt() bool {
 | 
					func (pka PublicKeyAlgorithm) CanEncrypt() bool {
 | 
				
			||||||
	switch pka {
 | 
						switch pka {
 | 
				
			||||||
	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal:
 | 
						case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal, PubKeyAlgoECDH:
 | 
				
			||||||
		return true
 | 
							return true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return false
 | 
						return false
 | 
				
			||||||
@@ -426,7 +433,7 @@ func (pka PublicKeyAlgorithm) CanEncrypt() bool {
 | 
				
			|||||||
// sign a message.
 | 
					// sign a message.
 | 
				
			||||||
func (pka PublicKeyAlgorithm) CanSign() bool {
 | 
					func (pka PublicKeyAlgorithm) CanSign() bool {
 | 
				
			||||||
	switch pka {
 | 
						switch pka {
 | 
				
			||||||
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
 | 
						case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA, PubKeyAlgoEdDSA:
 | 
				
			||||||
		return true
 | 
							return true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return false
 | 
						return false
 | 
				
			||||||
@@ -520,6 +527,25 @@ func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) {
 | 
				
			|||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func WritePaddedBigInt(w io.Writer, length int, X *big.Int) (n int, err error) {
 | 
				
			||||||
 | 
						bytes := X.Bytes()
 | 
				
			||||||
 | 
						n1, err := w.Write(make([]byte, length-len(bytes)))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return n1, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						n2, err := w.Write(bytes)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return n2, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return (n1 + n2), err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Minimum number of bytes to fit the curve coordinates. All
 | 
				
			||||||
 | 
					// coordinates have to be 0-padded to this length.
 | 
				
			||||||
 | 
					func mpiPointByteLength(curve elliptic.Curve) int {
 | 
				
			||||||
 | 
						return (curve.Params().P.BitLen() + 7) / 8
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// writeBig serializes a *big.Int to w.
 | 
					// writeBig serializes a *big.Int to w.
 | 
				
			||||||
func writeBig(w io.Writer, i *big.Int) error {
 | 
					func writeBig(w io.Writer, i *big.Int) error {
 | 
				
			||||||
	return writeMPI(w, uint16(i.BitLen()), i.Bytes())
 | 
						return writeMPI(w, uint16(i.BitLen()), i.Bytes())
 | 
				
			||||||
@@ -6,21 +6,23 @@ package packet
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
	"crypto"
 | 
					 | 
				
			||||||
	"crypto/cipher"
 | 
						"crypto/cipher"
 | 
				
			||||||
	"crypto/dsa"
 | 
						"crypto/dsa"
 | 
				
			||||||
	"crypto/ecdsa"
 | 
						"crypto/ecdsa"
 | 
				
			||||||
	"crypto/rsa"
 | 
					 | 
				
			||||||
	"crypto/sha1"
 | 
						"crypto/sha1"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"math/big"
 | 
						"math/big"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/elgamal"
 | 
						"github.com/keybase/go-crypto/ed25519"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/errors"
 | 
						"github.com/keybase/go-crypto/openpgp/ecdh"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/s2k"
 | 
						"github.com/keybase/go-crypto/openpgp/elgamal"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/s2k"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/rsa"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PrivateKey represents a possibly encrypted private key. See RFC 4880,
 | 
					// PrivateKey represents a possibly encrypted private key. See RFC 4880,
 | 
				
			||||||
@@ -31,9 +33,32 @@ type PrivateKey struct {
 | 
				
			|||||||
	encryptedData []byte
 | 
						encryptedData []byte
 | 
				
			||||||
	cipher        CipherFunction
 | 
						cipher        CipherFunction
 | 
				
			||||||
	s2k           func(out, in []byte)
 | 
						s2k           func(out, in []byte)
 | 
				
			||||||
	PrivateKey    interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or a crypto.Signer.
 | 
						PrivateKey    interface{} // An *rsa.PrivateKey or *dsa.PrivateKey.
 | 
				
			||||||
	sha1Checksum  bool
 | 
						sha1Checksum  bool
 | 
				
			||||||
	iv            []byte
 | 
						iv            []byte
 | 
				
			||||||
 | 
						s2kHeader     []byte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type EdDSAPrivateKey struct {
 | 
				
			||||||
 | 
						PrivateKey
 | 
				
			||||||
 | 
						seed parsedMPI
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *EdDSAPrivateKey) Sign(digest []byte) (R, S []byte, err error) {
 | 
				
			||||||
 | 
						r := bytes.NewReader(e.seed.bytes)
 | 
				
			||||||
 | 
						publicKey, privateKey, err := ed25519.GenerateKey(r)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !bytes.Equal(publicKey, e.PublicKey.edk.p.bytes[1:]) { // [1:] because [0] is 0x40 mpi header
 | 
				
			||||||
 | 
							return nil, nil, errors.UnsupportedError("EdDSA: Private key does not match public key.")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sig := ed25519.Sign(privateKey, digest)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sigLen := ed25519.SignatureSize / 2
 | 
				
			||||||
 | 
						return sig[:sigLen], sig[sigLen:], nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
 | 
					func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
 | 
				
			||||||
@@ -64,23 +89,6 @@ func NewECDSAPrivateKey(currentTime time.Time, priv *ecdsa.PrivateKey) *PrivateK
 | 
				
			|||||||
	return pk
 | 
						return pk
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewSignerPrivateKey creates a sign-only PrivateKey from a crypto.Signer that
 | 
					 | 
				
			||||||
// implements RSA or ECDSA.
 | 
					 | 
				
			||||||
func NewSignerPrivateKey(currentTime time.Time, signer crypto.Signer) *PrivateKey {
 | 
					 | 
				
			||||||
	pk := new(PrivateKey)
 | 
					 | 
				
			||||||
	switch pubkey := signer.Public().(type) {
 | 
					 | 
				
			||||||
	case rsa.PublicKey:
 | 
					 | 
				
			||||||
		pk.PublicKey = *NewRSAPublicKey(currentTime, &pubkey)
 | 
					 | 
				
			||||||
		pk.PubKeyAlgo = PubKeyAlgoRSASignOnly
 | 
					 | 
				
			||||||
	case ecdsa.PublicKey:
 | 
					 | 
				
			||||||
		pk.PublicKey = *NewECDSAPublicKey(currentTime, &pubkey)
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	pk.PrivateKey = signer
 | 
					 | 
				
			||||||
	return pk
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (pk *PrivateKey) parse(r io.Reader) (err error) {
 | 
					func (pk *PrivateKey) parse(r io.Reader) (err error) {
 | 
				
			||||||
	err = (&pk.PublicKey).parse(r)
 | 
						err = (&pk.PublicKey).parse(r)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -112,10 +120,16 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
 | 
				
			|||||||
		if s2kType == 254 {
 | 
							if s2kType == 254 {
 | 
				
			||||||
			pk.sha1Checksum = true
 | 
								pk.sha1Checksum = true
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							// S2K == nil implies that we got a "GNU Dummy" S2K. For instance,
 | 
				
			||||||
 | 
							// because our master secret key is on a USB key in a vault somewhere.
 | 
				
			||||||
 | 
							// In that case, there is no further data to consume here.
 | 
				
			||||||
 | 
							if pk.s2k == nil {
 | 
				
			||||||
 | 
								pk.Encrypted = false
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return errors.UnsupportedError("deprecated s2k function in private key")
 | 
							return errors.UnsupportedError("deprecated s2k function in private key")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if pk.Encrypted {
 | 
						if pk.Encrypted {
 | 
				
			||||||
		blockSize := pk.cipher.blockSize()
 | 
							blockSize := pk.cipher.blockSize()
 | 
				
			||||||
		if blockSize == 0 {
 | 
							if blockSize == 0 {
 | 
				
			||||||
@@ -148,31 +162,105 @@ func mod64kHash(d []byte) uint16 {
 | 
				
			|||||||
	return h
 | 
						return h
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Encrypt is the counterpart to the Decrypt() method below. It encrypts
 | 
				
			||||||
 | 
					// the private key with the provided passphrase. If config is nil, then
 | 
				
			||||||
 | 
					// the standard, and sensible, defaults apply.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// A key will be derived from the given passphrase using S2K Specifier
 | 
				
			||||||
 | 
					// Type 3 (Iterated + Salted, see RFC-4880 Sec. 3.7.1.3). This choice
 | 
				
			||||||
 | 
					// is hardcoded in s2k.Serialize(). S2KCount is hardcoded to 0, which is
 | 
				
			||||||
 | 
					// equivalent to 65536. And the hash algorithm for key-derivation can be
 | 
				
			||||||
 | 
					// set with config. The encrypted PrivateKey, using the algorithm specified
 | 
				
			||||||
 | 
					// in config (if provided), is written out to the encryptedData member.
 | 
				
			||||||
 | 
					// When Serialize() is called, this encryptedData member will be
 | 
				
			||||||
 | 
					// serialized, using S2K Usage value of 254, and thus SHA1 checksum.
 | 
				
			||||||
 | 
					func (pk *PrivateKey) Encrypt(passphrase []byte, config *Config) (err error) {
 | 
				
			||||||
 | 
						if pk.PrivateKey == nil {
 | 
				
			||||||
 | 
							return errors.InvalidArgumentError("there is no private key to encrypt")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pk.sha1Checksum = true
 | 
				
			||||||
 | 
						pk.cipher = config.Cipher()
 | 
				
			||||||
 | 
						s2kConfig := s2k.Config{
 | 
				
			||||||
 | 
							Hash:     config.Hash(),
 | 
				
			||||||
 | 
							S2KCount: 0,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						s2kBuf := bytes.NewBuffer(nil)
 | 
				
			||||||
 | 
						derivedKey := make([]byte, pk.cipher.KeySize())
 | 
				
			||||||
 | 
						err = s2k.Serialize(s2kBuf, derivedKey, config.Random(), passphrase, &s2kConfig)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pk.s2kHeader = s2kBuf.Bytes()
 | 
				
			||||||
 | 
						// No good way to set pk.s2k but to call s2k.Parse(),
 | 
				
			||||||
 | 
						// even though we have all the information here, but
 | 
				
			||||||
 | 
						// most of the functions needed are private to s2k.
 | 
				
			||||||
 | 
						pk.s2k, err = s2k.Parse(s2kBuf)
 | 
				
			||||||
 | 
						pk.iv = make([]byte, pk.cipher.blockSize())
 | 
				
			||||||
 | 
						if _, err = config.Random().Read(pk.iv); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						privateKeyBuf := bytes.NewBuffer(nil)
 | 
				
			||||||
 | 
						if err = pk.serializePrivateKey(privateKeyBuf); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						checksum := sha1.Sum(privateKeyBuf.Bytes())
 | 
				
			||||||
 | 
						if _, err = privateKeyBuf.Write(checksum[:]); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pkData := privateKeyBuf.Bytes()
 | 
				
			||||||
 | 
						block := pk.cipher.new(derivedKey)
 | 
				
			||||||
 | 
						pk.encryptedData = make([]byte, len(pkData))
 | 
				
			||||||
 | 
						cfb := cipher.NewCFBEncrypter(block, pk.iv)
 | 
				
			||||||
 | 
						cfb.XORKeyStream(pk.encryptedData, pkData)
 | 
				
			||||||
 | 
						pk.Encrypted = true
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
 | 
					func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
 | 
				
			||||||
	// TODO(agl): support encrypted private keys
 | 
					 | 
				
			||||||
	buf := bytes.NewBuffer(nil)
 | 
						buf := bytes.NewBuffer(nil)
 | 
				
			||||||
	err = pk.PublicKey.serializeWithoutHeaders(buf)
 | 
						err = pk.PublicKey.serializeWithoutHeaders(buf)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	buf.WriteByte(0 /* no encryption */)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	privateKeyBuf := bytes.NewBuffer(nil)
 | 
						privateKeyBuf := bytes.NewBuffer(nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch priv := pk.PrivateKey.(type) {
 | 
						if pk.PrivateKey == nil {
 | 
				
			||||||
	case *rsa.PrivateKey:
 | 
							_, err = buf.Write([]byte{
 | 
				
			||||||
		err = serializeRSAPrivateKey(privateKeyBuf, priv)
 | 
								254,           // SHA-1 Convention
 | 
				
			||||||
	case *dsa.PrivateKey:
 | 
								9,             // Encryption scheme (AES256)
 | 
				
			||||||
		err = serializeDSAPrivateKey(privateKeyBuf, priv)
 | 
								101,           // GNU Extensions
 | 
				
			||||||
	case *elgamal.PrivateKey:
 | 
								2,             // Hash value (SHA1)
 | 
				
			||||||
		err = serializeElGamalPrivateKey(privateKeyBuf, priv)
 | 
								'G', 'N', 'U', // "GNU" as a string
 | 
				
			||||||
	case *ecdsa.PrivateKey:
 | 
								1, // Extension type 1001 (minus 1000)
 | 
				
			||||||
		err = serializeECDSAPrivateKey(privateKeyBuf, priv)
 | 
							})
 | 
				
			||||||
	default:
 | 
						} else if pk.Encrypted {
 | 
				
			||||||
		err = errors.InvalidArgumentError("unknown private key type")
 | 
							_, err = buf.Write([]byte{
 | 
				
			||||||
	}
 | 
								254,             // SHA-1 Convention
 | 
				
			||||||
	if err != nil {
 | 
								byte(pk.cipher), // Encryption scheme
 | 
				
			||||||
		return
 | 
							})
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if _, err = buf.Write(pk.s2kHeader); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if _, err = buf.Write(pk.iv); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if _, err = privateKeyBuf.Write(pk.encryptedData); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							buf.WriteByte(0 /* no encryption */)
 | 
				
			||||||
 | 
							if err = pk.serializePrivateKey(privateKeyBuf); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ptype := packetTypePrivateKey
 | 
						ptype := packetTypePrivateKey
 | 
				
			||||||
@@ -181,7 +269,11 @@ func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
 | 
				
			|||||||
	if pk.IsSubkey {
 | 
						if pk.IsSubkey {
 | 
				
			||||||
		ptype = packetTypePrivateSubkey
 | 
							ptype = packetTypePrivateSubkey
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2)
 | 
						totalLen := len(contents) + len(privateKeyBytes)
 | 
				
			||||||
 | 
						if !pk.Encrypted {
 | 
				
			||||||
 | 
							totalLen += 2
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = serializeHeader(w, ptype, totalLen)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -194,15 +286,38 @@ func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	checksum := mod64kHash(privateKeyBytes)
 | 
						if len(privateKeyBytes) > 0 && !pk.Encrypted {
 | 
				
			||||||
	var checksumBytes [2]byte
 | 
							checksum := mod64kHash(privateKeyBytes)
 | 
				
			||||||
	checksumBytes[0] = byte(checksum >> 8)
 | 
							var checksumBytes [2]byte
 | 
				
			||||||
	checksumBytes[1] = byte(checksum)
 | 
							checksumBytes[0] = byte(checksum >> 8)
 | 
				
			||||||
	_, err = w.Write(checksumBytes[:])
 | 
							checksumBytes[1] = byte(checksum)
 | 
				
			||||||
 | 
							_, err = w.Write(checksumBytes[:])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (pk *PrivateKey) serializePrivateKey(w io.Writer) (err error) {
 | 
				
			||||||
 | 
						switch priv := pk.PrivateKey.(type) {
 | 
				
			||||||
 | 
						case *rsa.PrivateKey:
 | 
				
			||||||
 | 
							err = serializeRSAPrivateKey(w, priv)
 | 
				
			||||||
 | 
						case *dsa.PrivateKey:
 | 
				
			||||||
 | 
							err = serializeDSAPrivateKey(w, priv)
 | 
				
			||||||
 | 
						case *elgamal.PrivateKey:
 | 
				
			||||||
 | 
							err = serializeElGamalPrivateKey(w, priv)
 | 
				
			||||||
 | 
						case *ecdsa.PrivateKey:
 | 
				
			||||||
 | 
							err = serializeECDSAPrivateKey(w, priv)
 | 
				
			||||||
 | 
						case *ecdh.PrivateKey:
 | 
				
			||||||
 | 
							err = serializeECDHPrivateKey(w, priv)
 | 
				
			||||||
 | 
						case *EdDSAPrivateKey:
 | 
				
			||||||
 | 
							err = serializeEdDSAPrivateKey(w, priv)
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							err = errors.InvalidArgumentError("unknown private key type")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error {
 | 
					func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error {
 | 
				
			||||||
	err := writeBig(w, priv.D)
 | 
						err := writeBig(w, priv.D)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -231,11 +346,23 @@ func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error {
 | 
				
			|||||||
	return writeBig(w, priv.D)
 | 
						return writeBig(w, priv.D)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func serializeECDHPrivateKey(w io.Writer, priv *ecdh.PrivateKey) error {
 | 
				
			||||||
 | 
						return writeBig(w, priv.X)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func serializeEdDSAPrivateKey(w io.Writer, priv *EdDSAPrivateKey) error {
 | 
				
			||||||
 | 
						return writeMPI(w, priv.seed.bitLength, priv.seed.bytes)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Decrypt decrypts an encrypted private key using a passphrase.
 | 
					// Decrypt decrypts an encrypted private key using a passphrase.
 | 
				
			||||||
func (pk *PrivateKey) Decrypt(passphrase []byte) error {
 | 
					func (pk *PrivateKey) Decrypt(passphrase []byte) error {
 | 
				
			||||||
	if !pk.Encrypted {
 | 
						if !pk.Encrypted {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						// For GNU Dummy S2K, there's no key here, so don't do anything.
 | 
				
			||||||
 | 
						if pk.s2k == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	key := make([]byte, pk.cipher.KeySize())
 | 
						key := make([]byte, pk.cipher.KeySize())
 | 
				
			||||||
	pk.s2k(key, passphrase)
 | 
						pk.s2k(key, passphrase)
 | 
				
			||||||
@@ -284,6 +411,10 @@ func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
 | 
				
			|||||||
		return pk.parseElGamalPrivateKey(data)
 | 
							return pk.parseElGamalPrivateKey(data)
 | 
				
			||||||
	case PubKeyAlgoECDSA:
 | 
						case PubKeyAlgoECDSA:
 | 
				
			||||||
		return pk.parseECDSAPrivateKey(data)
 | 
							return pk.parseECDSAPrivateKey(data)
 | 
				
			||||||
 | 
						case PubKeyAlgoECDH:
 | 
				
			||||||
 | 
							return pk.parseECDHPrivateKey(data)
 | 
				
			||||||
 | 
						case PubKeyAlgoEdDSA:
 | 
				
			||||||
 | 
							return pk.parseEdDSAPrivateKey(data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	panic("impossible")
 | 
						panic("impossible")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -360,8 +491,10 @@ func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) {
 | 
					func (pk *PrivateKey) parseECDHPrivateKey(data []byte) (err error) {
 | 
				
			||||||
	ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey)
 | 
						pub := pk.PublicKey.PublicKey.(*ecdh.PublicKey)
 | 
				
			||||||
 | 
						priv := new(ecdh.PrivateKey)
 | 
				
			||||||
 | 
						priv.PublicKey = *pub
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	buf := bytes.NewBuffer(data)
 | 
						buf := bytes.NewBuffer(data)
 | 
				
			||||||
	d, _, err := readMPI(buf)
 | 
						d, _, err := readMPI(buf)
 | 
				
			||||||
@@ -369,10 +502,47 @@ func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pk.PrivateKey = &ecdsa.PrivateKey{
 | 
						priv.X = new(big.Int).SetBytes(d)
 | 
				
			||||||
		PublicKey: *ecdsaPub,
 | 
						pk.PrivateKey = priv
 | 
				
			||||||
		D:         new(big.Int).SetBytes(d),
 | 
						pk.Encrypted = false
 | 
				
			||||||
 | 
						pk.encryptedData = nil
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) {
 | 
				
			||||||
 | 
						ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey)
 | 
				
			||||||
 | 
						ecdsaPriv := new(ecdsa.PrivateKey)
 | 
				
			||||||
 | 
						ecdsaPriv.PublicKey = *ecdsaPub
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buf := bytes.NewBuffer(data)
 | 
				
			||||||
 | 
						d, _, err := readMPI(buf)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ecdsaPriv.D = new(big.Int).SetBytes(d)
 | 
				
			||||||
 | 
						pk.PrivateKey = ecdsaPriv
 | 
				
			||||||
 | 
						pk.Encrypted = false
 | 
				
			||||||
 | 
						pk.encryptedData = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (pk *PrivateKey) parseEdDSAPrivateKey(data []byte) (err error) {
 | 
				
			||||||
 | 
						eddsaPriv := new(EdDSAPrivateKey)
 | 
				
			||||||
 | 
						eddsaPriv.PublicKey = pk.PublicKey
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buf := bytes.NewBuffer(data)
 | 
				
			||||||
 | 
						eddsaPriv.seed.bytes, eddsaPriv.seed.bitLength, err = readMPI(buf)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if bLen := len(eddsaPriv.seed.bytes); bLen != 32 { // 32 bytes private part of ed25519 key.
 | 
				
			||||||
 | 
							return errors.UnsupportedError(fmt.Sprintf("Unexpected EdDSA private key length: %d", bLen))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pk.PrivateKey = eddsaPriv
 | 
				
			||||||
	pk.Encrypted = false
 | 
						pk.Encrypted = false
 | 
				
			||||||
	pk.encryptedData = nil
 | 
						pk.encryptedData = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -10,7 +10,6 @@ import (
 | 
				
			|||||||
	"crypto/dsa"
 | 
						"crypto/dsa"
 | 
				
			||||||
	"crypto/ecdsa"
 | 
						"crypto/ecdsa"
 | 
				
			||||||
	"crypto/elliptic"
 | 
						"crypto/elliptic"
 | 
				
			||||||
	"crypto/rsa"
 | 
					 | 
				
			||||||
	"crypto/sha1"
 | 
						"crypto/sha1"
 | 
				
			||||||
	_ "crypto/sha256"
 | 
						_ "crypto/sha256"
 | 
				
			||||||
	_ "crypto/sha512"
 | 
						_ "crypto/sha512"
 | 
				
			||||||
@@ -22,8 +21,13 @@ import (
 | 
				
			|||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/elgamal"
 | 
						"github.com/keybase/go-crypto/brainpool"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/errors"
 | 
						"github.com/keybase/go-crypto/curve25519"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/ed25519"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/ecdh"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/elgamal"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/rsa"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
@@ -33,9 +37,19 @@ var (
 | 
				
			|||||||
	oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22}
 | 
						oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22}
 | 
				
			||||||
	// NIST curve P-521
 | 
						// NIST curve P-521
 | 
				
			||||||
	oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23}
 | 
						oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23}
 | 
				
			||||||
 | 
						// Brainpool curve P-256r1
 | 
				
			||||||
 | 
						oidCurveP256r1 []byte = []byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07}
 | 
				
			||||||
 | 
						// Brainpool curve P-384r1
 | 
				
			||||||
 | 
						oidCurveP384r1 []byte = []byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B}
 | 
				
			||||||
 | 
						// Brainpool curve P-512r1
 | 
				
			||||||
 | 
						oidCurveP512r1 []byte = []byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D}
 | 
				
			||||||
 | 
						// EdDSA
 | 
				
			||||||
 | 
						oidEdDSA []byte = []byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01}
 | 
				
			||||||
 | 
						// cv25519
 | 
				
			||||||
 | 
						oidCurve25519 []byte = []byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const maxOIDLength = 8
 | 
					const maxOIDLength = 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ecdsaKey stores the algorithm-specific fields for ECDSA keys.
 | 
					// ecdsaKey stores the algorithm-specific fields for ECDSA keys.
 | 
				
			||||||
// as defined in RFC 6637, Section 9.
 | 
					// as defined in RFC 6637, Section 9.
 | 
				
			||||||
@@ -46,6 +60,38 @@ type ecdsaKey struct {
 | 
				
			|||||||
	p parsedMPI
 | 
						p parsedMPI
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type edDSAkey struct {
 | 
				
			||||||
 | 
						ecdsaKey
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func copyFrontFill(dst, src []byte, length int) int {
 | 
				
			||||||
 | 
						if srcLen := len(src); srcLen < length {
 | 
				
			||||||
 | 
							return copy(dst[length-srcLen:], src[:])
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							return copy(dst[:], src[:])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *edDSAkey) Verify(payload []byte, r parsedMPI, s parsedMPI) bool {
 | 
				
			||||||
 | 
						const halfSigSize = ed25519.SignatureSize / 2
 | 
				
			||||||
 | 
						var sig [ed25519.SignatureSize]byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// NOTE: The first byte is 0x40 - MPI header
 | 
				
			||||||
 | 
						// TODO: Maybe clean the code up and use 0x40 as a header when
 | 
				
			||||||
 | 
						// reading and keep only actual number in p field. Find out how
 | 
				
			||||||
 | 
						// other MPIs are stored.
 | 
				
			||||||
 | 
						key := e.p.bytes[1:]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Note: it may happen that R + S do not form 64-byte signature buffer that
 | 
				
			||||||
 | 
						// ed25519 expects, but because we copy it over to an array of exact size,
 | 
				
			||||||
 | 
						// we will always pass correctly sized slice to Verify. Slice too short
 | 
				
			||||||
 | 
						// would make ed25519 panic().
 | 
				
			||||||
 | 
						copyFrontFill(sig[:halfSigSize], r.bytes, halfSigSize)
 | 
				
			||||||
 | 
						copyFrontFill(sig[halfSigSize:], s.bytes, halfSigSize)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ed25519.Verify(key, payload, sig[:])
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// parseOID reads the OID for the curve as defined in RFC 6637, Section 9.
 | 
					// parseOID reads the OID for the curve as defined in RFC 6637, Section 9.
 | 
				
			||||||
func parseOID(r io.Reader) (oid []byte, err error) {
 | 
					func parseOID(r io.Reader) (oid []byte, err error) {
 | 
				
			||||||
	buf := make([]byte, maxOIDLength)
 | 
						buf := make([]byte, maxOIDLength)
 | 
				
			||||||
@@ -67,7 +113,7 @@ func (f *ecdsaKey) parse(r io.Reader) (err error) {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	f.p.bytes, f.p.bitLength, err = readMPI(r)
 | 
						f.p.bytes, f.p.bitLength, err = readMPI(r)
 | 
				
			||||||
	return
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *ecdsaKey) serialize(w io.Writer) (err error) {
 | 
					func (f *ecdsaKey) serialize(w io.Writer) (err error) {
 | 
				
			||||||
@@ -80,17 +126,34 @@ func (f *ecdsaKey) serialize(w io.Writer) (err error) {
 | 
				
			|||||||
	return writeMPIs(w, f.p)
 | 
						return writeMPIs(w, f.p)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getCurveByOid(oid []byte) elliptic.Curve {
 | 
				
			||||||
 | 
						switch {
 | 
				
			||||||
 | 
						case bytes.Equal(oid, oidCurveP256):
 | 
				
			||||||
 | 
							return elliptic.P256()
 | 
				
			||||||
 | 
						case bytes.Equal(oid, oidCurveP384):
 | 
				
			||||||
 | 
							return elliptic.P384()
 | 
				
			||||||
 | 
						case bytes.Equal(oid, oidCurveP521):
 | 
				
			||||||
 | 
							return elliptic.P521()
 | 
				
			||||||
 | 
						case bytes.Equal(oid, oidCurveP256r1):
 | 
				
			||||||
 | 
							return brainpool.P256r1()
 | 
				
			||||||
 | 
						case bytes.Equal(oid, oidCurveP384r1):
 | 
				
			||||||
 | 
							return brainpool.P384r1()
 | 
				
			||||||
 | 
						case bytes.Equal(oid, oidCurveP512r1):
 | 
				
			||||||
 | 
							return brainpool.P512r1()
 | 
				
			||||||
 | 
						case bytes.Equal(oid, oidCurve25519):
 | 
				
			||||||
 | 
							return curve25519.Cv25519()
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) {
 | 
					func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) {
 | 
				
			||||||
	var c elliptic.Curve
 | 
						var c = getCurveByOid(f.oid)
 | 
				
			||||||
	if bytes.Equal(f.oid, oidCurveP256) {
 | 
						// Curve25519 should not be used in ECDSA.
 | 
				
			||||||
		c = elliptic.P256()
 | 
						if c == nil || bytes.Equal(f.oid, oidCurve25519) {
 | 
				
			||||||
	} 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))
 | 
							return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						// Note: Unmarshal already checks if point is on curve.
 | 
				
			||||||
	x, y := elliptic.Unmarshal(c, f.p.bytes)
 | 
						x, y := elliptic.Unmarshal(c, f.p.bytes)
 | 
				
			||||||
	if x == nil {
 | 
						if x == nil {
 | 
				
			||||||
		return nil, errors.UnsupportedError("failed to parse EC point")
 | 
							return nil, errors.UnsupportedError("failed to parse EC point")
 | 
				
			||||||
@@ -98,6 +161,20 @@ func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) {
 | 
				
			|||||||
	return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil
 | 
						return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *ecdsaKey) newECDH() (*ecdh.PublicKey, error) {
 | 
				
			||||||
 | 
						var c = getCurveByOid(f.oid)
 | 
				
			||||||
 | 
						if c == nil {
 | 
				
			||||||
 | 
							return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// ecdh.Unmarshal handles unmarshaling for all curve types. It
 | 
				
			||||||
 | 
						// also checks if point is on curve.
 | 
				
			||||||
 | 
						x, y := ecdh.Unmarshal(c, f.p.bytes)
 | 
				
			||||||
 | 
						if x == nil {
 | 
				
			||||||
 | 
							return nil, errors.UnsupportedError("failed to parse EC point")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &ecdh.PublicKey{Curve: c, X: x, Y: y}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *ecdsaKey) byteLen() int {
 | 
					func (f *ecdsaKey) byteLen() int {
 | 
				
			||||||
	return 1 + len(f.oid) + 2 + len(f.p.bytes)
 | 
						return 1 + len(f.oid) + 2 + len(f.p.bytes)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -163,6 +240,9 @@ type PublicKey struct {
 | 
				
			|||||||
	// RFC 6637 fields
 | 
						// RFC 6637 fields
 | 
				
			||||||
	ec   *ecdsaKey
 | 
						ec   *ecdsaKey
 | 
				
			||||||
	ecdh *ecdhKdf
 | 
						ecdh *ecdhKdf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// EdDSA fields (no RFC available), uses ecdsa scaffolding
 | 
				
			||||||
 | 
						edk *edDSAkey
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// signingKey provides a convenient abstraction over signature verification
 | 
					// signingKey provides a convenient abstraction over signature verification
 | 
				
			||||||
@@ -172,21 +252,28 @@ type signingKey interface {
 | 
				
			|||||||
	serializeWithoutHeaders(io.Writer) error
 | 
						serializeWithoutHeaders(io.Writer) error
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func fromBig(n *big.Int) parsedMPI {
 | 
					func FromBig(n *big.Int) parsedMPI {
 | 
				
			||||||
	return parsedMPI{
 | 
						return parsedMPI{
 | 
				
			||||||
		bytes:     n.Bytes(),
 | 
							bytes:     n.Bytes(),
 | 
				
			||||||
		bitLength: uint16(n.BitLen()),
 | 
							bitLength: uint16(n.BitLen()),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func FromBytes(bytes []byte) parsedMPI {
 | 
				
			||||||
 | 
						return parsedMPI{
 | 
				
			||||||
 | 
							bytes:     bytes,
 | 
				
			||||||
 | 
							bitLength: uint16(8 * len(bytes)),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
 | 
					// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
 | 
				
			||||||
func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey {
 | 
					func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey {
 | 
				
			||||||
	pk := &PublicKey{
 | 
						pk := &PublicKey{
 | 
				
			||||||
		CreationTime: creationTime,
 | 
							CreationTime: creationTime,
 | 
				
			||||||
		PubKeyAlgo:   PubKeyAlgoRSA,
 | 
							PubKeyAlgo:   PubKeyAlgoRSA,
 | 
				
			||||||
		PublicKey:    pub,
 | 
							PublicKey:    pub,
 | 
				
			||||||
		n:            fromBig(pub.N),
 | 
							n:            FromBig(pub.N),
 | 
				
			||||||
		e:            fromBig(big.NewInt(int64(pub.E))),
 | 
							e:            FromBig(big.NewInt(int64(pub.E))),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pk.setFingerPrintAndKeyId()
 | 
						pk.setFingerPrintAndKeyId()
 | 
				
			||||||
@@ -199,25 +286,38 @@ func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey {
 | 
				
			|||||||
		CreationTime: creationTime,
 | 
							CreationTime: creationTime,
 | 
				
			||||||
		PubKeyAlgo:   PubKeyAlgoDSA,
 | 
							PubKeyAlgo:   PubKeyAlgoDSA,
 | 
				
			||||||
		PublicKey:    pub,
 | 
							PublicKey:    pub,
 | 
				
			||||||
		p:            fromBig(pub.P),
 | 
							p:            FromBig(pub.P),
 | 
				
			||||||
		q:            fromBig(pub.Q),
 | 
							q:            FromBig(pub.Q),
 | 
				
			||||||
		g:            fromBig(pub.G),
 | 
							g:            FromBig(pub.G),
 | 
				
			||||||
		y:            fromBig(pub.Y),
 | 
							y:            FromBig(pub.Y),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pk.setFingerPrintAndKeyId()
 | 
						pk.setFingerPrintAndKeyId()
 | 
				
			||||||
	return pk
 | 
						return pk
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// check EdDSA public key material.
 | 
				
			||||||
 | 
					// There is currently no RFC for it, but it doesn't mean it's not
 | 
				
			||||||
 | 
					// implemented or in use.
 | 
				
			||||||
 | 
					func (e *edDSAkey) check() error {
 | 
				
			||||||
 | 
						if !bytes.Equal(e.oid, oidEdDSA) {
 | 
				
			||||||
 | 
							return errors.UnsupportedError(fmt.Sprintf("Bad OID for EdDSA key: %v", e.oid))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if bLen := len(e.p.bytes); bLen != 33 { // 32 bytes for ed25519 key and 1 byte for 0x40 header
 | 
				
			||||||
 | 
							return errors.UnsupportedError(fmt.Sprintf("Unexpected EdDSA public key length: %d", bLen))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey.
 | 
					// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey.
 | 
				
			||||||
func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey {
 | 
					func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey {
 | 
				
			||||||
	pk := &PublicKey{
 | 
						pk := &PublicKey{
 | 
				
			||||||
		CreationTime: creationTime,
 | 
							CreationTime: creationTime,
 | 
				
			||||||
		PubKeyAlgo:   PubKeyAlgoElGamal,
 | 
							PubKeyAlgo:   PubKeyAlgoElGamal,
 | 
				
			||||||
		PublicKey:    pub,
 | 
							PublicKey:    pub,
 | 
				
			||||||
		p:            fromBig(pub.P),
 | 
							p:            FromBig(pub.P),
 | 
				
			||||||
		g:            fromBig(pub.G),
 | 
							g:            FromBig(pub.G),
 | 
				
			||||||
		y:            fromBig(pub.Y),
 | 
							y:            FromBig(pub.Y),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pk.setFingerPrintAndKeyId()
 | 
						pk.setFingerPrintAndKeyId()
 | 
				
			||||||
@@ -231,7 +331,6 @@ func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey
 | 
				
			|||||||
		PublicKey:    pub,
 | 
							PublicKey:    pub,
 | 
				
			||||||
		ec:           new(ecdsaKey),
 | 
							ec:           new(ecdsaKey),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch pub.Curve {
 | 
						switch pub.Curve {
 | 
				
			||||||
	case elliptic.P256():
 | 
						case elliptic.P256():
 | 
				
			||||||
		pk.ec.oid = oidCurveP256
 | 
							pk.ec.oid = oidCurveP256
 | 
				
			||||||
@@ -239,10 +338,13 @@ func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey
 | 
				
			|||||||
		pk.ec.oid = oidCurveP384
 | 
							pk.ec.oid = oidCurveP384
 | 
				
			||||||
	case elliptic.P521():
 | 
						case elliptic.P521():
 | 
				
			||||||
		pk.ec.oid = oidCurveP521
 | 
							pk.ec.oid = oidCurveP521
 | 
				
			||||||
	default:
 | 
						case brainpool.P256r1():
 | 
				
			||||||
		panic("unknown elliptic curve")
 | 
							pk.ec.oid = oidCurveP256r1
 | 
				
			||||||
 | 
						case brainpool.P384r1():
 | 
				
			||||||
 | 
							pk.ec.oid = oidCurveP384r1
 | 
				
			||||||
 | 
						case brainpool.P512r1():
 | 
				
			||||||
 | 
							pk.ec.oid = oidCurveP512r1
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
 | 
						pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
 | 
				
			||||||
	pk.ec.p.bitLength = uint16(8 * len(pk.ec.p.bytes))
 | 
						pk.ec.p.bitLength = uint16(8 * len(pk.ec.p.bytes))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -269,6 +371,12 @@ func (pk *PublicKey) parse(r io.Reader) (err error) {
 | 
				
			|||||||
		err = pk.parseDSA(r)
 | 
							err = pk.parseDSA(r)
 | 
				
			||||||
	case PubKeyAlgoElGamal:
 | 
						case PubKeyAlgoElGamal:
 | 
				
			||||||
		err = pk.parseElGamal(r)
 | 
							err = pk.parseElGamal(r)
 | 
				
			||||||
 | 
						case PubKeyAlgoEdDSA:
 | 
				
			||||||
 | 
							pk.edk = new(edDSAkey)
 | 
				
			||||||
 | 
							if err = pk.edk.parse(r); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							err = pk.edk.check()
 | 
				
			||||||
	case PubKeyAlgoECDSA:
 | 
						case PubKeyAlgoECDSA:
 | 
				
			||||||
		pk.ec = new(ecdsaKey)
 | 
							pk.ec = new(ecdsaKey)
 | 
				
			||||||
		if err = pk.ec.parse(r); err != nil {
 | 
							if err = pk.ec.parse(r); err != nil {
 | 
				
			||||||
@@ -284,8 +392,7 @@ func (pk *PublicKey) parse(r io.Reader) (err error) {
 | 
				
			|||||||
		if err = pk.ecdh.parse(r); err != nil {
 | 
							if err = pk.ecdh.parse(r); err != nil {
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// The ECDH key is stored in an ecdsa.PublicKey for convenience.
 | 
							pk.PublicKey, err = pk.ec.newECDH()
 | 
				
			||||||
		pk.PublicKey, err = pk.ec.newECDSA()
 | 
					 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
 | 
							err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -318,7 +425,7 @@ func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(pk.e.bytes) > 3 {
 | 
						if len(pk.e.bytes) > 7 {
 | 
				
			||||||
		err = errors.UnsupportedError("large public exponent")
 | 
							err = errors.UnsupportedError("large public exponent")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -328,7 +435,7 @@ func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	for i := 0; i < len(pk.e.bytes); i++ {
 | 
						for i := 0; i < len(pk.e.bytes); i++ {
 | 
				
			||||||
		rsa.E <<= 8
 | 
							rsa.E <<= 8
 | 
				
			||||||
		rsa.E |= int(pk.e.bytes[i])
 | 
							rsa.E |= int64(pk.e.bytes[i])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	pk.PublicKey = rsa
 | 
						pk.PublicKey = rsa
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
@@ -410,6 +517,8 @@ func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) {
 | 
				
			|||||||
	case PubKeyAlgoECDH:
 | 
						case PubKeyAlgoECDH:
 | 
				
			||||||
		pLength += uint16(pk.ec.byteLen())
 | 
							pLength += uint16(pk.ec.byteLen())
 | 
				
			||||||
		pLength += uint16(pk.ecdh.byteLen())
 | 
							pLength += uint16(pk.ecdh.byteLen())
 | 
				
			||||||
 | 
						case PubKeyAlgoEdDSA:
 | 
				
			||||||
 | 
							pLength += uint16(pk.edk.byteLen())
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		panic("unknown public key algorithm")
 | 
							panic("unknown public key algorithm")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -439,6 +548,8 @@ func (pk *PublicKey) Serialize(w io.Writer) (err error) {
 | 
				
			|||||||
	case PubKeyAlgoECDH:
 | 
						case PubKeyAlgoECDH:
 | 
				
			||||||
		length += pk.ec.byteLen()
 | 
							length += pk.ec.byteLen()
 | 
				
			||||||
		length += pk.ecdh.byteLen()
 | 
							length += pk.ecdh.byteLen()
 | 
				
			||||||
 | 
						case PubKeyAlgoEdDSA:
 | 
				
			||||||
 | 
							length += pk.edk.byteLen()
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		panic("unknown public key algorithm")
 | 
							panic("unknown public key algorithm")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -480,6 +591,8 @@ func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
 | 
				
			|||||||
		return writeMPIs(w, pk.p, pk.g, pk.y)
 | 
							return writeMPIs(w, pk.p, pk.g, pk.y)
 | 
				
			||||||
	case PubKeyAlgoECDSA:
 | 
						case PubKeyAlgoECDSA:
 | 
				
			||||||
		return pk.ec.serialize(w)
 | 
							return pk.ec.serialize(w)
 | 
				
			||||||
 | 
						case PubKeyAlgoEdDSA:
 | 
				
			||||||
 | 
							return pk.edk.serialize(w)
 | 
				
			||||||
	case PubKeyAlgoECDH:
 | 
						case PubKeyAlgoECDH:
 | 
				
			||||||
		if err = pk.ec.serialize(w); err != nil {
 | 
							if err = pk.ec.serialize(w); err != nil {
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
@@ -504,9 +617,18 @@ func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err erro
 | 
				
			|||||||
	signed.Write(sig.HashSuffix)
 | 
						signed.Write(sig.HashSuffix)
 | 
				
			||||||
	hashBytes := signed.Sum(nil)
 | 
						hashBytes := signed.Sum(nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
 | 
						// NOTE(maxtaco) 2016-08-22
 | 
				
			||||||
		return errors.SignatureError("hash tag doesn't match")
 | 
						//
 | 
				
			||||||
	}
 | 
						// We used to do this:
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
 | 
				
			||||||
 | 
						//	  return errors.SignatureError("hash tag doesn't match")
 | 
				
			||||||
 | 
						// }
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// But don't do anything in this case. Some GPGs generate bad
 | 
				
			||||||
 | 
						// 2-byte hash prefixes, but GPG also doesn't seem to care on
 | 
				
			||||||
 | 
						// import. See BrentMaxwell's key. I think it's safe to disable
 | 
				
			||||||
 | 
						// this check!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if pk.PubKeyAlgo != sig.PubKeyAlgo {
 | 
						if pk.PubKeyAlgo != sig.PubKeyAlgo {
 | 
				
			||||||
		return errors.InvalidArgumentError("public key and signature use different algorithms")
 | 
							return errors.InvalidArgumentError("public key and signature use different algorithms")
 | 
				
			||||||
@@ -537,9 +659,15 @@ func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err erro
 | 
				
			|||||||
			return errors.SignatureError("ECDSA verification failure")
 | 
								return errors.SignatureError("ECDSA verification failure")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
 | 
						case PubKeyAlgoEdDSA:
 | 
				
			||||||
 | 
							if !pk.edk.Verify(hashBytes, sig.EdDSASigR, sig.EdDSASigS) {
 | 
				
			||||||
 | 
								return errors.SignatureError("EdDSA verification failure")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return errors.SignatureError("Unsupported public key algorithm used in signature")
 | 
							return errors.SignatureError("Unsupported public key algorithm used in signature")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						panic("unreachable")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// VerifySignatureV3 returns nil iff sig is a valid signature, made by this
 | 
					// VerifySignatureV3 returns nil iff sig is a valid signature, made by this
 | 
				
			||||||
@@ -584,6 +712,7 @@ func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err
 | 
				
			|||||||
	default:
 | 
						default:
 | 
				
			||||||
		panic("shouldn't happen")
 | 
							panic("shouldn't happen")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						panic("unreachable")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// keySignatureHash returns a Hash of the message that needs to be signed for
 | 
					// keySignatureHash returns a Hash of the message that needs to be signed for
 | 
				
			||||||
@@ -594,12 +723,18 @@ func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	h = hashFunc.New()
 | 
						h = hashFunc.New()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						updateKeySignatureHash(pk, signed, h)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// updateKeySignatureHash does the actual hash updates for keySignatureHash.
 | 
				
			||||||
 | 
					func updateKeySignatureHash(pk, signed signingKey, h hash.Hash) {
 | 
				
			||||||
	// RFC 4880, section 5.2.4
 | 
						// RFC 4880, section 5.2.4
 | 
				
			||||||
	pk.SerializeSignaturePrefix(h)
 | 
						pk.SerializeSignaturePrefix(h)
 | 
				
			||||||
	pk.serializeWithoutHeaders(h)
 | 
						pk.serializeWithoutHeaders(h)
 | 
				
			||||||
	signed.SerializeSignaturePrefix(h)
 | 
						signed.SerializeSignaturePrefix(h)
 | 
				
			||||||
	signed.serializeWithoutHeaders(h)
 | 
						signed.serializeWithoutHeaders(h)
 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// VerifyKeySignature returns nil iff sig is a valid signature, made by this
 | 
					// VerifyKeySignature returns nil iff sig is a valid signature, made by this
 | 
				
			||||||
@@ -614,6 +749,19 @@ func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if sig.FlagSign {
 | 
						if sig.FlagSign {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// BUG(maxtaco)
 | 
				
			||||||
 | 
							//
 | 
				
			||||||
 | 
							// We should check for more than FlagsSign here, because if
 | 
				
			||||||
 | 
							// you read keys.go, we can sometimes use signing subkeys even if they're
 | 
				
			||||||
 | 
							// not explicitly flagged as such. However, so doing fails lots of currently
 | 
				
			||||||
 | 
							// working tests, so I'm not going to do much here.
 | 
				
			||||||
 | 
							//
 | 
				
			||||||
 | 
							// In other words, we should have this disjunction in the condition above:
 | 
				
			||||||
 | 
							//
 | 
				
			||||||
 | 
							//    || (!sig.FlagsValid && pk.PubKeyAlgo.CanSign()) {
 | 
				
			||||||
 | 
							//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Signing subkeys must be cross-signed. See
 | 
							// Signing subkeys must be cross-signed. See
 | 
				
			||||||
		// https://www.gnupg.org/faq/subkey-cross-certify.html.
 | 
							// https://www.gnupg.org/faq/subkey-cross-certify.html.
 | 
				
			||||||
		if sig.EmbeddedSignature == nil {
 | 
							if sig.EmbeddedSignature == nil {
 | 
				
			||||||
@@ -648,14 +796,27 @@ func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err er
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this
 | 
					// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this
 | 
				
			||||||
// public key.
 | 
					// public key.
 | 
				
			||||||
func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) {
 | 
					func (pk *PublicKey) VerifyRevocationSignature(revokedKey *PublicKey, sig *Signature) (err error) {
 | 
				
			||||||
	h, err := keyRevocationHash(pk, sig.Hash)
 | 
						h, err := keyRevocationHash(revokedKey, sig.Hash)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return pk.VerifySignature(h, sig)
 | 
						return pk.VerifySignature(h, sig)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type teeHash struct {
 | 
				
			||||||
 | 
						h hash.Hash
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (t teeHash) Write(b []byte) (n int, err error) {
 | 
				
			||||||
 | 
						fmt.Printf("hash -> %s %+v\n", string(b), b)
 | 
				
			||||||
 | 
						return t.h.Write(b)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (t teeHash) Sum(b []byte) []byte { return t.h.Sum(b) }
 | 
				
			||||||
 | 
					func (t teeHash) Reset()              { t.h.Reset() }
 | 
				
			||||||
 | 
					func (t teeHash) Size() int           { return t.h.Size() }
 | 
				
			||||||
 | 
					func (t teeHash) BlockSize() int      { return t.h.BlockSize() }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// userIdSignatureHash returns a Hash of the message that needs to be signed
 | 
					// userIdSignatureHash returns a Hash of the message that needs to be signed
 | 
				
			||||||
// to assert that pk is a valid key for id.
 | 
					// to assert that pk is a valid key for id.
 | 
				
			||||||
func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
 | 
					func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
 | 
				
			||||||
@@ -664,6 +825,14 @@ func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	h = hashFunc.New()
 | 
						h = hashFunc.New()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						updateUserIdSignatureHash(id, pk, h)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// updateUserIdSignatureHash does the actual hash updates for
 | 
				
			||||||
 | 
					// userIdSignatureHash.
 | 
				
			||||||
 | 
					func updateUserIdSignatureHash(id string, pk *PublicKey, h hash.Hash) {
 | 
				
			||||||
	// RFC 4880, section 5.2.4
 | 
						// RFC 4880, section 5.2.4
 | 
				
			||||||
	pk.SerializeSignaturePrefix(h)
 | 
						pk.SerializeSignaturePrefix(h)
 | 
				
			||||||
	pk.serializeWithoutHeaders(h)
 | 
						pk.serializeWithoutHeaders(h)
 | 
				
			||||||
@@ -732,7 +901,9 @@ func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) {
 | 
				
			|||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BitLength returns the bit length for the given public key.
 | 
					// BitLength returns the bit length for the given public key. Used for
 | 
				
			||||||
 | 
					// displaying key information, actual buffers and BigInts inside may
 | 
				
			||||||
 | 
					// have non-matching different size if the key is invalid.
 | 
				
			||||||
func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
 | 
					func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
 | 
				
			||||||
	switch pk.PubKeyAlgo {
 | 
						switch pk.PubKeyAlgo {
 | 
				
			||||||
	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
 | 
						case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
 | 
				
			||||||
@@ -741,6 +912,17 @@ func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
 | 
				
			|||||||
		bitLength = pk.p.bitLength
 | 
							bitLength = pk.p.bitLength
 | 
				
			||||||
	case PubKeyAlgoElGamal:
 | 
						case PubKeyAlgoElGamal:
 | 
				
			||||||
		bitLength = pk.p.bitLength
 | 
							bitLength = pk.p.bitLength
 | 
				
			||||||
 | 
						case PubKeyAlgoECDH:
 | 
				
			||||||
 | 
							ecdhPublicKey := pk.PublicKey.(*ecdh.PublicKey)
 | 
				
			||||||
 | 
							bitLength = uint16(ecdhPublicKey.Curve.Params().BitSize)
 | 
				
			||||||
 | 
						case PubKeyAlgoECDSA:
 | 
				
			||||||
 | 
							ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey)
 | 
				
			||||||
 | 
							bitLength = uint16(ecdsaPublicKey.Curve.Params().BitSize)
 | 
				
			||||||
 | 
						case PubKeyAlgoEdDSA:
 | 
				
			||||||
 | 
							// EdDSA only support ed25519 curves right now, just return
 | 
				
			||||||
 | 
							// the length. Also, we don't have any PublicKey.Curve object
 | 
				
			||||||
 | 
							// to look the size up from.
 | 
				
			||||||
 | 
							bitLength = 256
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		err = errors.InvalidArgumentError("bad public-key algorithm")
 | 
							err = errors.InvalidArgumentError("bad public-key algorithm")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -7,7 +7,6 @@ package packet
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"crypto"
 | 
						"crypto"
 | 
				
			||||||
	"crypto/md5"
 | 
						"crypto/md5"
 | 
				
			||||||
	"crypto/rsa"
 | 
					 | 
				
			||||||
	"encoding/binary"
 | 
						"encoding/binary"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"hash"
 | 
						"hash"
 | 
				
			||||||
@@ -16,7 +15,8 @@ import (
 | 
				
			|||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/errors"
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/rsa"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PublicKeyV3 represents older, version 3 public keys. These keys are less secure and
 | 
					// PublicKeyV3 represents older, version 3 public keys. These keys are less secure and
 | 
				
			||||||
@@ -42,8 +42,8 @@ func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3
 | 
				
			|||||||
	pk := &PublicKeyV3{
 | 
						pk := &PublicKeyV3{
 | 
				
			||||||
		CreationTime: creationTime,
 | 
							CreationTime: creationTime,
 | 
				
			||||||
		PublicKey:    pub,
 | 
							PublicKey:    pub,
 | 
				
			||||||
		n:            fromBig(pub.N),
 | 
							n:            FromBig(pub.N),
 | 
				
			||||||
		e:            fromBig(big.NewInt(int64(pub.E))),
 | 
							e:            FromBig(big.NewInt(int64(pub.E))),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pk.setFingerPrintAndKeyId()
 | 
						pk.setFingerPrintAndKeyId()
 | 
				
			||||||
@@ -100,14 +100,14 @@ func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) {
 | 
				
			|||||||
	if len(pk.n.bytes) < 8 {
 | 
						if len(pk.n.bytes) < 8 {
 | 
				
			||||||
		return errors.StructuralError("v3 public key modulus is too short")
 | 
							return errors.StructuralError("v3 public key modulus is too short")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if len(pk.e.bytes) > 3 {
 | 
						if len(pk.e.bytes) > 7 {
 | 
				
			||||||
		err = errors.UnsupportedError("large public exponent")
 | 
							err = errors.UnsupportedError("large public exponent")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)}
 | 
						rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)}
 | 
				
			||||||
	for i := 0; i < len(pk.e.bytes); i++ {
 | 
						for i := 0; i < len(pk.e.bytes); i++ {
 | 
				
			||||||
		rsa.E <<= 8
 | 
							rsa.E <<= 8
 | 
				
			||||||
		rsa.E |= int(pk.e.bytes[i])
 | 
							rsa.E |= int64(pk.e.bytes[i])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	pk.PublicKey = rsa
 | 
						pk.PublicKey = rsa
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
@@ -216,6 +216,7 @@ func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (er
 | 
				
			|||||||
		// V3 public keys only support RSA.
 | 
							// V3 public keys only support RSA.
 | 
				
			||||||
		panic("shouldn't happen")
 | 
							panic("shouldn't happen")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						panic("unreachable")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this
 | 
					// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this
 | 
				
			||||||
@@ -5,8 +5,9 @@
 | 
				
			|||||||
package packet
 | 
					package packet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/errors"
 | 
					 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Reader reads packets from an io.Reader and allows packets to be 'unread' so
 | 
					// Reader reads packets from an io.Reader and allows packets to be 'unread' so
 | 
				
			||||||
@@ -46,7 +47,6 @@ func (r *Reader) Next() (p Packet, err error) {
 | 
				
			|||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil, io.EOF
 | 
						return nil, io.EOF
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -9,16 +9,15 @@ import (
 | 
				
			|||||||
	"crypto"
 | 
						"crypto"
 | 
				
			||||||
	"crypto/dsa"
 | 
						"crypto/dsa"
 | 
				
			||||||
	"crypto/ecdsa"
 | 
						"crypto/ecdsa"
 | 
				
			||||||
	"encoding/asn1"
 | 
					 | 
				
			||||||
	"encoding/binary"
 | 
						"encoding/binary"
 | 
				
			||||||
	"hash"
 | 
						"hash"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"math/big"
 | 
					 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/errors"
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/s2k"
 | 
						"github.com/keybase/go-crypto/openpgp/s2k"
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/rsa"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
@@ -29,6 +28,29 @@ const (
 | 
				
			|||||||
	KeyFlagEncryptStorage
 | 
						KeyFlagEncryptStorage
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Signer can be implemented by application code to do actual signing.
 | 
				
			||||||
 | 
					type Signer interface {
 | 
				
			||||||
 | 
						hash.Hash
 | 
				
			||||||
 | 
						Sign(sig *Signature) error
 | 
				
			||||||
 | 
						KeyId() uint64
 | 
				
			||||||
 | 
						PublicKeyAlgo() PublicKeyAlgorithm
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RevocationKey represents designated revoker packet. See RFC 4880
 | 
				
			||||||
 | 
					// section 5.2.3.15 for details.
 | 
				
			||||||
 | 
					type RevocationKey struct {
 | 
				
			||||||
 | 
						Class         byte
 | 
				
			||||||
 | 
						PublicKeyAlgo PublicKeyAlgorithm
 | 
				
			||||||
 | 
						Fingerprint   []byte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// KeyFlagBits holds boolean whether any usage flags were provided in
 | 
				
			||||||
 | 
					// the signature and BitField with KeyFlag* flags.
 | 
				
			||||||
 | 
					type KeyFlagBits struct {
 | 
				
			||||||
 | 
						Valid    bool
 | 
				
			||||||
 | 
						BitField byte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Signature represents a signature. See RFC 4880, section 5.2.
 | 
					// Signature represents a signature. See RFC 4880, section 5.2.
 | 
				
			||||||
type Signature struct {
 | 
					type Signature struct {
 | 
				
			||||||
	SigType    SignatureType
 | 
						SigType    SignatureType
 | 
				
			||||||
@@ -45,6 +67,7 @@ type Signature struct {
 | 
				
			|||||||
	RSASignature         parsedMPI
 | 
						RSASignature         parsedMPI
 | 
				
			||||||
	DSASigR, DSASigS     parsedMPI
 | 
						DSASigR, DSASigS     parsedMPI
 | 
				
			||||||
	ECDSASigR, ECDSASigS parsedMPI
 | 
						ECDSASigR, ECDSASigS parsedMPI
 | 
				
			||||||
 | 
						EdDSASigR, EdDSASigS parsedMPI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// rawSubpackets contains the unparsed subpackets, in order.
 | 
						// rawSubpackets contains the unparsed subpackets, in order.
 | 
				
			||||||
	rawSubpackets []outputSubpacket
 | 
						rawSubpackets []outputSubpacket
 | 
				
			||||||
@@ -54,8 +77,10 @@ type Signature struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	SigLifetimeSecs, KeyLifetimeSecs                        *uint32
 | 
						SigLifetimeSecs, KeyLifetimeSecs                        *uint32
 | 
				
			||||||
	PreferredSymmetric, PreferredHash, PreferredCompression []uint8
 | 
						PreferredSymmetric, PreferredHash, PreferredCompression []uint8
 | 
				
			||||||
 | 
						PreferredKeyServer                                      string
 | 
				
			||||||
	IssuerKeyId                                             *uint64
 | 
						IssuerKeyId                                             *uint64
 | 
				
			||||||
	IsPrimaryId                                             *bool
 | 
						IsPrimaryId                                             *bool
 | 
				
			||||||
 | 
						IssuerFingerprint                                       []byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// FlagsValid is set if any flags were given. See RFC 4880, section
 | 
						// FlagsValid is set if any flags were given. See RFC 4880, section
 | 
				
			||||||
	// 5.2.3.21 for details.
 | 
						// 5.2.3.21 for details.
 | 
				
			||||||
@@ -67,6 +92,12 @@ type Signature struct {
 | 
				
			|||||||
	RevocationReason     *uint8
 | 
						RevocationReason     *uint8
 | 
				
			||||||
	RevocationReasonText string
 | 
						RevocationReasonText string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// PolicyURI is optional. See RFC 4880, Section 5.2.3.20 for details
 | 
				
			||||||
 | 
						PolicyURI string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Regex is a regex that can match a PGP UID. See RFC 4880, 5.2.3.14 for details
 | 
				
			||||||
 | 
						Regex string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// MDC is set if this signature has a feature packet that indicates
 | 
						// MDC is set if this signature has a feature packet that indicates
 | 
				
			||||||
	// support for MDC subpackets.
 | 
						// support for MDC subpackets.
 | 
				
			||||||
	MDC bool
 | 
						MDC bool
 | 
				
			||||||
@@ -76,6 +107,16 @@ type Signature struct {
 | 
				
			|||||||
	// subkey as their own.
 | 
						// subkey as their own.
 | 
				
			||||||
	EmbeddedSignature *Signature
 | 
						EmbeddedSignature *Signature
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// StubbedOutCriticalError is not fail-stop, since it shouldn't break key parsing
 | 
				
			||||||
 | 
						// when appearing in WoT-style cross signatures. But it should prevent a signature
 | 
				
			||||||
 | 
						// from being applied to a primary or subkey.
 | 
				
			||||||
 | 
						StubbedOutCriticalError error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DesignaterRevoker will be present if this signature certifies a
 | 
				
			||||||
 | 
						// designated revoking key id (3rd party key that can sign
 | 
				
			||||||
 | 
						// revocation for this key).
 | 
				
			||||||
 | 
						DesignatedRevoker *RevocationKey
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	outSubpackets []outputSubpacket
 | 
						outSubpackets []outputSubpacket
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -98,7 +139,7 @@ func (sig *Signature) parse(r io.Reader) (err error) {
 | 
				
			|||||||
	sig.SigType = SignatureType(buf[0])
 | 
						sig.SigType = SignatureType(buf[0])
 | 
				
			||||||
	sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1])
 | 
						sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1])
 | 
				
			||||||
	switch sig.PubKeyAlgo {
 | 
						switch sig.PubKeyAlgo {
 | 
				
			||||||
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
 | 
						case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA, PubKeyAlgoEdDSA:
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
 | 
							err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@@ -162,6 +203,11 @@ func (sig *Signature) parse(r io.Reader) (err error) {
 | 
				
			|||||||
		if err == nil {
 | 
							if err == nil {
 | 
				
			||||||
			sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
 | 
								sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						case PubKeyAlgoEdDSA:
 | 
				
			||||||
 | 
							sig.EdDSASigR.bytes, sig.EdDSASigR.bitLength, err = readMPI(r)
 | 
				
			||||||
 | 
							if err == nil {
 | 
				
			||||||
 | 
								sig.EdDSASigS.bytes, sig.EdDSASigS.bitLength, err = readMPI(r)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	case PubKeyAlgoECDSA:
 | 
						case PubKeyAlgoECDSA:
 | 
				
			||||||
		sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r)
 | 
							sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r)
 | 
				
			||||||
		if err == nil {
 | 
							if err == nil {
 | 
				
			||||||
@@ -195,16 +241,21 @@ type signatureSubpacketType uint8
 | 
				
			|||||||
const (
 | 
					const (
 | 
				
			||||||
	creationTimeSubpacket        signatureSubpacketType = 2
 | 
						creationTimeSubpacket        signatureSubpacketType = 2
 | 
				
			||||||
	signatureExpirationSubpacket signatureSubpacketType = 3
 | 
						signatureExpirationSubpacket signatureSubpacketType = 3
 | 
				
			||||||
 | 
						regularExpressionSubpacket   signatureSubpacketType = 6
 | 
				
			||||||
	keyExpirationSubpacket       signatureSubpacketType = 9
 | 
						keyExpirationSubpacket       signatureSubpacketType = 9
 | 
				
			||||||
	prefSymmetricAlgosSubpacket  signatureSubpacketType = 11
 | 
						prefSymmetricAlgosSubpacket  signatureSubpacketType = 11
 | 
				
			||||||
 | 
						revocationKey                signatureSubpacketType = 12
 | 
				
			||||||
	issuerSubpacket              signatureSubpacketType = 16
 | 
						issuerSubpacket              signatureSubpacketType = 16
 | 
				
			||||||
	prefHashAlgosSubpacket       signatureSubpacketType = 21
 | 
						prefHashAlgosSubpacket       signatureSubpacketType = 21
 | 
				
			||||||
	prefCompressionSubpacket     signatureSubpacketType = 22
 | 
						prefCompressionSubpacket     signatureSubpacketType = 22
 | 
				
			||||||
 | 
						prefKeyServerSubpacket       signatureSubpacketType = 24
 | 
				
			||||||
	primaryUserIdSubpacket       signatureSubpacketType = 25
 | 
						primaryUserIdSubpacket       signatureSubpacketType = 25
 | 
				
			||||||
 | 
						policyURISubpacket           signatureSubpacketType = 26
 | 
				
			||||||
	keyFlagsSubpacket            signatureSubpacketType = 27
 | 
						keyFlagsSubpacket            signatureSubpacketType = 27
 | 
				
			||||||
	reasonForRevocationSubpacket signatureSubpacketType = 29
 | 
						reasonForRevocationSubpacket signatureSubpacketType = 29
 | 
				
			||||||
	featuresSubpacket            signatureSubpacketType = 30
 | 
						featuresSubpacket            signatureSubpacketType = 30
 | 
				
			||||||
	embeddedSignatureSubpacket   signatureSubpacketType = 32
 | 
						embeddedSignatureSubpacket   signatureSubpacketType = 32
 | 
				
			||||||
 | 
						issuerFingerprint            signatureSubpacketType = 33
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
 | 
					// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
 | 
				
			||||||
@@ -382,6 +433,32 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
 | 
				
			|||||||
		if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding {
 | 
							if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding {
 | 
				
			||||||
			return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType)))
 | 
								return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType)))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						case policyURISubpacket:
 | 
				
			||||||
 | 
							// See RFC 4880, Section 5.2.3.20
 | 
				
			||||||
 | 
							sig.PolicyURI = string(subpacket[:])
 | 
				
			||||||
 | 
						case regularExpressionSubpacket:
 | 
				
			||||||
 | 
							sig.Regex = string(subpacket[:])
 | 
				
			||||||
 | 
							if isCritical {
 | 
				
			||||||
 | 
								sig.StubbedOutCriticalError = errors.UnsupportedError("regex support is stubbed out")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case prefKeyServerSubpacket:
 | 
				
			||||||
 | 
							sig.PreferredKeyServer = string(subpacket[:])
 | 
				
			||||||
 | 
						case issuerFingerprint:
 | 
				
			||||||
 | 
							// The first byte is how many bytes the fingerprint is, but we'll just
 | 
				
			||||||
 | 
							// read until the end of the subpacket, so we'll ignore it.
 | 
				
			||||||
 | 
							sig.IssuerFingerprint = append([]byte{}, subpacket[1:]...)
 | 
				
			||||||
 | 
						case revocationKey:
 | 
				
			||||||
 | 
							// Authorizes the specified key to issue revocation signatures
 | 
				
			||||||
 | 
							// for a key.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// TODO: Class octet must have bit 0x80 set. If the bit 0x40
 | 
				
			||||||
 | 
							// is set, then this means that the revocation information is
 | 
				
			||||||
 | 
							// sensitive.
 | 
				
			||||||
 | 
							sig.DesignatedRevoker = &RevocationKey{
 | 
				
			||||||
 | 
								Class:         subpacket[0],
 | 
				
			||||||
 | 
								PublicKeyAlgo: PublicKeyAlgorithm(subpacket[1]),
 | 
				
			||||||
 | 
								Fingerprint:   append([]byte{}, subpacket[2:]...),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		if isCritical {
 | 
							if isCritical {
 | 
				
			||||||
			err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
 | 
								err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
 | 
				
			||||||
@@ -464,6 +541,26 @@ func (sig *Signature) KeyExpired(currentTime time.Time) bool {
 | 
				
			|||||||
	return currentTime.After(expiry)
 | 
						return currentTime.After(expiry)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ExpiresBeforeOther checks if other signature has expiration at
 | 
				
			||||||
 | 
					// later date than sig.
 | 
				
			||||||
 | 
					func (sig *Signature) ExpiresBeforeOther(other *Signature) bool {
 | 
				
			||||||
 | 
						if sig.KeyLifetimeSecs == nil {
 | 
				
			||||||
 | 
							// This sig never expires, or has infinitely long expiration
 | 
				
			||||||
 | 
							// time.
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						} else if other.KeyLifetimeSecs == nil {
 | 
				
			||||||
 | 
							// This sig expires at some non-infinite point, but the other
 | 
				
			||||||
 | 
							// sig never expires.
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						getExpiryDate := func(s *Signature) time.Time {
 | 
				
			||||||
 | 
							return s.CreationTime.Add(time.Duration(*s.KeyLifetimeSecs) * time.Second)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return getExpiryDate(other).After(getExpiryDate(sig))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
 | 
					// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
 | 
				
			||||||
func (sig *Signature) buildHashSuffix() (err error) {
 | 
					func (sig *Signature) buildHashSuffix() (err error) {
 | 
				
			||||||
	hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
 | 
						hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
 | 
				
			||||||
@@ -509,16 +606,27 @@ func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) {
 | 
				
			|||||||
// On success, the signature is stored in sig. Call Serialize to write it out.
 | 
					// On success, the signature is stored in sig. Call Serialize to write it out.
 | 
				
			||||||
// If config is nil, sensible defaults will be used.
 | 
					// If config is nil, sensible defaults will be used.
 | 
				
			||||||
func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) {
 | 
					func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) {
 | 
				
			||||||
 | 
						signer, hashIsSigner := h.(Signer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !hashIsSigner && (priv == nil || priv.PrivateKey == nil) {
 | 
				
			||||||
 | 
							err = errors.InvalidArgumentError("attempting to sign with nil PrivateKey")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sig.outSubpackets = sig.buildSubpackets()
 | 
						sig.outSubpackets = sig.buildSubpackets()
 | 
				
			||||||
	digest, err := sig.signPrepareHash(h)
 | 
						digest, err := sig.signPrepareHash(h)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if hashIsSigner {
 | 
				
			||||||
 | 
							err = signer.Sign(sig)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch priv.PubKeyAlgo {
 | 
						switch priv.PubKeyAlgo {
 | 
				
			||||||
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
 | 
						case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
 | 
				
			||||||
		// supports both *rsa.PrivateKey and crypto.Signer
 | 
							sig.RSASignature.bytes, err = rsa.SignPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
 | 
				
			||||||
		sig.RSASignature.bytes, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash)
 | 
					 | 
				
			||||||
		sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
 | 
							sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
 | 
				
			||||||
	case PubKeyAlgoDSA:
 | 
						case PubKeyAlgoDSA:
 | 
				
			||||||
		dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)
 | 
							dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)
 | 
				
			||||||
@@ -536,20 +644,16 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
 | 
				
			|||||||
			sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
 | 
								sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case PubKeyAlgoECDSA:
 | 
						case PubKeyAlgoECDSA:
 | 
				
			||||||
		var r, s *big.Int
 | 
							r, s, err := ecdsa.Sign(config.Random(), priv.PrivateKey.(*ecdsa.PrivateKey), digest)
 | 
				
			||||||
		if pk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok {
 | 
					 | 
				
			||||||
			// direct support, avoid asn1 wrapping/unwrapping
 | 
					 | 
				
			||||||
			r, s, err = ecdsa.Sign(config.Random(), pk, digest)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			var b []byte
 | 
					 | 
				
			||||||
			b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, nil)
 | 
					 | 
				
			||||||
			if err == nil {
 | 
					 | 
				
			||||||
				r, s, err = unwrapECDSASig(b)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if err == nil {
 | 
							if err == nil {
 | 
				
			||||||
			sig.ECDSASigR = fromBig(r)
 | 
								sig.ECDSASigR = FromBig(r)
 | 
				
			||||||
			sig.ECDSASigS = fromBig(s)
 | 
								sig.ECDSASigS = FromBig(s)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case PubKeyAlgoEdDSA:
 | 
				
			||||||
 | 
							r, s, err := priv.PrivateKey.(*EdDSAPrivateKey).Sign(digest)
 | 
				
			||||||
 | 
							if err == nil {
 | 
				
			||||||
 | 
								sig.EdDSASigR = FromBytes(r)
 | 
				
			||||||
 | 
								sig.EdDSASigS = FromBytes(s)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
 | 
							err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
 | 
				
			||||||
@@ -558,19 +662,6 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
 | 
				
			|||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA
 | 
					 | 
				
			||||||
// signature.
 | 
					 | 
				
			||||||
func unwrapECDSASig(b []byte) (r, s *big.Int, err error) {
 | 
					 | 
				
			||||||
	var ecsdaSig struct {
 | 
					 | 
				
			||||||
		R, S *big.Int
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	_, err = asn1.Unmarshal(b, &ecsdaSig)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return ecsdaSig.R, ecsdaSig.S, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SignUserId computes a signature from priv, asserting that pub is a valid
 | 
					// 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
 | 
					// key for the identity id.  On success, the signature is stored in sig. Call
 | 
				
			||||||
// Serialize to write it out.
 | 
					// Serialize to write it out.
 | 
				
			||||||
@@ -583,6 +674,16 @@ func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, co
 | 
				
			|||||||
	return sig.Sign(h, priv, config)
 | 
						return sig.Sign(h, priv, config)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SignUserIdWithSigner 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) SignUserIdWithSigner(id string, pub *PublicKey, s Signer, config *Config) error {
 | 
				
			||||||
 | 
						updateUserIdSignatureHash(id, pub, s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return sig.Sign(s, nil, config)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SignKey computes a signature from priv, asserting that pub is a subkey. On
 | 
					// 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.
 | 
					// success, the signature is stored in sig. Call Serialize to write it out.
 | 
				
			||||||
// If config is nil, sensible defaults will be used.
 | 
					// If config is nil, sensible defaults will be used.
 | 
				
			||||||
@@ -594,13 +695,25 @@ func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config)
 | 
				
			|||||||
	return sig.Sign(h, priv, config)
 | 
						return sig.Sign(h, priv, config)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SignKeyWithSigner computes a signature using s, asserting that
 | 
				
			||||||
 | 
					// signeePubKey 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) SignKeyWithSigner(signeePubKey *PublicKey, signerPubKey *PublicKey, s Signer, config *Config) error {
 | 
				
			||||||
 | 
						updateKeySignatureHash(signerPubKey, signeePubKey, s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return sig.Sign(s, nil, config)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
 | 
					// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
 | 
				
			||||||
// called first.
 | 
					// called first.
 | 
				
			||||||
func (sig *Signature) Serialize(w io.Writer) (err error) {
 | 
					func (sig *Signature) Serialize(w io.Writer) (err error) {
 | 
				
			||||||
	if len(sig.outSubpackets) == 0 {
 | 
						if len(sig.outSubpackets) == 0 {
 | 
				
			||||||
		sig.outSubpackets = sig.rawSubpackets
 | 
							sig.outSubpackets = sig.rawSubpackets
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil {
 | 
						if sig.RSASignature.bytes == nil &&
 | 
				
			||||||
 | 
							sig.DSASigR.bytes == nil &&
 | 
				
			||||||
 | 
							sig.ECDSASigR.bytes == nil &&
 | 
				
			||||||
 | 
							sig.EdDSASigR.bytes == nil {
 | 
				
			||||||
		return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
 | 
							return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -611,6 +724,9 @@ func (sig *Signature) Serialize(w io.Writer) (err error) {
 | 
				
			|||||||
	case PubKeyAlgoDSA:
 | 
						case PubKeyAlgoDSA:
 | 
				
			||||||
		sigLength = 2 + len(sig.DSASigR.bytes)
 | 
							sigLength = 2 + len(sig.DSASigR.bytes)
 | 
				
			||||||
		sigLength += 2 + len(sig.DSASigS.bytes)
 | 
							sigLength += 2 + len(sig.DSASigS.bytes)
 | 
				
			||||||
 | 
						case PubKeyAlgoEdDSA:
 | 
				
			||||||
 | 
							sigLength = 2 + len(sig.EdDSASigR.bytes)
 | 
				
			||||||
 | 
							sigLength += 2 + len(sig.EdDSASigS.bytes)
 | 
				
			||||||
	case PubKeyAlgoECDSA:
 | 
						case PubKeyAlgoECDSA:
 | 
				
			||||||
		sigLength = 2 + len(sig.ECDSASigR.bytes)
 | 
							sigLength = 2 + len(sig.ECDSASigR.bytes)
 | 
				
			||||||
		sigLength += 2 + len(sig.ECDSASigS.bytes)
 | 
							sigLength += 2 + len(sig.ECDSASigS.bytes)
 | 
				
			||||||
@@ -651,6 +767,8 @@ func (sig *Signature) Serialize(w io.Writer) (err error) {
 | 
				
			|||||||
		err = writeMPIs(w, sig.RSASignature)
 | 
							err = writeMPIs(w, sig.RSASignature)
 | 
				
			||||||
	case PubKeyAlgoDSA:
 | 
						case PubKeyAlgoDSA:
 | 
				
			||||||
		err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
 | 
							err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
 | 
				
			||||||
 | 
						case PubKeyAlgoEdDSA:
 | 
				
			||||||
 | 
							err = writeMPIs(w, sig.EdDSASigR, sig.EdDSASigS)
 | 
				
			||||||
	case PubKeyAlgoECDSA:
 | 
						case PubKeyAlgoECDSA:
 | 
				
			||||||
		err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS)
 | 
							err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS)
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
@@ -687,20 +805,7 @@ func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
 | 
				
			|||||||
	// Key flags may only appear in self-signatures or certification signatures.
 | 
						// Key flags may only appear in self-signatures or certification signatures.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if sig.FlagsValid {
 | 
						if sig.FlagsValid {
 | 
				
			||||||
		var flags byte
 | 
							subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{sig.GetKeyFlags().BitField}})
 | 
				
			||||||
		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
 | 
						// The following subpackets may only appear in self-signatures
 | 
				
			||||||
@@ -729,3 +834,47 @@ func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (sig *Signature) GetKeyFlags() (ret KeyFlagBits) {
 | 
				
			||||||
 | 
						if !sig.FlagsValid {
 | 
				
			||||||
 | 
							return ret
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret.Valid = true
 | 
				
			||||||
 | 
						if sig.FlagCertify {
 | 
				
			||||||
 | 
							ret.BitField |= KeyFlagCertify
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if sig.FlagSign {
 | 
				
			||||||
 | 
							ret.BitField |= KeyFlagSign
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if sig.FlagEncryptCommunications {
 | 
				
			||||||
 | 
							ret.BitField |= KeyFlagEncryptCommunications
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if sig.FlagEncryptStorage {
 | 
				
			||||||
 | 
							ret.BitField |= KeyFlagEncryptStorage
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ret
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *KeyFlagBits) HasFlagCertify() bool {
 | 
				
			||||||
 | 
						return f.BitField&KeyFlagCertify != 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *KeyFlagBits) HasFlagSign() bool {
 | 
				
			||||||
 | 
						return f.BitField&KeyFlagSign != 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *KeyFlagBits) HasFlagEncryptCommunications() bool {
 | 
				
			||||||
 | 
						return f.BitField&KeyFlagEncryptCommunications != 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *KeyFlagBits) HasFlagEncryptStorage() bool {
 | 
				
			||||||
 | 
						return f.BitField&KeyFlagEncryptStorage != 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *KeyFlagBits) Merge(other KeyFlagBits) {
 | 
				
			||||||
 | 
						if other.Valid {
 | 
				
			||||||
 | 
							f.Valid = true
 | 
				
			||||||
 | 
							f.BitField |= other.BitField
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -12,8 +12,8 @@ import (
 | 
				
			|||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/errors"
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/s2k"
 | 
						"github.com/keybase/go-crypto/openpgp/s2k"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SignatureV3 represents older version 3 signatures. These signatures are less secure
 | 
					// SignatureV3 represents older version 3 signatures. These signatures are less secure
 | 
				
			||||||
@@ -10,8 +10,8 @@ import (
 | 
				
			|||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/errors"
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/s2k"
 | 
						"github.com/keybase/go-crypto/openpgp/s2k"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This is the largest session key that we'll support. Since no 512-bit cipher
 | 
					// This is the largest session key that we'll support. Since no 512-bit cipher
 | 
				
			||||||
@@ -48,6 +48,9 @@ func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if ske.s2k == nil {
 | 
				
			||||||
 | 
							return errors.UnsupportedError("can't use dummy S2K for symmetric key encryption")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	encryptedKey := make([]byte, maxSessionKeySizeInBytes)
 | 
						encryptedKey := make([]byte, maxSessionKeySizeInBytes)
 | 
				
			||||||
	// The session key may follow. We just have to try and read to find
 | 
						// The session key may follow. We just have to try and read to find
 | 
				
			||||||
@@ -8,10 +8,11 @@ import (
 | 
				
			|||||||
	"crypto/cipher"
 | 
						"crypto/cipher"
 | 
				
			||||||
	"crypto/sha1"
 | 
						"crypto/sha1"
 | 
				
			||||||
	"crypto/subtle"
 | 
						"crypto/subtle"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/errors"
 | 
					 | 
				
			||||||
	"hash"
 | 
						"hash"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The
 | 
					// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The
 | 
				
			||||||
							
								
								
									
										7
									
								
								vendor/github.com/keybase/go-crypto/openpgp/patch.sh
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/keybase/go-crypto/openpgp/patch.sh
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					patch < sig-v3.patch
 | 
				
			||||||
 | 
					patch < s2k-gnu-dummy.patch
 | 
				
			||||||
 | 
					find . -type f -name '*.go' -exec sed -i'' -e 's/golang.org\/x\/crypto\/openpgp/github.com\/keybase\/go-crypto\/openpgp/' {} \;
 | 
				
			||||||
 | 
					find . -type f -name '*.go-e' -exec rm {} \;
 | 
				
			||||||
 | 
					go test ./...
 | 
				
			||||||
@@ -3,18 +3,19 @@
 | 
				
			|||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Package openpgp implements high level operations on OpenPGP messages.
 | 
					// Package openpgp implements high level operations on OpenPGP messages.
 | 
				
			||||||
package openpgp // import "golang.org/x/crypto/openpgp"
 | 
					package openpgp // import "github.com/keybase/go-crypto/openpgp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"crypto"
 | 
						"crypto"
 | 
				
			||||||
 | 
						"crypto/hmac"
 | 
				
			||||||
	_ "crypto/sha256"
 | 
						_ "crypto/sha256"
 | 
				
			||||||
	"hash"
 | 
						"hash"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/armor"
 | 
						"github.com/keybase/go-crypto/openpgp/armor"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/errors"
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/packet"
 | 
						"github.com/keybase/go-crypto/openpgp/packet"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SignatureType is the armor type for a PGP signature.
 | 
					// SignatureType is the armor type for a PGP signature.
 | 
				
			||||||
@@ -50,7 +51,7 @@ type MessageDetails struct {
 | 
				
			|||||||
	// If IsSigned is true and SignedBy is non-zero then the signature will
 | 
						// If IsSigned is true and SignedBy is non-zero then the signature will
 | 
				
			||||||
	// be verified as UnverifiedBody is read. The signature cannot be
 | 
						// be verified as UnverifiedBody is read. The signature cannot be
 | 
				
			||||||
	// checked until the whole of UnverifiedBody is read so UnverifiedBody
 | 
						// checked until the whole of UnverifiedBody is read so UnverifiedBody
 | 
				
			||||||
	// must be consumed until EOF before the data can be trusted. Even if a
 | 
						// must be consumed until EOF before the data can trusted. Even if a
 | 
				
			||||||
	// message isn't signed (or the signer is unknown) the data may contain
 | 
						// message isn't signed (or the signer is unknown) the data may contain
 | 
				
			||||||
	// an authentication code that is only checked once UnverifiedBody has
 | 
						// an authentication code that is only checked once UnverifiedBody has
 | 
				
			||||||
	// been consumed. Once EOF has been seen, the following fields are
 | 
						// been consumed. Once EOF has been seen, the following fields are
 | 
				
			||||||
@@ -113,7 +114,7 @@ ParsePackets:
 | 
				
			|||||||
			// This packet contains the decryption key encrypted to a public key.
 | 
								// This packet contains the decryption key encrypted to a public key.
 | 
				
			||||||
			md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId)
 | 
								md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId)
 | 
				
			||||||
			switch p.Algo {
 | 
								switch p.Algo {
 | 
				
			||||||
			case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal:
 | 
								case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal, packet.PubKeyAlgoECDH:
 | 
				
			||||||
				break
 | 
									break
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
@@ -122,7 +123,7 @@ ParsePackets:
 | 
				
			|||||||
			if p.KeyId == 0 {
 | 
								if p.KeyId == 0 {
 | 
				
			||||||
				keys = keyring.DecryptionKeys()
 | 
									keys = keyring.DecryptionKeys()
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				keys = keyring.KeysById(p.KeyId)
 | 
									keys = keyring.KeysById(p.KeyId, nil)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			for _, k := range keys {
 | 
								for _, k := range keys {
 | 
				
			||||||
				pubKeys = append(pubKeys, keyEnvelopePair{k, p})
 | 
									pubKeys = append(pubKeys, keyEnvelopePair{k, p})
 | 
				
			||||||
@@ -255,7 +256,7 @@ FindLiteralData:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			md.IsSigned = true
 | 
								md.IsSigned = true
 | 
				
			||||||
			md.SignedByKeyId = p.KeyId
 | 
								md.SignedByKeyId = p.KeyId
 | 
				
			||||||
			keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign)
 | 
								keys := keyring.KeysByIdUsage(p.KeyId, nil, packet.KeyFlagSign)
 | 
				
			||||||
			if len(keys) > 0 {
 | 
								if len(keys) > 0 {
 | 
				
			||||||
				md.SignedBy = &keys[0]
 | 
									md.SignedBy = &keys[0]
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -336,7 +337,16 @@ func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		var ok bool
 | 
							var ok bool
 | 
				
			||||||
		if scr.md.Signature, ok = p.(*packet.Signature); ok {
 | 
							if scr.md.Signature, ok = p.(*packet.Signature); ok {
 | 
				
			||||||
			scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature)
 | 
								var err error
 | 
				
			||||||
 | 
								if fingerprint := scr.md.Signature.IssuerFingerprint; fingerprint != nil {
 | 
				
			||||||
 | 
									if !hmac.Equal(fingerprint, scr.md.SignedBy.PublicKey.Fingerprint[:]) {
 | 
				
			||||||
 | 
										err = errors.StructuralError("bad key fingerprint")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if err == nil {
 | 
				
			||||||
 | 
									err = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								scr.md.SignatureError = err
 | 
				
			||||||
		} else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok {
 | 
							} else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok {
 | 
				
			||||||
			scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3)
 | 
								scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
@@ -361,7 +371,13 @@ func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) {
 | 
				
			|||||||
// returns the signer if the signature is valid. If the signer isn't known,
 | 
					// returns the signer if the signature is valid. If the signer isn't known,
 | 
				
			||||||
// ErrUnknownIssuer is returned.
 | 
					// ErrUnknownIssuer is returned.
 | 
				
			||||||
func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
 | 
					func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
 | 
				
			||||||
 | 
						signer, _, err = checkDetachedSignature(keyring, signed, signature)
 | 
				
			||||||
 | 
						return signer, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func checkDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, issuer *uint64, err error) {
 | 
				
			||||||
	var issuerKeyId uint64
 | 
						var issuerKeyId uint64
 | 
				
			||||||
 | 
						var issuerFingerprint []byte
 | 
				
			||||||
	var hashFunc crypto.Hash
 | 
						var hashFunc crypto.Hash
 | 
				
			||||||
	var sigType packet.SignatureType
 | 
						var sigType packet.SignatureType
 | 
				
			||||||
	var keys []Key
 | 
						var keys []Key
 | 
				
			||||||
@@ -371,29 +387,30 @@ func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signe
 | 
				
			|||||||
	for {
 | 
						for {
 | 
				
			||||||
		p, err = packets.Next()
 | 
							p, err = packets.Next()
 | 
				
			||||||
		if err == io.EOF {
 | 
							if err == io.EOF {
 | 
				
			||||||
			return nil, errors.ErrUnknownIssuer
 | 
								return nil, nil, errors.ErrUnknownIssuer
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch sig := p.(type) {
 | 
							switch sig := p.(type) {
 | 
				
			||||||
		case *packet.Signature:
 | 
							case *packet.Signature:
 | 
				
			||||||
			if sig.IssuerKeyId == nil {
 | 
								if sig.IssuerKeyId == nil {
 | 
				
			||||||
				return nil, errors.StructuralError("signature doesn't have an issuer")
 | 
									return nil, nil, errors.StructuralError("signature doesn't have an issuer")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			issuerKeyId = *sig.IssuerKeyId
 | 
								issuerKeyId = *sig.IssuerKeyId
 | 
				
			||||||
			hashFunc = sig.Hash
 | 
								hashFunc = sig.Hash
 | 
				
			||||||
			sigType = sig.SigType
 | 
								sigType = sig.SigType
 | 
				
			||||||
 | 
								issuerFingerprint = sig.IssuerFingerprint
 | 
				
			||||||
		case *packet.SignatureV3:
 | 
							case *packet.SignatureV3:
 | 
				
			||||||
			issuerKeyId = sig.IssuerKeyId
 | 
								issuerKeyId = sig.IssuerKeyId
 | 
				
			||||||
			hashFunc = sig.Hash
 | 
								hashFunc = sig.Hash
 | 
				
			||||||
			sigType = sig.SigType
 | 
								sigType = sig.SigType
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			return nil, errors.StructuralError("non signature packet found")
 | 
								return nil, nil, errors.StructuralError("non signature packet found")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign)
 | 
							keys = keyring.KeysByIdUsage(issuerKeyId, issuerFingerprint, packet.KeyFlagSign)
 | 
				
			||||||
		if len(keys) > 0 {
 | 
							if len(keys) > 0 {
 | 
				
			||||||
			break
 | 
								break
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -405,11 +422,11 @@ func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signe
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	h, wrappedHash, err := hashForSignature(hashFunc, sigType)
 | 
						h, wrappedHash, err := hashForSignature(hashFunc, sigType)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if _, err := io.Copy(wrappedHash, signed); err != nil && err != io.EOF {
 | 
						if _, err := io.Copy(wrappedHash, signed); err != nil && err != io.EOF {
 | 
				
			||||||
		return nil, err
 | 
							return nil, nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, key := range keys {
 | 
						for _, key := range keys {
 | 
				
			||||||
@@ -423,20 +440,24 @@ func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signe
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err == nil {
 | 
							if err == nil {
 | 
				
			||||||
			return key.Entity, nil
 | 
								return key.Entity, &issuerKeyId, nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil, err
 | 
						return nil, nil, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CheckArmoredDetachedSignature performs the same actions as
 | 
					// CheckArmoredDetachedSignature performs the same actions as
 | 
				
			||||||
// CheckDetachedSignature but expects the signature to be armored.
 | 
					// CheckDetachedSignature but expects the signature to be armored.
 | 
				
			||||||
func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
 | 
					func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
 | 
				
			||||||
 | 
						signer, _, err = checkArmoredDetachedSignature(keyring, signed, signature)
 | 
				
			||||||
 | 
						return signer, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func checkArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, issuer *uint64, err error) {
 | 
				
			||||||
	body, err := readArmored(signature, SignatureType)
 | 
						body, err := readArmored(signature, SignatureType)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return checkDetachedSignature(keyring, signed, body)
 | 
				
			||||||
	return CheckDetachedSignature(keyring, signed, body)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -4,7 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Package s2k implements the various OpenPGP string-to-key transforms as
 | 
					// Package s2k implements the various OpenPGP string-to-key transforms as
 | 
				
			||||||
// specified in RFC 4800 section 3.7.1.
 | 
					// specified in RFC 4800 section 3.7.1.
 | 
				
			||||||
package s2k // import "golang.org/x/crypto/openpgp/s2k"
 | 
					package s2k // import "github.com/keybase/go-crypto/openpgp/s2k"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"crypto"
 | 
						"crypto"
 | 
				
			||||||
@@ -12,7 +12,7 @@ import (
 | 
				
			|||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/errors"
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Config collects configuration parameters for s2k key-stretching
 | 
					// Config collects configuration parameters for s2k key-stretching
 | 
				
			||||||
@@ -151,6 +151,53 @@ func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func parseGNUExtensions(r io.Reader) (f func(out, in []byte), err error) {
 | 
				
			||||||
 | 
						var buf [9]byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// A three-byte string identifier
 | 
				
			||||||
 | 
						_, err = io.ReadFull(r, buf[:3])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						gnuExt := string(buf[:3])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if gnuExt != "GNU" {
 | 
				
			||||||
 | 
							return nil, errors.UnsupportedError("Malformed GNU extension: " + gnuExt)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, err = io.ReadFull(r, buf[:1])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						gnuExtType := int(buf[0])
 | 
				
			||||||
 | 
						switch gnuExtType {
 | 
				
			||||||
 | 
						case 1:
 | 
				
			||||||
 | 
							return nil, nil
 | 
				
			||||||
 | 
						case 2:
 | 
				
			||||||
 | 
							// Read a serial number, which is prefixed by a 1-byte length.
 | 
				
			||||||
 | 
							// The maximum length is 16.
 | 
				
			||||||
 | 
							var lenBuf [1]byte
 | 
				
			||||||
 | 
							_, err = io.ReadFull(r, lenBuf[:])
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							maxLen := 16
 | 
				
			||||||
 | 
							ivLen := int(lenBuf[0])
 | 
				
			||||||
 | 
							if ivLen > maxLen {
 | 
				
			||||||
 | 
								ivLen = maxLen
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ivBuf := make([]byte, ivLen)
 | 
				
			||||||
 | 
							// For now we simply discard the IV
 | 
				
			||||||
 | 
							_, err = io.ReadFull(r, ivBuf)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil, nil
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return nil, errors.UnsupportedError("unknown S2K GNU protection mode: " + strconv.Itoa(int(gnuExtType)))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Parse reads a binary specification for a string-to-key transformation from r
 | 
					// Parse reads a binary specification for a string-to-key transformation from r
 | 
				
			||||||
// and returns a function which performs that transform.
 | 
					// and returns a function which performs that transform.
 | 
				
			||||||
func Parse(r io.Reader) (f func(out, in []byte), err error) {
 | 
					func Parse(r io.Reader) (f func(out, in []byte), err error) {
 | 
				
			||||||
@@ -161,6 +208,12 @@ func Parse(r io.Reader) (f func(out, in []byte), err error) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// GNU Extensions; handle them before we try to look for a hash, which won't
 | 
				
			||||||
 | 
						// be needed in most cases anyway.
 | 
				
			||||||
 | 
						if buf[0] == 101 {
 | 
				
			||||||
 | 
							return parseGNUExtensions(r)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hash, ok := HashIdToHash(buf[1])
 | 
						hash, ok := HashIdToHash(buf[1])
 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
		return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1])))
 | 
							return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1])))
 | 
				
			||||||
@@ -251,7 +304,7 @@ func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HashIdToString returns the name of the hash function corresponding to the
 | 
					// HashIdToString returns the name of the hash function corresponding to the
 | 
				
			||||||
// given OpenPGP hash id.
 | 
					// given OpenPGP hash id, or panics if id is unknown.
 | 
				
			||||||
func HashIdToString(id byte) (name string, ok bool) {
 | 
					func HashIdToString(id byte) (name string, ok bool) {
 | 
				
			||||||
	for _, m := range hashToHashIdMapping {
 | 
						for _, m := range hashToHashIdMapping {
 | 
				
			||||||
		if m.id == id {
 | 
							if m.id == id {
 | 
				
			||||||
							
								
								
									
										135
									
								
								vendor/github.com/keybase/go-crypto/openpgp/sig-v3.patch
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								vendor/github.com/keybase/go-crypto/openpgp/sig-v3.patch
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,135 @@
 | 
				
			|||||||
 | 
					diff --git a/openpgp/read.go b/openpgp/read.go
 | 
				
			||||||
 | 
					index a6cecc5..0c9397b 100644
 | 
				
			||||||
 | 
					--- a/openpgp/read.go
 | 
				
			||||||
 | 
					+++ b/openpgp/read.go
 | 
				
			||||||
 | 
					@@ -56,8 +56,9 @@ type MessageDetails struct {
 | 
				
			||||||
 | 
					 	// been consumed. Once EOF has been seen, the following fields are
 | 
				
			||||||
 | 
					 	// valid. (An authentication code failure is reported as a
 | 
				
			||||||
 | 
					 	// SignatureError error when reading from UnverifiedBody.)
 | 
				
			||||||
 | 
					-	SignatureError error             // nil if the signature is good.
 | 
				
			||||||
 | 
					-	Signature      *packet.Signature // the signature packet itself.
 | 
				
			||||||
 | 
					+	SignatureError error               // nil if the signature is good.
 | 
				
			||||||
 | 
					+	Signature      *packet.Signature   // the signature packet itself, if v4 (default)
 | 
				
			||||||
 | 
					+	SignatureV3    *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	decrypted io.ReadCloser
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					@@ -334,13 +335,15 @@ func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) {
 | 
				
			||||||
 | 
					 		}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 		var ok bool
 | 
				
			||||||
 | 
					-		if scr.md.Signature, ok = p.(*packet.Signature); !ok {
 | 
				
			||||||
 | 
					+		if scr.md.Signature, ok = p.(*packet.Signature); ok {
 | 
				
			||||||
 | 
					+			scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature)
 | 
				
			||||||
 | 
					+		} else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok {
 | 
				
			||||||
 | 
					+			scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3)
 | 
				
			||||||
 | 
					+		} else {
 | 
				
			||||||
 | 
					 			scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature")
 | 
				
			||||||
 | 
					 			return
 | 
				
			||||||
 | 
					 		}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-		scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature)
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 		// The SymmetricallyEncrypted packet, if any, might have an
 | 
				
			||||||
 | 
					 		// unsigned hash of its own. In order to check this we need to
 | 
				
			||||||
 | 
					 		// close that Reader.
 | 
				
			||||||
 | 
					diff --git a/openpgp/read_test.go b/openpgp/read_test.go
 | 
				
			||||||
 | 
					index 52f942c..abe8d7b 100644
 | 
				
			||||||
 | 
					--- a/openpgp/read_test.go
 | 
				
			||||||
 | 
					+++ b/openpgp/read_test.go
 | 
				
			||||||
 | 
					@@ -13,6 +13,7 @@ import (
 | 
				
			||||||
 | 
					 	"strings"
 | 
				
			||||||
 | 
					 	"testing"
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	"golang.org/x/crypto/openpgp/armor"
 | 
				
			||||||
 | 
					 	"golang.org/x/crypto/openpgp/errors"
 | 
				
			||||||
 | 
					 )
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -411,6 +412,50 @@ func TestIssue11504(t *testing.T) {
 | 
				
			||||||
 | 
					 	testReadMessageError(t, "9303000130303030303030303030983002303030303030030000000130")
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+// TestSignatureV3Message tests the verification of V3 signature, generated
 | 
				
			||||||
 | 
					+// with a modern V4-style key.  Some people have their clients set to generate
 | 
				
			||||||
 | 
					+// V3 signatures, so it's useful to be able to verify them.
 | 
				
			||||||
 | 
					+func TestSignatureV3Message(t *testing.T) {
 | 
				
			||||||
 | 
					+	sig, err := armor.Decode(strings.NewReader(signedMessageV3))
 | 
				
			||||||
 | 
					+	if err != nil {
 | 
				
			||||||
 | 
					+		t.Error(err)
 | 
				
			||||||
 | 
					+		return
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	key, err := ReadArmoredKeyRing(strings.NewReader(keyV4forVerifyingSignedMessageV3))
 | 
				
			||||||
 | 
					+	if err != nil {
 | 
				
			||||||
 | 
					+		t.Error(err)
 | 
				
			||||||
 | 
					+		return
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	md, err := ReadMessage(sig.Body, key, nil, nil)
 | 
				
			||||||
 | 
					+	if err != nil {
 | 
				
			||||||
 | 
					+		t.Error(err)
 | 
				
			||||||
 | 
					+		return
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	_, err = ioutil.ReadAll(md.UnverifiedBody)
 | 
				
			||||||
 | 
					+	if err != nil {
 | 
				
			||||||
 | 
					+		t.Error(err)
 | 
				
			||||||
 | 
					+		return
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	// We'll see a sig error here after reading in the UnverifiedBody above,
 | 
				
			||||||
 | 
					+	// if there was one to see.
 | 
				
			||||||
 | 
					+	if err = md.SignatureError; err != nil {
 | 
				
			||||||
 | 
					+		t.Error(err)
 | 
				
			||||||
 | 
					+		return
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if md.SignatureV3 == nil {
 | 
				
			||||||
 | 
					+		t.Errorf("No available signature after checking signature")
 | 
				
			||||||
 | 
					+		return
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	if md.Signature != nil {
 | 
				
			||||||
 | 
					+		t.Errorf("Did not expect a signature V4 back")
 | 
				
			||||||
 | 
					+		return
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	return
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 const testKey1KeyId = 0xA34D7E18C20C31BB
 | 
				
			||||||
 | 
					 const testKey3KeyId = 0x338934250CCC0360
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -504,3 +549,36 @@ const unknownHashFunctionHex = `8a00000040040001990006050253863c24000a09103b4fe6
 | 
				
			||||||
 | 
					 const missingHashFunctionHex = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101`
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 const campbellQuine = `a0b001000300fcffa0b001000d00f2ff000300fcffa0b001000d00f2ff8270a01c00000500faff8270a01c00000500faff000500faff001400ebff8270a01c00000500faff000500faff001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400000000ffff000000ffff000b00f4ff428821c400000000ffff000000ffff000b00f4ff0233214c40000100feff000233214c40000100feff0000`
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+const keyV4forVerifyingSignedMessageV3 = `-----BEGIN PGP PUBLIC KEY BLOCK-----
 | 
				
			||||||
 | 
					+Comment: GPGTools - https://gpgtools.org
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+mI0EVfxoFQEEAMBIqmbDfYygcvP6Phr1wr1XI41IF7Qixqybs/foBF8qqblD9gIY
 | 
				
			||||||
 | 
					+BKpXjnBOtbkcVOJ0nljd3/sQIfH4E0vQwK5/4YRQSI59eKOqd6Fx+fWQOLG+uu6z
 | 
				
			||||||
 | 
					+tewpeCj9LLHvibx/Sc7VWRnrznia6ftrXxJ/wHMezSab3tnGC0YPVdGNABEBAAG0
 | 
				
			||||||
 | 
					+JEdvY3J5cHRvIFRlc3QgS2V5IDx0aGVtYXhAZ21haWwuY29tPoi5BBMBCgAjBQJV
 | 
				
			||||||
 | 
					+/GgVAhsDBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQeXnQmhdGW9PFVAP+
 | 
				
			||||||
 | 
					+K7TU0qX5ArvIONIxh/WAweyOk884c5cE8f+3NOPOOCRGyVy0FId5A7MmD5GOQh4H
 | 
				
			||||||
 | 
					+JseOZVEVCqlmngEvtHZb3U1VYtVGE5WZ+6rQhGsMcWP5qaT4soYwMBlSYxgYwQcx
 | 
				
			||||||
 | 
					+YhN9qOr292f9j2Y//TTIJmZT4Oa+lMxhWdqTfX+qMgG4jQRV/GgVAQQArhFSiij1
 | 
				
			||||||
 | 
					+b+hT3dnapbEU+23Z1yTu1DfF6zsxQ4XQWEV3eR8v+8mEDDNcz8oyyF56k6UQ3rXi
 | 
				
			||||||
 | 
					+UMTIwRDg4V6SbZmaFbZYCOwp/EmXJ3rfhm7z7yzXj2OFN22luuqbyVhuL7LRdB0M
 | 
				
			||||||
 | 
					+pxgmjXb4tTvfgKd26x34S+QqUJ7W6uprY4sAEQEAAYifBBgBCgAJBQJV/GgVAhsM
 | 
				
			||||||
 | 
					+AAoJEHl50JoXRlvT7y8D/02ckx4OMkKBZo7viyrBw0MLG92i+DC2bs35PooHR6zz
 | 
				
			||||||
 | 
					+786mitjOp5z2QWNLBvxC70S0qVfCIz8jKupO1J6rq6Z8CcbLF3qjm6h1omUBf8Nd
 | 
				
			||||||
 | 
					+EfXKD2/2HV6zMKVknnKzIEzauh+eCKS2CeJUSSSryap/QLVAjRnckaES/OsEWhNB
 | 
				
			||||||
 | 
					+=RZia
 | 
				
			||||||
 | 
					+-----END PGP PUBLIC KEY BLOCK-----
 | 
				
			||||||
 | 
					+`
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+const signedMessageV3 = `-----BEGIN PGP MESSAGE-----
 | 
				
			||||||
 | 
					+Comment: GPGTools - https://gpgtools.org
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+owGbwMvMwMVYWXlhlrhb9GXG03JJDKF/MtxDMjKLFYAoUaEktbhEITe1uDgxPVWP
 | 
				
			||||||
 | 
					+q5NhKjMrWAVcC9evD8z/bF/uWNjqtk/X3y5/38XGRQHm/57rrDRYuGnTw597Xqka
 | 
				
			||||||
 | 
					+uM3137/hH3Os+Jf2dc0fXOITKwJvXJvecPVs0ta+Vg7ZO1MLn8w58Xx+6L58mbka
 | 
				
			||||||
 | 
					+DGHyU9yTueZE8D+QF/Tz28Y78dqtF56R1VPn9Xw4uJqrWYdd7b3vIZ1V6R4Nh05d
 | 
				
			||||||
 | 
					+iT57d/OhWwA=
 | 
				
			||||||
 | 
					+=hG7R
 | 
				
			||||||
 | 
					+-----END PGP MESSAGE-----
 | 
				
			||||||
 | 
					+`
 | 
				
			||||||
@@ -11,10 +11,10 @@ import (
 | 
				
			|||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/armor"
 | 
						"github.com/keybase/go-crypto/openpgp/armor"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/errors"
 | 
						"github.com/keybase/go-crypto/openpgp/errors"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/packet"
 | 
						"github.com/keybase/go-crypto/openpgp/packet"
 | 
				
			||||||
	"golang.org/x/crypto/openpgp/s2k"
 | 
						"github.com/keybase/go-crypto/openpgp/s2k"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DetachSign signs message with the private key from signer (which must
 | 
					// DetachSign signs message with the private key from signer (which must
 | 
				
			||||||
@@ -59,20 +59,57 @@ func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType p
 | 
				
			|||||||
	return out.Close()
 | 
						return out.Close()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SignWithSigner signs the message of type sigType with s and writes the
 | 
				
			||||||
 | 
					// signature to w.
 | 
				
			||||||
 | 
					// If config is nil, sensible defaults will be used.
 | 
				
			||||||
 | 
					func SignWithSigner(s packet.Signer, w io.Writer, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) {
 | 
				
			||||||
 | 
						keyId := s.KeyId()
 | 
				
			||||||
 | 
						sig := new(packet.Signature)
 | 
				
			||||||
 | 
						sig.SigType = sigType
 | 
				
			||||||
 | 
						sig.PubKeyAlgo = s.PublicKeyAlgo()
 | 
				
			||||||
 | 
						sig.Hash = config.Hash()
 | 
				
			||||||
 | 
						sig.CreationTime = config.Now()
 | 
				
			||||||
 | 
						sig.IssuerKeyId = &keyId
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s.Reset()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wrapped := s.(hash.Hash)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if sigType == packet.SigTypeText {
 | 
				
			||||||
 | 
							wrapped = NewCanonicalTextHash(s)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						io.Copy(wrapped, message)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = sig.Sign(s, nil, config)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = sig.Serialize(w)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) {
 | 
					func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) {
 | 
				
			||||||
	if signer.PrivateKey == nil {
 | 
						signerSubkey, ok := signer.signingKey(config.Now())
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							err = errors.InvalidArgumentError("no valid signing keys")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if signerSubkey.PrivateKey == nil {
 | 
				
			||||||
		return errors.InvalidArgumentError("signing key doesn't have a private key")
 | 
							return errors.InvalidArgumentError("signing key doesn't have a private key")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if signer.PrivateKey.Encrypted {
 | 
						if signerSubkey.PrivateKey.Encrypted {
 | 
				
			||||||
		return errors.InvalidArgumentError("signing key is encrypted")
 | 
							return errors.InvalidArgumentError("signing key is encrypted")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sig := new(packet.Signature)
 | 
						sig := new(packet.Signature)
 | 
				
			||||||
	sig.SigType = sigType
 | 
						sig.SigType = sigType
 | 
				
			||||||
	sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo
 | 
						sig.PubKeyAlgo = signerSubkey.PrivateKey.PubKeyAlgo
 | 
				
			||||||
	sig.Hash = config.Hash()
 | 
						sig.Hash = config.Hash()
 | 
				
			||||||
	sig.CreationTime = config.Now()
 | 
						sig.CreationTime = config.Now()
 | 
				
			||||||
	sig.IssuerKeyId = &signer.PrivateKey.KeyId
 | 
						sig.IssuerKeyId = &signerSubkey.PrivateKey.KeyId
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
 | 
						h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -80,7 +117,7 @@ func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.S
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	io.Copy(wrappedHash, message)
 | 
						io.Copy(wrappedHash, message)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = sig.Sign(h, signer.PrivateKey, config)
 | 
						err = sig.Sign(h, signerSubkey.PrivateKey, config)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -198,11 +235,20 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
 | 
				
			|||||||
		hashToHashId(crypto.SHA1),
 | 
							hashToHashId(crypto.SHA1),
 | 
				
			||||||
		hashToHashId(crypto.RIPEMD160),
 | 
							hashToHashId(crypto.RIPEMD160),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// In the event that a recipient doesn't specify any supported ciphers
 | 
					
 | 
				
			||||||
	// or hash functions, these are the ones that we assume that every
 | 
						// If no preferences were specified, assume something safe and reasonable.
 | 
				
			||||||
	// implementation supports.
 | 
						defaultCiphers := []uint8{
 | 
				
			||||||
	defaultCiphers := candidateCiphers[len(candidateCiphers)-1:]
 | 
							uint8(packet.CipherAES128),
 | 
				
			||||||
	defaultHashes := candidateHashes[len(candidateHashes)-1:]
 | 
							uint8(packet.CipherAES192),
 | 
				
			||||||
 | 
							uint8(packet.CipherAES256),
 | 
				
			||||||
 | 
							uint8(packet.CipherCAST5),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defaultHashes := []uint8{
 | 
				
			||||||
 | 
							hashToHashId(crypto.SHA256),
 | 
				
			||||||
 | 
							hashToHashId(crypto.SHA512),
 | 
				
			||||||
 | 
							hashToHashId(crypto.RIPEMD160),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	encryptKeys := make([]Key, len(to))
 | 
						encryptKeys := make([]Key, len(to))
 | 
				
			||||||
	for i := range to {
 | 
						for i := range to {
 | 
				
			||||||
@@ -226,12 +272,15 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
 | 
				
			|||||||
		candidateHashes = intersectPreferences(candidateHashes, preferredHashes)
 | 
							candidateHashes = intersectPreferences(candidateHashes, preferredHashes)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(candidateCiphers) == 0 || len(candidateHashes) == 0 {
 | 
						if len(candidateCiphers) == 0 {
 | 
				
			||||||
		return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms")
 | 
							return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common ciphers")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(candidateHashes) == 0 {
 | 
				
			||||||
 | 
							return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common hashes")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cipher := packet.CipherFunction(candidateCiphers[0])
 | 
						cipher := packet.CipherFunction(candidateCiphers[0])
 | 
				
			||||||
	// If the cipher specified by config is a candidate, we'll use that.
 | 
						// If the cipher specifed by config is a candidate, we'll use that.
 | 
				
			||||||
	configuredCipher := config.Cipher()
 | 
						configuredCipher := config.Cipher()
 | 
				
			||||||
	for _, c := range candidateCiphers {
 | 
						for _, c := range candidateCiphers {
 | 
				
			||||||
		cipherFunc := packet.CipherFunction(c)
 | 
							cipherFunc := packet.CipherFunction(c)
 | 
				
			||||||
@@ -376,3 +425,71 @@ func (c noOpCloser) Write(data []byte) (n int, err error) {
 | 
				
			|||||||
func (c noOpCloser) Close() error {
 | 
					func (c noOpCloser) Close() error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AttachedSign is like openpgp.Encrypt (as in p.crypto/openpgp/write.go), but
 | 
				
			||||||
 | 
					// don't encrypt at all, just sign the literal unencrypted data.
 | 
				
			||||||
 | 
					// Unfortunately we need to duplicate some code here that's already
 | 
				
			||||||
 | 
					// in write.go
 | 
				
			||||||
 | 
					func AttachedSign(out io.WriteCloser, signed Entity, hints *FileHints,
 | 
				
			||||||
 | 
						config *packet.Config) (in io.WriteCloser, err error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if hints == nil {
 | 
				
			||||||
 | 
							hints = &FileHints{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if config == nil {
 | 
				
			||||||
 | 
							config = &packet.Config{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var signer *packet.PrivateKey
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						signKey, ok := signed.signingKey(config.Now())
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							err = errors.InvalidArgumentError("no valid signing keys")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						signer = signKey.PrivateKey
 | 
				
			||||||
 | 
						if signer == nil {
 | 
				
			||||||
 | 
							err = errors.InvalidArgumentError("no valid signing keys")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if signer.Encrypted {
 | 
				
			||||||
 | 
							err = errors.InvalidArgumentError("signing key must be decrypted")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hasher := crypto.SHA512
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ops := &packet.OnePassSignature{
 | 
				
			||||||
 | 
							SigType:    packet.SigTypeBinary,
 | 
				
			||||||
 | 
							Hash:       hasher,
 | 
				
			||||||
 | 
							PubKeyAlgo: signer.PubKeyAlgo,
 | 
				
			||||||
 | 
							KeyId:      signer.KeyId,
 | 
				
			||||||
 | 
							IsLast:     true,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err = ops.Serialize(out); err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var epochSeconds uint32
 | 
				
			||||||
 | 
						if !hints.ModTime.IsZero() {
 | 
				
			||||||
 | 
							epochSeconds = uint32(hints.ModTime.Unix())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We don't want the literal serializer to closer the output stream
 | 
				
			||||||
 | 
						// since we're going to need to write to it when we finish up the
 | 
				
			||||||
 | 
						// signature stuff.
 | 
				
			||||||
 | 
						in, err = packet.SerializeLiteral(noOpCloser{out}, hints.IsBinary, hints.FileName, epochSeconds)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If we need to write a signature packet after the literal
 | 
				
			||||||
 | 
						// data then we need to stop literalData from closing
 | 
				
			||||||
 | 
						// encryptedData.
 | 
				
			||||||
 | 
						in = signatureWriter{out, in, hasher, hasher.New(), signer, config}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										325
									
								
								vendor/github.com/keybase/go-crypto/rsa/pkcs1v15.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										325
									
								
								vendor/github.com/keybase/go-crypto/rsa/pkcs1v15.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,325 @@
 | 
				
			|||||||
 | 
					// 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 rsa
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"crypto"
 | 
				
			||||||
 | 
						"crypto/subtle"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This file implements encryption and decryption using PKCS#1 v1.5 padding.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PKCS1v15DecrypterOpts is for passing options to PKCS#1 v1.5 decryption using
 | 
				
			||||||
 | 
					// the crypto.Decrypter interface.
 | 
				
			||||||
 | 
					type PKCS1v15DecryptOptions struct {
 | 
				
			||||||
 | 
						// SessionKeyLen is the length of the session key that is being
 | 
				
			||||||
 | 
						// decrypted. If not zero, then a padding error during decryption will
 | 
				
			||||||
 | 
						// cause a random plaintext of this length to be returned rather than
 | 
				
			||||||
 | 
						// an error. These alternatives happen in constant time.
 | 
				
			||||||
 | 
						SessionKeyLen int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// EncryptPKCS1v15 encrypts the given message with RSA and the padding scheme from PKCS#1 v1.5.
 | 
				
			||||||
 | 
					// The message must be no longer than the length of the public modulus minus 11 bytes.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The rand parameter is used as a source of entropy to ensure that encrypting
 | 
				
			||||||
 | 
					// the same message twice doesn't result in the same ciphertext.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// WARNING: use of this function to encrypt plaintexts other than session keys
 | 
				
			||||||
 | 
					// is dangerous. Use RSA OAEP in new protocols.
 | 
				
			||||||
 | 
					func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, err error) {
 | 
				
			||||||
 | 
						if err := checkPub(pub); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						k := (pub.N.BitLen() + 7) / 8
 | 
				
			||||||
 | 
						if len(msg) > k-11 {
 | 
				
			||||||
 | 
							err = ErrMessageTooLong
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// EM = 0x00 || 0x02 || PS || 0x00 || M
 | 
				
			||||||
 | 
						em := make([]byte, k)
 | 
				
			||||||
 | 
						em[1] = 2
 | 
				
			||||||
 | 
						ps, mm := em[2:len(em)-len(msg)-1], em[len(em)-len(msg):]
 | 
				
			||||||
 | 
						err = nonZeroRandomBytes(ps, rand)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						em[len(em)-len(msg)-1] = 0
 | 
				
			||||||
 | 
						copy(mm, msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m := new(big.Int).SetBytes(em)
 | 
				
			||||||
 | 
						c := encrypt(new(big.Int), pub, m)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						copyWithLeftPad(em, c.Bytes())
 | 
				
			||||||
 | 
						out = em
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
 | 
				
			||||||
 | 
					// If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Note that whether this function returns an error or not discloses secret
 | 
				
			||||||
 | 
					// information. If an attacker can cause this function to run repeatedly and
 | 
				
			||||||
 | 
					// learn whether each instance returned an error then they can decrypt and
 | 
				
			||||||
 | 
					// forge signatures as if they had the private key. See
 | 
				
			||||||
 | 
					// DecryptPKCS1v15SessionKey for a way of solving this problem.
 | 
				
			||||||
 | 
					func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err error) {
 | 
				
			||||||
 | 
						if err := checkPub(&priv.PublicKey); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						valid, out, index, err := decryptPKCS1v15(rand, priv, ciphertext)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if valid == 0 {
 | 
				
			||||||
 | 
							return nil, ErrDecryption
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out = out[index:]
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DecryptPKCS1v15SessionKey decrypts a session key using RSA and the padding scheme from PKCS#1 v1.5.
 | 
				
			||||||
 | 
					// If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
 | 
				
			||||||
 | 
					// It returns an error if the ciphertext is the wrong length or if the
 | 
				
			||||||
 | 
					// ciphertext is greater than the public modulus. Otherwise, no error is
 | 
				
			||||||
 | 
					// returned. If the padding is valid, the resulting plaintext message is copied
 | 
				
			||||||
 | 
					// into key. Otherwise, key is unchanged. These alternatives occur in constant
 | 
				
			||||||
 | 
					// time. It is intended that the user of this function generate a random
 | 
				
			||||||
 | 
					// session key beforehand and continue the protocol with the resulting value.
 | 
				
			||||||
 | 
					// This will remove any possibility that an attacker can learn any information
 | 
				
			||||||
 | 
					// about the plaintext.
 | 
				
			||||||
 | 
					// See ``Chosen Ciphertext Attacks Against Protocols Based on the RSA
 | 
				
			||||||
 | 
					// Encryption Standard PKCS #1'', Daniel Bleichenbacher, Advances in Cryptology
 | 
				
			||||||
 | 
					// (Crypto '98).
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Note that if the session key is too small then it may be possible for an
 | 
				
			||||||
 | 
					// attacker to brute-force it. If they can do that then they can learn whether
 | 
				
			||||||
 | 
					// a random value was used (because it'll be different for the same ciphertext)
 | 
				
			||||||
 | 
					// and thus whether the padding was correct. This defeats the point of this
 | 
				
			||||||
 | 
					// function. Using at least a 16-byte key will protect against this attack.
 | 
				
			||||||
 | 
					func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err error) {
 | 
				
			||||||
 | 
						if err := checkPub(&priv.PublicKey); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						k := (priv.N.BitLen() + 7) / 8
 | 
				
			||||||
 | 
						if k-(len(key)+3+8) < 0 {
 | 
				
			||||||
 | 
							return ErrDecryption
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						valid, em, index, err := decryptPKCS1v15(rand, priv, ciphertext)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(em) != k {
 | 
				
			||||||
 | 
							// This should be impossible because decryptPKCS1v15 always
 | 
				
			||||||
 | 
							// returns the full slice.
 | 
				
			||||||
 | 
							return ErrDecryption
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						valid &= subtle.ConstantTimeEq(int32(len(em)-index), int32(len(key)))
 | 
				
			||||||
 | 
						subtle.ConstantTimeCopy(valid, key, em[len(em)-len(key):])
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// decryptPKCS1v15 decrypts ciphertext using priv and blinds the operation if
 | 
				
			||||||
 | 
					// rand is not nil. It returns one or zero in valid that indicates whether the
 | 
				
			||||||
 | 
					// plaintext was correctly structured. In either case, the plaintext is
 | 
				
			||||||
 | 
					// returned in em so that it may be read independently of whether it was valid
 | 
				
			||||||
 | 
					// in order to maintain constant memory access patterns. If the plaintext was
 | 
				
			||||||
 | 
					// valid then index contains the index of the original message in em.
 | 
				
			||||||
 | 
					func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) {
 | 
				
			||||||
 | 
						k := (priv.N.BitLen() + 7) / 8
 | 
				
			||||||
 | 
						if k < 11 {
 | 
				
			||||||
 | 
							err = ErrDecryption
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c := new(big.Int).SetBytes(ciphertext)
 | 
				
			||||||
 | 
						m, err := decrypt(rand, priv, c)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						em = leftPad(m.Bytes(), k)
 | 
				
			||||||
 | 
						firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
 | 
				
			||||||
 | 
						secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 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.
 | 
				
			||||||
 | 
						lookingForIndex := 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 2; i < len(em); i++ {
 | 
				
			||||||
 | 
							equals0 := subtle.ConstantTimeByteEq(em[i], 0)
 | 
				
			||||||
 | 
							index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
 | 
				
			||||||
 | 
							lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The PS padding must be at least 8 bytes long, and it starts two
 | 
				
			||||||
 | 
						// bytes into em.
 | 
				
			||||||
 | 
						validPS := subtle.ConstantTimeLessOrEq(2+8, index)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						valid = firstByteIsZero & secondByteIsTwo & (^lookingForIndex & 1) & validPS
 | 
				
			||||||
 | 
						index = subtle.ConstantTimeSelect(valid, index+1, 0)
 | 
				
			||||||
 | 
						return valid, em, index, 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
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								// In tests, the PRNG may return all zeros so we do
 | 
				
			||||||
 | 
								// this to break the loop.
 | 
				
			||||||
 | 
								s[i] ^= 0x42
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// These are ASN1 DER structures:
 | 
				
			||||||
 | 
					//   DigestInfo ::= SEQUENCE {
 | 
				
			||||||
 | 
					//     digestAlgorithm AlgorithmIdentifier,
 | 
				
			||||||
 | 
					//     digest OCTET STRING
 | 
				
			||||||
 | 
					//   }
 | 
				
			||||||
 | 
					// For performance, we don't use the generic ASN1 encoder. Rather, we
 | 
				
			||||||
 | 
					// precompute a prefix of the digest value that makes a valid ASN1 DER string
 | 
				
			||||||
 | 
					// with the correct contents.
 | 
				
			||||||
 | 
					var hashPrefixes = map[crypto.Hash][]byte{
 | 
				
			||||||
 | 
						crypto.MD5:       {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
 | 
				
			||||||
 | 
						crypto.SHA1:      {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
 | 
				
			||||||
 | 
						crypto.SHA224:    {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c},
 | 
				
			||||||
 | 
						crypto.SHA256:    {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
 | 
				
			||||||
 | 
						crypto.SHA384:    {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
 | 
				
			||||||
 | 
						crypto.SHA512:    {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
 | 
				
			||||||
 | 
						crypto.MD5SHA1:   {}, // A special TLS case which doesn't use an ASN1 prefix.
 | 
				
			||||||
 | 
						crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SignPKCS1v15 calculates the signature of hashed using RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5.
 | 
				
			||||||
 | 
					// Note that hashed must be the result of hashing the input message using the
 | 
				
			||||||
 | 
					// given hash function. If hash is zero, hashed is signed directly. This isn't
 | 
				
			||||||
 | 
					// advisable except for interoperability.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// If rand is not nil then RSA blinding will be used to avoid timing side-channel attacks.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This function is deterministic. Thus, if the set of possible messages is
 | 
				
			||||||
 | 
					// small, an attacker may be able to build a map from messages to signatures
 | 
				
			||||||
 | 
					// and identify the signed messages. As ever, signatures provide authenticity,
 | 
				
			||||||
 | 
					// not confidentiality.
 | 
				
			||||||
 | 
					func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) (s []byte, err error) {
 | 
				
			||||||
 | 
						hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tLen := len(prefix) + hashLen
 | 
				
			||||||
 | 
						k := (priv.N.BitLen() + 7) / 8
 | 
				
			||||||
 | 
						if k < tLen+11 {
 | 
				
			||||||
 | 
							return nil, ErrMessageTooLong
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// EM = 0x00 || 0x01 || PS || 0x00 || T
 | 
				
			||||||
 | 
						em := make([]byte, k)
 | 
				
			||||||
 | 
						em[1] = 1
 | 
				
			||||||
 | 
						for i := 2; i < k-tLen-1; i++ {
 | 
				
			||||||
 | 
							em[i] = 0xff
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						copy(em[k-tLen:k-hashLen], prefix)
 | 
				
			||||||
 | 
						copy(em[k-hashLen:k], hashed)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m := new(big.Int).SetBytes(em)
 | 
				
			||||||
 | 
						c, err := decryptAndCheck(rand, priv, m)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						copyWithLeftPad(em, c.Bytes())
 | 
				
			||||||
 | 
						s = em
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// VerifyPKCS1v15 verifies an RSA PKCS#1 v1.5 signature.
 | 
				
			||||||
 | 
					// hashed is the result of hashing the input message using the given hash
 | 
				
			||||||
 | 
					// function and sig is the signature. A valid signature is indicated by
 | 
				
			||||||
 | 
					// returning a nil error. If hash is zero then hashed is used directly. This
 | 
				
			||||||
 | 
					// isn't advisable except for interoperability.
 | 
				
			||||||
 | 
					func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) (err error) {
 | 
				
			||||||
 | 
						hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tLen := len(prefix) + hashLen
 | 
				
			||||||
 | 
						k := (pub.N.BitLen() + 7) / 8
 | 
				
			||||||
 | 
						if k < tLen+11 {
 | 
				
			||||||
 | 
							err = ErrVerification
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c := new(big.Int).SetBytes(sig)
 | 
				
			||||||
 | 
						m := encrypt(new(big.Int), pub, c)
 | 
				
			||||||
 | 
						em := leftPad(m.Bytes(), k)
 | 
				
			||||||
 | 
						// EM = 0x00 || 0x01 || PS || 0x00 || T
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ok := subtle.ConstantTimeByteEq(em[0], 0)
 | 
				
			||||||
 | 
						ok &= subtle.ConstantTimeByteEq(em[1], 1)
 | 
				
			||||||
 | 
						ok &= subtle.ConstantTimeCompare(em[k-hashLen:k], hashed)
 | 
				
			||||||
 | 
						ok &= subtle.ConstantTimeCompare(em[k-tLen:k-hashLen], prefix)
 | 
				
			||||||
 | 
						ok &= subtle.ConstantTimeByteEq(em[k-tLen-1], 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 2; i < k-tLen-1; i++ {
 | 
				
			||||||
 | 
							ok &= subtle.ConstantTimeByteEq(em[i], 0xff)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ok != 1 {
 | 
				
			||||||
 | 
							return ErrVerification
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) {
 | 
				
			||||||
 | 
						// Special case: crypto.Hash(0) is used to indicate that the data is
 | 
				
			||||||
 | 
						// signed directly.
 | 
				
			||||||
 | 
						if hash == 0 {
 | 
				
			||||||
 | 
							return inLen, nil, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hashLen = hash.Size()
 | 
				
			||||||
 | 
						if inLen != hashLen {
 | 
				
			||||||
 | 
							return 0, nil, errors.New("crypto/rsa: input must be hashed message")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						prefix, ok := hashPrefixes[hash]
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return 0, nil, errors.New("crypto/rsa: unsupported hash function")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// copyWithLeftPad copies src to the end of dest, padding with zero bytes as
 | 
				
			||||||
 | 
					// needed.
 | 
				
			||||||
 | 
					func copyWithLeftPad(dest, src []byte) {
 | 
				
			||||||
 | 
						numPaddingBytes := len(dest) - len(src)
 | 
				
			||||||
 | 
						for i := 0; i < numPaddingBytes; i++ {
 | 
				
			||||||
 | 
							dest[i] = 0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						copy(dest[numPaddingBytes:], src)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										297
									
								
								vendor/github.com/keybase/go-crypto/rsa/pss.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										297
									
								
								vendor/github.com/keybase/go-crypto/rsa/pss.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,297 @@
 | 
				
			|||||||
 | 
					// 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 rsa
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This file implements the PSS signature scheme [1].
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// [1] http://www.rsa.com/rsalabs/pkcs/files/h11300-wp-pkcs-1v2-2-rsa-cryptography-standard.pdf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"crypto"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"hash"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byte, error) {
 | 
				
			||||||
 | 
						// See [1], section 9.1.1
 | 
				
			||||||
 | 
						hLen := hash.Size()
 | 
				
			||||||
 | 
						sLen := len(salt)
 | 
				
			||||||
 | 
						emLen := (emBits + 7) / 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 1.  If the length of M is greater than the input limitation for the
 | 
				
			||||||
 | 
						//     hash function (2^61 - 1 octets for SHA-1), output "message too
 | 
				
			||||||
 | 
						//     long" and stop.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// 2.  Let mHash = Hash(M), an octet string of length hLen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(mHash) != hLen {
 | 
				
			||||||
 | 
							return nil, errors.New("crypto/rsa: input must be hashed message")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 3.  If emLen < hLen + sLen + 2, output "encoding error" and stop.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if emLen < hLen+sLen+2 {
 | 
				
			||||||
 | 
							return nil, errors.New("crypto/rsa: encoding error")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						em := make([]byte, emLen)
 | 
				
			||||||
 | 
						db := em[:emLen-sLen-hLen-2+1+sLen]
 | 
				
			||||||
 | 
						h := em[emLen-sLen-hLen-2+1+sLen : emLen-1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 4.  Generate a random octet string salt of length sLen; if sLen = 0,
 | 
				
			||||||
 | 
						//     then salt is the empty string.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// 5.  Let
 | 
				
			||||||
 | 
						//       M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt;
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						//     M' is an octet string of length 8 + hLen + sLen with eight
 | 
				
			||||||
 | 
						//     initial zero octets.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// 6.  Let H = Hash(M'), an octet string of length hLen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var prefix [8]byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hash.Write(prefix[:])
 | 
				
			||||||
 | 
						hash.Write(mHash)
 | 
				
			||||||
 | 
						hash.Write(salt)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						h = hash.Sum(h[:0])
 | 
				
			||||||
 | 
						hash.Reset()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 7.  Generate an octet string PS consisting of emLen - sLen - hLen - 2
 | 
				
			||||||
 | 
						//     zero octets.  The length of PS may be 0.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// 8.  Let DB = PS || 0x01 || salt; DB is an octet string of length
 | 
				
			||||||
 | 
						//     emLen - hLen - 1.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						db[emLen-sLen-hLen-2] = 0x01
 | 
				
			||||||
 | 
						copy(db[emLen-sLen-hLen-1:], salt)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 9.  Let dbMask = MGF(H, emLen - hLen - 1).
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// 10. Let maskedDB = DB \xor dbMask.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mgf1XOR(db, hash, h)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 11. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in
 | 
				
			||||||
 | 
						//     maskedDB to zero.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						db[0] &= (0xFF >> uint(8*emLen-emBits))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 12. Let EM = maskedDB || H || 0xbc.
 | 
				
			||||||
 | 
						em[emLen-1] = 0xBC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 13. Output EM.
 | 
				
			||||||
 | 
						return em, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
 | 
				
			||||||
 | 
						// 1.  If the length of M is greater than the input limitation for the
 | 
				
			||||||
 | 
						//     hash function (2^61 - 1 octets for SHA-1), output "inconsistent"
 | 
				
			||||||
 | 
						//     and stop.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// 2.  Let mHash = Hash(M), an octet string of length hLen.
 | 
				
			||||||
 | 
						hLen := hash.Size()
 | 
				
			||||||
 | 
						if hLen != len(mHash) {
 | 
				
			||||||
 | 
							return ErrVerification
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 3.  If emLen < hLen + sLen + 2, output "inconsistent" and stop.
 | 
				
			||||||
 | 
						emLen := (emBits + 7) / 8
 | 
				
			||||||
 | 
						if emLen < hLen+sLen+2 {
 | 
				
			||||||
 | 
							return ErrVerification
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 4.  If the rightmost octet of EM does not have hexadecimal value
 | 
				
			||||||
 | 
						//     0xbc, output "inconsistent" and stop.
 | 
				
			||||||
 | 
						if em[len(em)-1] != 0xBC {
 | 
				
			||||||
 | 
							return ErrVerification
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 5.  Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and
 | 
				
			||||||
 | 
						//     let H be the next hLen octets.
 | 
				
			||||||
 | 
						db := em[:emLen-hLen-1]
 | 
				
			||||||
 | 
						h := em[emLen-hLen-1 : len(em)-1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 6.  If the leftmost 8 * emLen - emBits bits of the leftmost octet in
 | 
				
			||||||
 | 
						//     maskedDB are not all equal to zero, output "inconsistent" and
 | 
				
			||||||
 | 
						//     stop.
 | 
				
			||||||
 | 
						if em[0]&(0xFF<<uint(8-(8*emLen-emBits))) != 0 {
 | 
				
			||||||
 | 
							return ErrVerification
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 7.  Let dbMask = MGF(H, emLen - hLen - 1).
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// 8.  Let DB = maskedDB \xor dbMask.
 | 
				
			||||||
 | 
						mgf1XOR(db, hash, h)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 9.  Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB
 | 
				
			||||||
 | 
						//     to zero.
 | 
				
			||||||
 | 
						db[0] &= (0xFF >> uint(8*emLen-emBits))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if sLen == PSSSaltLengthAuto {
 | 
				
			||||||
 | 
						FindSaltLength:
 | 
				
			||||||
 | 
							for sLen = emLen - (hLen + 2); sLen >= 0; sLen-- {
 | 
				
			||||||
 | 
								switch db[emLen-hLen-sLen-2] {
 | 
				
			||||||
 | 
								case 1:
 | 
				
			||||||
 | 
									break FindSaltLength
 | 
				
			||||||
 | 
								case 0:
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									return ErrVerification
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if sLen < 0 {
 | 
				
			||||||
 | 
								return ErrVerification
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							// 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero
 | 
				
			||||||
 | 
							//     or if the octet at position emLen - hLen - sLen - 1 (the leftmost
 | 
				
			||||||
 | 
							//     position is "position 1") does not have hexadecimal value 0x01,
 | 
				
			||||||
 | 
							//     output "inconsistent" and stop.
 | 
				
			||||||
 | 
							for _, e := range db[:emLen-hLen-sLen-2] {
 | 
				
			||||||
 | 
								if e != 0x00 {
 | 
				
			||||||
 | 
									return ErrVerification
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if db[emLen-hLen-sLen-2] != 0x01 {
 | 
				
			||||||
 | 
								return ErrVerification
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 11.  Let salt be the last sLen octets of DB.
 | 
				
			||||||
 | 
						salt := db[len(db)-sLen:]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 12.  Let
 | 
				
			||||||
 | 
						//          M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt ;
 | 
				
			||||||
 | 
						//     M' is an octet string of length 8 + hLen + sLen with eight
 | 
				
			||||||
 | 
						//     initial zero octets.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// 13. Let H' = Hash(M'), an octet string of length hLen.
 | 
				
			||||||
 | 
						var prefix [8]byte
 | 
				
			||||||
 | 
						hash.Write(prefix[:])
 | 
				
			||||||
 | 
						hash.Write(mHash)
 | 
				
			||||||
 | 
						hash.Write(salt)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						h0 := hash.Sum(nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 14. If H = H', output "consistent." Otherwise, output "inconsistent."
 | 
				
			||||||
 | 
						if !bytes.Equal(h0, h) {
 | 
				
			||||||
 | 
							return ErrVerification
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// signPSSWithSalt calculates the signature of hashed using PSS [1] with specified salt.
 | 
				
			||||||
 | 
					// Note that hashed must be the result of hashing the input message using the
 | 
				
			||||||
 | 
					// given hash function. salt is a random sequence of bytes whose length will be
 | 
				
			||||||
 | 
					// later used to verify the signature.
 | 
				
			||||||
 | 
					func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) (s []byte, err error) {
 | 
				
			||||||
 | 
						nBits := priv.N.BitLen()
 | 
				
			||||||
 | 
						em, err := emsaPSSEncode(hashed, nBits-1, salt, hash.New())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m := new(big.Int).SetBytes(em)
 | 
				
			||||||
 | 
						c, err := decryptAndCheck(rand, priv, m)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						s = make([]byte, (nBits+7)/8)
 | 
				
			||||||
 | 
						copyWithLeftPad(s, c.Bytes())
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						// PSSSaltLengthAuto causes the salt in a PSS signature to be as large
 | 
				
			||||||
 | 
						// as possible when signing, and to be auto-detected when verifying.
 | 
				
			||||||
 | 
						PSSSaltLengthAuto = 0
 | 
				
			||||||
 | 
						// PSSSaltLengthEqualsHash causes the salt length to equal the length
 | 
				
			||||||
 | 
						// of the hash used in the signature.
 | 
				
			||||||
 | 
						PSSSaltLengthEqualsHash = -1
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PSSOptions contains options for creating and verifying PSS signatures.
 | 
				
			||||||
 | 
					type PSSOptions struct {
 | 
				
			||||||
 | 
						// SaltLength controls the length of the salt used in the PSS
 | 
				
			||||||
 | 
						// signature. It can either be a number of bytes, or one of the special
 | 
				
			||||||
 | 
						// PSSSaltLength constants.
 | 
				
			||||||
 | 
						SaltLength int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Hash, if not zero, overrides the hash function passed to SignPSS.
 | 
				
			||||||
 | 
						// This is the only way to specify the hash function when using the
 | 
				
			||||||
 | 
						// crypto.Signer interface.
 | 
				
			||||||
 | 
						Hash crypto.Hash
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// HashFunc returns pssOpts.Hash so that PSSOptions implements
 | 
				
			||||||
 | 
					// crypto.SignerOpts.
 | 
				
			||||||
 | 
					func (pssOpts *PSSOptions) HashFunc() crypto.Hash {
 | 
				
			||||||
 | 
						return pssOpts.Hash
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (opts *PSSOptions) saltLength() int {
 | 
				
			||||||
 | 
						if opts == nil {
 | 
				
			||||||
 | 
							return PSSSaltLengthAuto
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return opts.SaltLength
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SignPSS calculates the signature of hashed using RSASSA-PSS [1].
 | 
				
			||||||
 | 
					// Note that hashed must be the result of hashing the input message using the
 | 
				
			||||||
 | 
					// given hash function. The opts argument may be nil, in which case sensible
 | 
				
			||||||
 | 
					// defaults are used.
 | 
				
			||||||
 | 
					func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, opts *PSSOptions) (s []byte, err error) {
 | 
				
			||||||
 | 
						saltLength := opts.saltLength()
 | 
				
			||||||
 | 
						switch saltLength {
 | 
				
			||||||
 | 
						case PSSSaltLengthAuto:
 | 
				
			||||||
 | 
							saltLength = (priv.N.BitLen()+7)/8 - 2 - hash.Size()
 | 
				
			||||||
 | 
						case PSSSaltLengthEqualsHash:
 | 
				
			||||||
 | 
							saltLength = hash.Size()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if opts != nil && opts.Hash != 0 {
 | 
				
			||||||
 | 
							hash = opts.Hash
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						salt := make([]byte, saltLength)
 | 
				
			||||||
 | 
						if _, err = io.ReadFull(rand, salt); err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return signPSSWithSalt(rand, priv, hash, hashed, salt)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// VerifyPSS verifies a PSS signature.
 | 
				
			||||||
 | 
					// hashed is the result of hashing the input message using the given hash
 | 
				
			||||||
 | 
					// function and sig is the signature. A valid signature is indicated by
 | 
				
			||||||
 | 
					// returning a nil error. The opts argument may be nil, in which case sensible
 | 
				
			||||||
 | 
					// defaults are used.
 | 
				
			||||||
 | 
					func VerifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, opts *PSSOptions) error {
 | 
				
			||||||
 | 
						return verifyPSS(pub, hash, hashed, sig, opts.saltLength())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// verifyPSS verifies a PSS signature with the given salt length.
 | 
				
			||||||
 | 
					func verifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, saltLen int) error {
 | 
				
			||||||
 | 
						nBits := pub.N.BitLen()
 | 
				
			||||||
 | 
						if len(sig) != (nBits+7)/8 {
 | 
				
			||||||
 | 
							return ErrVerification
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						s := new(big.Int).SetBytes(sig)
 | 
				
			||||||
 | 
						m := encrypt(new(big.Int), pub, s)
 | 
				
			||||||
 | 
						emBits := nBits - 1
 | 
				
			||||||
 | 
						emLen := (emBits + 7) / 8
 | 
				
			||||||
 | 
						if emLen < len(m.Bytes()) {
 | 
				
			||||||
 | 
							return ErrVerification
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						em := make([]byte, emLen)
 | 
				
			||||||
 | 
						copyWithLeftPad(em, m.Bytes())
 | 
				
			||||||
 | 
						if saltLen == PSSSaltLengthEqualsHash {
 | 
				
			||||||
 | 
							saltLen = hash.Size()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return emsaPSSVerify(hashed, em, emBits, saltLen, hash.New())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										646
									
								
								vendor/github.com/keybase/go-crypto/rsa/rsa.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										646
									
								
								vendor/github.com/keybase/go-crypto/rsa/rsa.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,646 @@
 | 
				
			|||||||
 | 
					// 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 rsa implements RSA encryption as specified in PKCS#1.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// RSA is a single, fundamental operation that is used in this package to
 | 
				
			||||||
 | 
					// implement either public-key encryption or public-key signatures.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The original specification for encryption and signatures with RSA is PKCS#1
 | 
				
			||||||
 | 
					// and the terms "RSA encryption" and "RSA signatures" by default refer to
 | 
				
			||||||
 | 
					// PKCS#1 version 1.5. However, that specification has flaws and new designs
 | 
				
			||||||
 | 
					// should use version two, usually called by just OAEP and PSS, where
 | 
				
			||||||
 | 
					// possible.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Two sets of interfaces are included in this package. When a more abstract
 | 
				
			||||||
 | 
					// interface isn't neccessary, there are functions for encrypting/decrypting
 | 
				
			||||||
 | 
					// with v1.5/OAEP and signing/verifying with v1.5/PSS. If one needs to abstract
 | 
				
			||||||
 | 
					// over the public-key primitive, the PrivateKey struct implements the
 | 
				
			||||||
 | 
					// Decrypter and Signer interfaces from the crypto package.
 | 
				
			||||||
 | 
					package rsa
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"crypto"
 | 
				
			||||||
 | 
						"crypto/rand"
 | 
				
			||||||
 | 
						"crypto/subtle"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"hash"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var bigZero = big.NewInt(0)
 | 
				
			||||||
 | 
					var bigOne = big.NewInt(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A PublicKey represents the public part of an RSA key.
 | 
				
			||||||
 | 
					type PublicKey struct {
 | 
				
			||||||
 | 
						N *big.Int // modulus
 | 
				
			||||||
 | 
						E int64    // public exponent
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// OAEPOptions is an interface for passing options to OAEP decryption using the
 | 
				
			||||||
 | 
					// crypto.Decrypter interface.
 | 
				
			||||||
 | 
					type OAEPOptions struct {
 | 
				
			||||||
 | 
						// Hash is the hash function that will be used when generating the mask.
 | 
				
			||||||
 | 
						Hash crypto.Hash
 | 
				
			||||||
 | 
						// Label is an arbitrary byte string that must be equal to the value
 | 
				
			||||||
 | 
						// used when encrypting.
 | 
				
			||||||
 | 
						Label []byte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						errPublicModulus       = errors.New("crypto/rsa: missing public modulus")
 | 
				
			||||||
 | 
						errPublicExponentSmall = errors.New("crypto/rsa: public exponent too small")
 | 
				
			||||||
 | 
						errPublicExponentLarge = errors.New("crypto/rsa: public exponent too large")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// checkPub sanity checks the public key before we use it.
 | 
				
			||||||
 | 
					// We require pub.E to fit into a 32-bit integer so that we
 | 
				
			||||||
 | 
					// do not have different behavior depending on whether
 | 
				
			||||||
 | 
					// int is 32 or 64 bits. See also
 | 
				
			||||||
 | 
					// http://www.imperialviolet.org/2012/03/16/rsae.html.
 | 
				
			||||||
 | 
					func checkPub(pub *PublicKey) error {
 | 
				
			||||||
 | 
						if pub.N == nil {
 | 
				
			||||||
 | 
							return errPublicModulus
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if pub.E < 2 {
 | 
				
			||||||
 | 
							return errPublicExponentSmall
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if pub.E > 1<<63-1 {
 | 
				
			||||||
 | 
							return errPublicExponentLarge
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A PrivateKey represents an RSA key
 | 
				
			||||||
 | 
					type PrivateKey struct {
 | 
				
			||||||
 | 
						PublicKey            // public part.
 | 
				
			||||||
 | 
						D         *big.Int   // private exponent
 | 
				
			||||||
 | 
						Primes    []*big.Int // prime factors of N, has >= 2 elements.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Precomputed contains precomputed values that speed up private
 | 
				
			||||||
 | 
						// operations, if available.
 | 
				
			||||||
 | 
						Precomputed PrecomputedValues
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Public returns the public key corresponding to priv.
 | 
				
			||||||
 | 
					func (priv *PrivateKey) Public() crypto.PublicKey {
 | 
				
			||||||
 | 
						return &priv.PublicKey
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Sign signs msg with priv, reading randomness from rand. If opts is a
 | 
				
			||||||
 | 
					// *PSSOptions then the PSS algorithm will be used, otherwise PKCS#1 v1.5 will
 | 
				
			||||||
 | 
					// be used. This method is intended to support keys where the private part is
 | 
				
			||||||
 | 
					// kept in, for example, a hardware module. Common uses should use the Sign*
 | 
				
			||||||
 | 
					// functions in this package.
 | 
				
			||||||
 | 
					func (priv *PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
 | 
				
			||||||
 | 
						if pssOpts, ok := opts.(*PSSOptions); ok {
 | 
				
			||||||
 | 
							return SignPSS(rand, priv, pssOpts.Hash, msg, pssOpts)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SignPKCS1v15(rand, priv, opts.HashFunc(), msg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Decrypt decrypts ciphertext with priv. If opts is nil or of type
 | 
				
			||||||
 | 
					// *PKCS1v15DecryptOptions then PKCS#1 v1.5 decryption is performed. Otherwise
 | 
				
			||||||
 | 
					// opts must have type *OAEPOptions and OAEP decryption is done.
 | 
				
			||||||
 | 
					func (priv *PrivateKey) Decrypt(rand io.Reader, ciphertext []byte, opts crypto.DecrypterOpts) (plaintext []byte, err error) {
 | 
				
			||||||
 | 
						if opts == nil {
 | 
				
			||||||
 | 
							return DecryptPKCS1v15(rand, priv, ciphertext)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch opts := opts.(type) {
 | 
				
			||||||
 | 
						case *OAEPOptions:
 | 
				
			||||||
 | 
							return DecryptOAEP(opts.Hash.New(), rand, priv, ciphertext, opts.Label)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case *PKCS1v15DecryptOptions:
 | 
				
			||||||
 | 
							if l := opts.SessionKeyLen; l > 0 {
 | 
				
			||||||
 | 
								plaintext = make([]byte, l)
 | 
				
			||||||
 | 
								if _, err := io.ReadFull(rand, plaintext); err != nil {
 | 
				
			||||||
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if err := DecryptPKCS1v15SessionKey(rand, priv, ciphertext, plaintext); err != nil {
 | 
				
			||||||
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return plaintext, nil
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return DecryptPKCS1v15(rand, priv, ciphertext)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return nil, errors.New("crypto/rsa: invalid options for Decrypt")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PrecomputedValues struct {
 | 
				
			||||||
 | 
						Dp, Dq *big.Int // D mod (P-1) (or mod Q-1)
 | 
				
			||||||
 | 
						Qinv   *big.Int // Q^-1 mod P
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// CRTValues is used for the 3rd and subsequent primes. Due to a
 | 
				
			||||||
 | 
						// historical accident, the CRT for the first two primes is handled
 | 
				
			||||||
 | 
						// differently in PKCS#1 and interoperability is sufficiently
 | 
				
			||||||
 | 
						// important that we mirror this.
 | 
				
			||||||
 | 
						CRTValues []CRTValue
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CRTValue contains the precomputed Chinese remainder theorem values.
 | 
				
			||||||
 | 
					type CRTValue struct {
 | 
				
			||||||
 | 
						Exp   *big.Int // D mod (prime-1).
 | 
				
			||||||
 | 
						Coeff *big.Int // R·Coeff ≡ 1 mod Prime.
 | 
				
			||||||
 | 
						R     *big.Int // product of primes prior to this (inc p and q).
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Validate performs basic sanity checks on the key.
 | 
				
			||||||
 | 
					// It returns nil if the key is valid, or else an error describing a problem.
 | 
				
			||||||
 | 
					func (priv *PrivateKey) Validate() error {
 | 
				
			||||||
 | 
						if err := checkPub(&priv.PublicKey); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check that Πprimes == n.
 | 
				
			||||||
 | 
						modulus := new(big.Int).Set(bigOne)
 | 
				
			||||||
 | 
						for _, prime := range priv.Primes {
 | 
				
			||||||
 | 
							// Any primes ≤ 1 will cause divide-by-zero panics later.
 | 
				
			||||||
 | 
							if prime.Cmp(bigOne) <= 0 {
 | 
				
			||||||
 | 
								return errors.New("crypto/rsa: invalid prime value")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							modulus.Mul(modulus, prime)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if modulus.Cmp(priv.N) != 0 {
 | 
				
			||||||
 | 
							return errors.New("crypto/rsa: invalid modulus")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check that de ≡ 1 mod p-1, for each prime.
 | 
				
			||||||
 | 
						// This implies that e is coprime to each p-1 as e has a multiplicative
 | 
				
			||||||
 | 
						// inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) =
 | 
				
			||||||
 | 
						// exponent(ℤ/nℤ). It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1
 | 
				
			||||||
 | 
						// mod p. Thus a^de ≡ a mod n for all a coprime to n, as required.
 | 
				
			||||||
 | 
						congruence := new(big.Int)
 | 
				
			||||||
 | 
						de := new(big.Int).SetInt64(int64(priv.E))
 | 
				
			||||||
 | 
						de.Mul(de, priv.D)
 | 
				
			||||||
 | 
						for _, prime := range priv.Primes {
 | 
				
			||||||
 | 
							pminus1 := new(big.Int).Sub(prime, bigOne)
 | 
				
			||||||
 | 
							congruence.Mod(de, pminus1)
 | 
				
			||||||
 | 
							if congruence.Cmp(bigOne) != 0 {
 | 
				
			||||||
 | 
								return errors.New("crypto/rsa: invalid exponents")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GenerateKey generates an RSA keypair of the given bit size using the
 | 
				
			||||||
 | 
					// random source random (for example, crypto/rand.Reader).
 | 
				
			||||||
 | 
					func GenerateKey(random io.Reader, bits int) (priv *PrivateKey, err error) {
 | 
				
			||||||
 | 
						return GenerateMultiPrimeKey(random, 2, bits)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GenerateMultiPrimeKey generates a multi-prime RSA keypair of the given bit
 | 
				
			||||||
 | 
					// size and the given random source, as suggested in [1]. Although the public
 | 
				
			||||||
 | 
					// keys are compatible (actually, indistinguishable) from the 2-prime case,
 | 
				
			||||||
 | 
					// the private keys are not. Thus it may not be possible to export multi-prime
 | 
				
			||||||
 | 
					// private keys in certain formats or to subsequently import them into other
 | 
				
			||||||
 | 
					// code.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Table 1 in [2] suggests maximum numbers of primes for a given size.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// [1] US patent 4405829 (1972, expired)
 | 
				
			||||||
 | 
					// [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
 | 
				
			||||||
 | 
					func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (priv *PrivateKey, err error) {
 | 
				
			||||||
 | 
						priv = new(PrivateKey)
 | 
				
			||||||
 | 
						priv.E = 65537
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if nprimes < 2 {
 | 
				
			||||||
 | 
							return nil, errors.New("crypto/rsa: GenerateMultiPrimeKey: nprimes must be >= 2")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						primes := make([]*big.Int, nprimes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NextSetOfPrimes:
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							todo := bits
 | 
				
			||||||
 | 
							// crypto/rand should set the top two bits in each prime.
 | 
				
			||||||
 | 
							// Thus each prime has the form
 | 
				
			||||||
 | 
							//   p_i = 2^bitlen(p_i) × 0.11... (in base 2).
 | 
				
			||||||
 | 
							// And the product is:
 | 
				
			||||||
 | 
							//   P = 2^todo × α
 | 
				
			||||||
 | 
							// where α is the product of nprimes numbers of the form 0.11...
 | 
				
			||||||
 | 
							//
 | 
				
			||||||
 | 
							// If α < 1/2 (which can happen for nprimes > 2), we need to
 | 
				
			||||||
 | 
							// shift todo to compensate for lost bits: the mean value of 0.11...
 | 
				
			||||||
 | 
							// is 7/8, so todo + shift - nprimes * log2(7/8) ~= bits - 1/2
 | 
				
			||||||
 | 
							// will give good results.
 | 
				
			||||||
 | 
							if nprimes >= 7 {
 | 
				
			||||||
 | 
								todo += (nprimes - 2) / 5
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for i := 0; i < nprimes; i++ {
 | 
				
			||||||
 | 
								primes[i], err = rand.Prime(random, todo/(nprimes-i))
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								todo -= primes[i].BitLen()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Make sure that primes is pairwise unequal.
 | 
				
			||||||
 | 
							for i, prime := range primes {
 | 
				
			||||||
 | 
								for j := 0; j < i; j++ {
 | 
				
			||||||
 | 
									if prime.Cmp(primes[j]) == 0 {
 | 
				
			||||||
 | 
										continue NextSetOfPrimes
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							n := new(big.Int).Set(bigOne)
 | 
				
			||||||
 | 
							totient := new(big.Int).Set(bigOne)
 | 
				
			||||||
 | 
							pminus1 := new(big.Int)
 | 
				
			||||||
 | 
							for _, prime := range primes {
 | 
				
			||||||
 | 
								n.Mul(n, prime)
 | 
				
			||||||
 | 
								pminus1.Sub(prime, bigOne)
 | 
				
			||||||
 | 
								totient.Mul(totient, pminus1)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if n.BitLen() != bits {
 | 
				
			||||||
 | 
								// This should never happen for nprimes == 2 because
 | 
				
			||||||
 | 
								// crypto/rand should set the top two bits in each prime.
 | 
				
			||||||
 | 
								// For nprimes > 2 we hope it does not happen often.
 | 
				
			||||||
 | 
								continue NextSetOfPrimes
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							g := new(big.Int)
 | 
				
			||||||
 | 
							priv.D = new(big.Int)
 | 
				
			||||||
 | 
							y := new(big.Int)
 | 
				
			||||||
 | 
							e := big.NewInt(int64(priv.E))
 | 
				
			||||||
 | 
							g.GCD(priv.D, y, e, totient)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if g.Cmp(bigOne) == 0 {
 | 
				
			||||||
 | 
								if priv.D.Sign() < 0 {
 | 
				
			||||||
 | 
									priv.D.Add(priv.D, totient)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								priv.Primes = primes
 | 
				
			||||||
 | 
								priv.N = n
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv.Precompute()
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// incCounter increments a four byte, big-endian counter.
 | 
				
			||||||
 | 
					func incCounter(c *[4]byte) {
 | 
				
			||||||
 | 
						if c[3]++; c[3] != 0 {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if c[2]++; c[2] != 0 {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if c[1]++; c[1] != 0 {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c[0]++
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// mgf1XOR XORs the bytes in out with a mask generated using the MGF1 function
 | 
				
			||||||
 | 
					// specified in PKCS#1 v2.1.
 | 
				
			||||||
 | 
					func mgf1XOR(out []byte, hash hash.Hash, seed []byte) {
 | 
				
			||||||
 | 
						var counter [4]byte
 | 
				
			||||||
 | 
						var digest []byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						done := 0
 | 
				
			||||||
 | 
						for done < len(out) {
 | 
				
			||||||
 | 
							hash.Write(seed)
 | 
				
			||||||
 | 
							hash.Write(counter[0:4])
 | 
				
			||||||
 | 
							digest = hash.Sum(digest[:0])
 | 
				
			||||||
 | 
							hash.Reset()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for i := 0; i < len(digest) && done < len(out); i++ {
 | 
				
			||||||
 | 
								out[done] ^= digest[i]
 | 
				
			||||||
 | 
								done++
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							incCounter(&counter)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ErrMessageTooLong is returned when attempting to encrypt a message which is
 | 
				
			||||||
 | 
					// too large for the size of the public key.
 | 
				
			||||||
 | 
					var ErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA public key size")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
 | 
				
			||||||
 | 
						e := big.NewInt(int64(pub.E))
 | 
				
			||||||
 | 
						c.Exp(m, e, pub.N)
 | 
				
			||||||
 | 
						return c
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// EncryptOAEP encrypts the given message with RSA-OAEP.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// OAEP is parameterised by a hash function that is used as a random oracle.
 | 
				
			||||||
 | 
					// Encryption and decryption of a given message must use the same hash function
 | 
				
			||||||
 | 
					// and sha256.New() is a reasonable choice.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The random parameter is used as a source of entropy to ensure that
 | 
				
			||||||
 | 
					// encrypting the same message twice doesn't result in the same ciphertext.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The label parameter may contain arbitrary data that will not be encrypted,
 | 
				
			||||||
 | 
					// but which gives important context to the message. For example, if a given
 | 
				
			||||||
 | 
					// public key is used to decrypt two types of messages then distinct label
 | 
				
			||||||
 | 
					// values could be used to ensure that a ciphertext for one purpose cannot be
 | 
				
			||||||
 | 
					// used for another by an attacker. If not required it can be empty.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The message must be no longer than the length of the public modulus less
 | 
				
			||||||
 | 
					// twice the hash length plus 2.
 | 
				
			||||||
 | 
					func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) (out []byte, err error) {
 | 
				
			||||||
 | 
						if err := checkPub(pub); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						hash.Reset()
 | 
				
			||||||
 | 
						k := (pub.N.BitLen() + 7) / 8
 | 
				
			||||||
 | 
						if len(msg) > k-2*hash.Size()-2 {
 | 
				
			||||||
 | 
							err = ErrMessageTooLong
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hash.Write(label)
 | 
				
			||||||
 | 
						lHash := hash.Sum(nil)
 | 
				
			||||||
 | 
						hash.Reset()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						em := make([]byte, k)
 | 
				
			||||||
 | 
						seed := em[1 : 1+hash.Size()]
 | 
				
			||||||
 | 
						db := em[1+hash.Size():]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						copy(db[0:hash.Size()], lHash)
 | 
				
			||||||
 | 
						db[len(db)-len(msg)-1] = 1
 | 
				
			||||||
 | 
						copy(db[len(db)-len(msg):], msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err = io.ReadFull(random, seed)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mgf1XOR(db, hash, seed)
 | 
				
			||||||
 | 
						mgf1XOR(seed, hash, db)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m := new(big.Int)
 | 
				
			||||||
 | 
						m.SetBytes(em)
 | 
				
			||||||
 | 
						c := encrypt(new(big.Int), pub, m)
 | 
				
			||||||
 | 
						out = c.Bytes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(out) < k {
 | 
				
			||||||
 | 
							// If the output is too small, we need to left-pad with zeros.
 | 
				
			||||||
 | 
							t := make([]byte, k)
 | 
				
			||||||
 | 
							copy(t[k-len(out):], out)
 | 
				
			||||||
 | 
							out = t
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ErrDecryption represents a failure to decrypt a message.
 | 
				
			||||||
 | 
					// It is deliberately vague to avoid adaptive attacks.
 | 
				
			||||||
 | 
					var ErrDecryption = errors.New("crypto/rsa: decryption error")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ErrVerification represents a failure to verify a signature.
 | 
				
			||||||
 | 
					// It is deliberately vague to avoid adaptive attacks.
 | 
				
			||||||
 | 
					var ErrVerification = errors.New("crypto/rsa: verification error")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// modInverse returns ia, the inverse of a in the multiplicative group of prime
 | 
				
			||||||
 | 
					// order n. It requires that a be a member of the group (i.e. less than n).
 | 
				
			||||||
 | 
					func modInverse(a, n *big.Int) (ia *big.Int, ok bool) {
 | 
				
			||||||
 | 
						g := new(big.Int)
 | 
				
			||||||
 | 
						x := new(big.Int)
 | 
				
			||||||
 | 
						y := new(big.Int)
 | 
				
			||||||
 | 
						g.GCD(x, y, a, n)
 | 
				
			||||||
 | 
						if g.Cmp(bigOne) != 0 {
 | 
				
			||||||
 | 
							// In this case, a and n aren't coprime and we cannot calculate
 | 
				
			||||||
 | 
							// the inverse. This happens because the values of n are nearly
 | 
				
			||||||
 | 
							// prime (being the product of two primes) rather than truly
 | 
				
			||||||
 | 
							// prime.
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if x.Cmp(bigOne) < 0 {
 | 
				
			||||||
 | 
							// 0 is not the multiplicative inverse of any element so, if x
 | 
				
			||||||
 | 
							// < 1, then x is negative.
 | 
				
			||||||
 | 
							x.Add(x, n)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return x, true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Precompute performs some calculations that speed up private key operations
 | 
				
			||||||
 | 
					// in the future.
 | 
				
			||||||
 | 
					func (priv *PrivateKey) Precompute() {
 | 
				
			||||||
 | 
						if priv.Precomputed.Dp != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv.Precomputed.Dp = new(big.Int).Sub(priv.Primes[0], bigOne)
 | 
				
			||||||
 | 
						priv.Precomputed.Dp.Mod(priv.D, priv.Precomputed.Dp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv.Precomputed.Dq = new(big.Int).Sub(priv.Primes[1], bigOne)
 | 
				
			||||||
 | 
						priv.Precomputed.Dq.Mod(priv.D, priv.Precomputed.Dq)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv.Precomputed.Qinv = new(big.Int).ModInverse(priv.Primes[1], priv.Primes[0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r := new(big.Int).Mul(priv.Primes[0], priv.Primes[1])
 | 
				
			||||||
 | 
						priv.Precomputed.CRTValues = make([]CRTValue, len(priv.Primes)-2)
 | 
				
			||||||
 | 
						for i := 2; i < len(priv.Primes); i++ {
 | 
				
			||||||
 | 
							prime := priv.Primes[i]
 | 
				
			||||||
 | 
							values := &priv.Precomputed.CRTValues[i-2]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							values.Exp = new(big.Int).Sub(prime, bigOne)
 | 
				
			||||||
 | 
							values.Exp.Mod(priv.D, values.Exp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							values.R = new(big.Int).Set(r)
 | 
				
			||||||
 | 
							values.Coeff = new(big.Int).ModInverse(r, prime)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							r.Mul(r, prime)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// decrypt performs an RSA decryption, resulting in a plaintext integer. If a
 | 
				
			||||||
 | 
					// random source is given, RSA blinding is used.
 | 
				
			||||||
 | 
					func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
 | 
				
			||||||
 | 
						// TODO(agl): can we get away with reusing blinds?
 | 
				
			||||||
 | 
						if c.Cmp(priv.N) > 0 {
 | 
				
			||||||
 | 
							err = ErrDecryption
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var ir *big.Int
 | 
				
			||||||
 | 
						if random != nil {
 | 
				
			||||||
 | 
							// Blinding enabled. Blinding involves multiplying c by r^e.
 | 
				
			||||||
 | 
							// Then the decryption operation performs (m^e * r^e)^d mod n
 | 
				
			||||||
 | 
							// which equals mr mod n. The factor of r can then be removed
 | 
				
			||||||
 | 
							// by multiplying by the multiplicative inverse of r.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var r *big.Int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								r, err = rand.Int(random, priv.N)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if r.Cmp(bigZero) == 0 {
 | 
				
			||||||
 | 
									r = bigOne
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var ok bool
 | 
				
			||||||
 | 
								ir, ok = modInverse(r, priv.N)
 | 
				
			||||||
 | 
								if ok {
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							bigE := big.NewInt(int64(priv.E))
 | 
				
			||||||
 | 
							rpowe := new(big.Int).Exp(r, bigE, priv.N)
 | 
				
			||||||
 | 
							cCopy := new(big.Int).Set(c)
 | 
				
			||||||
 | 
							cCopy.Mul(cCopy, rpowe)
 | 
				
			||||||
 | 
							cCopy.Mod(cCopy, priv.N)
 | 
				
			||||||
 | 
							c = cCopy
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if priv.Precomputed.Dp == nil {
 | 
				
			||||||
 | 
							m = new(big.Int).Exp(c, priv.D, priv.N)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							// We have the precalculated values needed for the CRT.
 | 
				
			||||||
 | 
							m = new(big.Int).Exp(c, priv.Precomputed.Dp, priv.Primes[0])
 | 
				
			||||||
 | 
							m2 := new(big.Int).Exp(c, priv.Precomputed.Dq, priv.Primes[1])
 | 
				
			||||||
 | 
							m.Sub(m, m2)
 | 
				
			||||||
 | 
							if m.Sign() < 0 {
 | 
				
			||||||
 | 
								m.Add(m, priv.Primes[0])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							m.Mul(m, priv.Precomputed.Qinv)
 | 
				
			||||||
 | 
							m.Mod(m, priv.Primes[0])
 | 
				
			||||||
 | 
							m.Mul(m, priv.Primes[1])
 | 
				
			||||||
 | 
							m.Add(m, m2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for i, values := range priv.Precomputed.CRTValues {
 | 
				
			||||||
 | 
								prime := priv.Primes[2+i]
 | 
				
			||||||
 | 
								m2.Exp(c, values.Exp, prime)
 | 
				
			||||||
 | 
								m2.Sub(m2, m)
 | 
				
			||||||
 | 
								m2.Mul(m2, values.Coeff)
 | 
				
			||||||
 | 
								m2.Mod(m2, prime)
 | 
				
			||||||
 | 
								if m2.Sign() < 0 {
 | 
				
			||||||
 | 
									m2.Add(m2, prime)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								m2.Mul(m2, values.R)
 | 
				
			||||||
 | 
								m.Add(m, m2)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ir != nil {
 | 
				
			||||||
 | 
							// Unblind.
 | 
				
			||||||
 | 
							m.Mul(m, ir)
 | 
				
			||||||
 | 
							m.Mod(m, priv.N)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func decryptAndCheck(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
 | 
				
			||||||
 | 
						m, err = decrypt(random, priv, c)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// In order to defend against errors in the CRT computation, m^e is
 | 
				
			||||||
 | 
						// calculated, which should match the original ciphertext.
 | 
				
			||||||
 | 
						check := encrypt(new(big.Int), &priv.PublicKey, m)
 | 
				
			||||||
 | 
						if c.Cmp(check) != 0 {
 | 
				
			||||||
 | 
							return nil, errors.New("rsa: internal error")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return m, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DecryptOAEP decrypts ciphertext using RSA-OAEP.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// OAEP is parameterised by a hash function that is used as a random oracle.
 | 
				
			||||||
 | 
					// Encryption and decryption of a given message must use the same hash function
 | 
				
			||||||
 | 
					// and sha256.New() is a reasonable choice.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The random parameter, if not nil, is used to blind the private-key operation
 | 
				
			||||||
 | 
					// and avoid timing side-channel attacks. Blinding is purely internal to this
 | 
				
			||||||
 | 
					// function – the random data need not match that used when encrypting.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The label parameter must match the value given when encrypting. See
 | 
				
			||||||
 | 
					// EncryptOAEP for details.
 | 
				
			||||||
 | 
					func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err error) {
 | 
				
			||||||
 | 
						if err := checkPub(&priv.PublicKey); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						k := (priv.N.BitLen() + 7) / 8
 | 
				
			||||||
 | 
						if len(ciphertext) > k ||
 | 
				
			||||||
 | 
							k < hash.Size()*2+2 {
 | 
				
			||||||
 | 
							err = ErrDecryption
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c := new(big.Int).SetBytes(ciphertext)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m, err := decrypt(random, priv, c)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hash.Write(label)
 | 
				
			||||||
 | 
						lHash := hash.Sum(nil)
 | 
				
			||||||
 | 
						hash.Reset()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Converting the plaintext number to bytes will strip any
 | 
				
			||||||
 | 
						// leading zeros so we may have to left pad. We do this unconditionally
 | 
				
			||||||
 | 
						// to avoid leaking timing information. (Although we still probably
 | 
				
			||||||
 | 
						// leak the number of leading zeros. It's not clear that we can do
 | 
				
			||||||
 | 
						// anything about this.)
 | 
				
			||||||
 | 
						em := leftPad(m.Bytes(), k)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						seed := em[1 : hash.Size()+1]
 | 
				
			||||||
 | 
						db := em[hash.Size()+1:]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mgf1XOR(seed, hash, db)
 | 
				
			||||||
 | 
						mgf1XOR(db, hash, seed)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lHash2 := db[0:hash.Size()]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We have to validate the plaintext in constant time in order to avoid
 | 
				
			||||||
 | 
						// attacks like: J. Manger. A Chosen Ciphertext Attack on RSA Optimal
 | 
				
			||||||
 | 
						// Asymmetric Encryption Padding (OAEP) as Standardized in PKCS #1
 | 
				
			||||||
 | 
						// v2.0. In J. Kilian, editor, Advances in Cryptology.
 | 
				
			||||||
 | 
						lHash2Good := subtle.ConstantTimeCompare(lHash, lHash2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The remainder of the plaintext must be zero or more 0x00, followed
 | 
				
			||||||
 | 
						// by 0x01, followed by the message.
 | 
				
			||||||
 | 
						//   lookingForIndex: 1 iff we are still looking for the 0x01
 | 
				
			||||||
 | 
						//   index: the offset of the first 0x01 byte
 | 
				
			||||||
 | 
						//   invalid: 1 iff we saw a non-zero byte before the 0x01.
 | 
				
			||||||
 | 
						var lookingForIndex, index, invalid int
 | 
				
			||||||
 | 
						lookingForIndex = 1
 | 
				
			||||||
 | 
						rest := db[hash.Size():]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < len(rest); i++ {
 | 
				
			||||||
 | 
							equals0 := subtle.ConstantTimeByteEq(rest[i], 0)
 | 
				
			||||||
 | 
							equals1 := subtle.ConstantTimeByteEq(rest[i], 1)
 | 
				
			||||||
 | 
							index = subtle.ConstantTimeSelect(lookingForIndex&equals1, i, index)
 | 
				
			||||||
 | 
							lookingForIndex = subtle.ConstantTimeSelect(equals1, 0, lookingForIndex)
 | 
				
			||||||
 | 
							invalid = subtle.ConstantTimeSelect(lookingForIndex&^equals0, 1, invalid)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if firstByteIsZero&lHash2Good&^invalid&^lookingForIndex != 1 {
 | 
				
			||||||
 | 
							err = ErrDecryption
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msg = rest[index+1:]
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// leftPad returns a new slice of length size. The contents of input are right
 | 
				
			||||||
 | 
					// aligned in the new slice.
 | 
				
			||||||
 | 
					func leftPad(input []byte, size int) (out []byte) {
 | 
				
			||||||
 | 
						n := len(input)
 | 
				
			||||||
 | 
						if n > size {
 | 
				
			||||||
 | 
							n = size
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out = make([]byte, size)
 | 
				
			||||||
 | 
						copy(out[len(out)-n:], input)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										637
									
								
								vendor/golang.org/x/crypto/openpgp/keys.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										637
									
								
								vendor/golang.org/x/crypto/openpgp/keys.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,637 +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
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 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,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// If the user passes in a DefaultHash via packet.Config,
 | 
					 | 
				
			||||||
	// set the PreferredHash for the SelfSignature.
 | 
					 | 
				
			||||||
	if config != nil && config.DefaultHash != 0 {
 | 
					 | 
				
			||||||
		e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										120
									
								
								vendor/vendor.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										120
									
								
								vendor/vendor.json
									
									
									
									
										vendored
									
									
								
							@@ -515,6 +515,84 @@
 | 
				
			|||||||
			"revision": "b2c7a7da5b2995941048f60146e67702a292e468",
 | 
								"revision": "b2c7a7da5b2995941048f60146e67702a292e468",
 | 
				
			||||||
			"revisionTime": "2016-02-12T04:00:40Z"
 | 
								"revisionTime": "2016-02-12T04:00:40Z"
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"checksumSHA1": "VJk3rOWfxEV9Ilig5lgzH1qg8Ss=",
 | 
				
			||||||
 | 
								"path": "github.com/keybase/go-crypto/brainpool",
 | 
				
			||||||
 | 
								"revision": "00ac4db533f63ef97576cbc7b07939ff7daf7329",
 | 
				
			||||||
 | 
								"revisionTime": "2017-06-05T14:56:57Z"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"checksumSHA1": "rnRjEJs5luF+DIXp2J6LFcQk8Gg=",
 | 
				
			||||||
 | 
								"path": "github.com/keybase/go-crypto/cast5",
 | 
				
			||||||
 | 
								"revision": "00ac4db533f63ef97576cbc7b07939ff7daf7329",
 | 
				
			||||||
 | 
								"revisionTime": "2017-06-05T14:56:57Z"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"checksumSHA1": "F5++ZQS5Vt7hd6lxPCKTffvph1A=",
 | 
				
			||||||
 | 
								"path": "github.com/keybase/go-crypto/curve25519",
 | 
				
			||||||
 | 
								"revision": "00ac4db533f63ef97576cbc7b07939ff7daf7329",
 | 
				
			||||||
 | 
								"revisionTime": "2017-06-05T14:56:57Z"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"checksumSHA1": "IvrDXwIixB5yPPbo6tq1/1cSn78=",
 | 
				
			||||||
 | 
								"path": "github.com/keybase/go-crypto/ed25519",
 | 
				
			||||||
 | 
								"revision": "00ac4db533f63ef97576cbc7b07939ff7daf7329",
 | 
				
			||||||
 | 
								"revisionTime": "2017-06-05T14:56:57Z"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"checksumSHA1": "4+fslB6pCbplNq4viy6CrOkkY6Y=",
 | 
				
			||||||
 | 
								"path": "github.com/keybase/go-crypto/ed25519/internal/edwards25519",
 | 
				
			||||||
 | 
								"revision": "00ac4db533f63ef97576cbc7b07939ff7daf7329",
 | 
				
			||||||
 | 
								"revisionTime": "2017-06-05T14:56:57Z"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"checksumSHA1": "fgFlkfkaotUjBVhJik2979oCeJw=",
 | 
				
			||||||
 | 
								"path": "github.com/keybase/go-crypto/openpgp",
 | 
				
			||||||
 | 
								"revision": "00ac4db533f63ef97576cbc7b07939ff7daf7329",
 | 
				
			||||||
 | 
								"revisionTime": "2017-06-05T14:56:57Z"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"checksumSHA1": "+spfcEChljh3yeIg4K/xHOQ2pVM=",
 | 
				
			||||||
 | 
								"path": "github.com/keybase/go-crypto/openpgp/armor",
 | 
				
			||||||
 | 
								"revision": "00ac4db533f63ef97576cbc7b07939ff7daf7329",
 | 
				
			||||||
 | 
								"revisionTime": "2017-06-05T14:56:57Z"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"checksumSHA1": "nWhmwjBJqPSvkCWqaap2Z9EiS1k=",
 | 
				
			||||||
 | 
								"path": "github.com/keybase/go-crypto/openpgp/ecdh",
 | 
				
			||||||
 | 
								"revision": "00ac4db533f63ef97576cbc7b07939ff7daf7329",
 | 
				
			||||||
 | 
								"revisionTime": "2017-06-05T14:56:57Z"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"checksumSHA1": "uxXG9IC/XF8jwwvZUbW65+x8/+M=",
 | 
				
			||||||
 | 
								"path": "github.com/keybase/go-crypto/openpgp/elgamal",
 | 
				
			||||||
 | 
								"revision": "00ac4db533f63ef97576cbc7b07939ff7daf7329",
 | 
				
			||||||
 | 
								"revisionTime": "2017-06-05T14:56:57Z"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"checksumSHA1": "EyUf82Yknzc75m8RcA21CNQINw0=",
 | 
				
			||||||
 | 
								"path": "github.com/keybase/go-crypto/openpgp/errors",
 | 
				
			||||||
 | 
								"revision": "00ac4db533f63ef97576cbc7b07939ff7daf7329",
 | 
				
			||||||
 | 
								"revisionTime": "2017-06-05T14:56:57Z"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"checksumSHA1": "y16ATKgHL/k6rQZqdXP1sIAJxE0=",
 | 
				
			||||||
 | 
								"path": "github.com/keybase/go-crypto/openpgp/packet",
 | 
				
			||||||
 | 
								"revision": "00ac4db533f63ef97576cbc7b07939ff7daf7329",
 | 
				
			||||||
 | 
								"revisionTime": "2017-06-05T14:56:57Z"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"checksumSHA1": "BGDxg1Xtsz0DSPzdQGJLLQqfYc8=",
 | 
				
			||||||
 | 
								"path": "github.com/keybase/go-crypto/openpgp/s2k",
 | 
				
			||||||
 | 
								"revision": "00ac4db533f63ef97576cbc7b07939ff7daf7329",
 | 
				
			||||||
 | 
								"revisionTime": "2017-06-05T14:56:57Z"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"checksumSHA1": "rE3pp7b3gfcmBregzpIvN5IdFhY=",
 | 
				
			||||||
 | 
								"path": "github.com/keybase/go-crypto/rsa",
 | 
				
			||||||
 | 
								"revision": "00ac4db533f63ef97576cbc7b07939ff7daf7329",
 | 
				
			||||||
 | 
								"revisionTime": "2017-06-05T14:56:57Z"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"checksumSHA1": "fh+CcgeUUsnuwSORHYWg0ycbp+4=",
 | 
								"checksumSHA1": "fh+CcgeUUsnuwSORHYWg0ycbp+4=",
 | 
				
			||||||
			"path": "github.com/klauspost/compress/flate",
 | 
								"path": "github.com/klauspost/compress/flate",
 | 
				
			||||||
@@ -1182,12 +1260,6 @@
 | 
				
			|||||||
			"revision": "2c050d2dae5345c417db301f11fda6fbf5ad0f0a",
 | 
								"revision": "2c050d2dae5345c417db301f11fda6fbf5ad0f0a",
 | 
				
			||||||
			"revisionTime": "2016-09-14T08:04:27Z"
 | 
								"revisionTime": "2016-09-14T08:04:27Z"
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"checksumSHA1": "TT1rac6kpQp2vz24m5yDGUNQ/QQ=",
 | 
					 | 
				
			||||||
			"path": "golang.org/x/crypto/cast5",
 | 
					 | 
				
			||||||
			"revision": "b8a2a83acfe6e6770b75de42d5ff4c67596675c0",
 | 
					 | 
				
			||||||
			"revisionTime": "2017-01-13T19:21:00Z"
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"checksumSHA1": "dwOedwBJ1EIK9+S3t108Bx054Y8=",
 | 
								"checksumSHA1": "dwOedwBJ1EIK9+S3t108Bx054Y8=",
 | 
				
			||||||
			"path": "golang.org/x/crypto/curve25519",
 | 
								"path": "golang.org/x/crypto/curve25519",
 | 
				
			||||||
@@ -1212,42 +1284,6 @@
 | 
				
			|||||||
			"revision": "ede567c8e044a5913dad1d1af3696d9da953104c",
 | 
								"revision": "ede567c8e044a5913dad1d1af3696d9da953104c",
 | 
				
			||||||
			"revisionTime": "2016-11-04T19:41:44Z"
 | 
								"revisionTime": "2016-11-04T19:41:44Z"
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"checksumSHA1": "IIhFTrLlmlc6lEFSitqi4aw2lw0=",
 | 
					 | 
				
			||||||
			"path": "golang.org/x/crypto/openpgp",
 | 
					 | 
				
			||||||
			"revision": "b8a2a83acfe6e6770b75de42d5ff4c67596675c0",
 | 
					 | 
				
			||||||
			"revisionTime": "2017-01-13T19:21:00Z"
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"checksumSHA1": "olOKkhrdkYQHZ0lf1orrFQPQrv4=",
 | 
					 | 
				
			||||||
			"path": "golang.org/x/crypto/openpgp/armor",
 | 
					 | 
				
			||||||
			"revision": "b8a2a83acfe6e6770b75de42d5ff4c67596675c0",
 | 
					 | 
				
			||||||
			"revisionTime": "2017-01-13T19:21:00Z"
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"checksumSHA1": "eo/KtdjieJQXH7Qy+faXFcF70ME=",
 | 
					 | 
				
			||||||
			"path": "golang.org/x/crypto/openpgp/elgamal",
 | 
					 | 
				
			||||||
			"revision": "b8a2a83acfe6e6770b75de42d5ff4c67596675c0",
 | 
					 | 
				
			||||||
			"revisionTime": "2017-01-13T19:21:00Z"
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"checksumSHA1": "rlxVSaGgqdAgwblsErxTxIfuGfg=",
 | 
					 | 
				
			||||||
			"path": "golang.org/x/crypto/openpgp/errors",
 | 
					 | 
				
			||||||
			"revision": "b8a2a83acfe6e6770b75de42d5ff4c67596675c0",
 | 
					 | 
				
			||||||
			"revisionTime": "2017-01-13T19:21:00Z"
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"checksumSHA1": "LWdaR8Q9yn6eBCcnGl0HvJRDUBE=",
 | 
					 | 
				
			||||||
			"path": "golang.org/x/crypto/openpgp/packet",
 | 
					 | 
				
			||||||
			"revision": "b8a2a83acfe6e6770b75de42d5ff4c67596675c0",
 | 
					 | 
				
			||||||
			"revisionTime": "2017-01-13T19:21:00Z"
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"checksumSHA1": "s2qT4UwvzBSkzXuiuMkowif1Olw=",
 | 
					 | 
				
			||||||
			"path": "golang.org/x/crypto/openpgp/s2k",
 | 
					 | 
				
			||||||
			"revision": "b8a2a83acfe6e6770b75de42d5ff4c67596675c0",
 | 
					 | 
				
			||||||
			"revisionTime": "2017-01-13T19:21:00Z"
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"checksumSHA1": "1MGpGDQqnUoRpv7VEcQrXOBydXE=",
 | 
								"checksumSHA1": "1MGpGDQqnUoRpv7VEcQrXOBydXE=",
 | 
				
			||||||
			"path": "golang.org/x/crypto/pbkdf2",
 | 
								"path": "golang.org/x/crypto/pbkdf2",
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user