mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-04 05:18:25 +00:00 
			
		
		
		
	* 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
		
	
		
			
				
	
	
		
			147 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			147 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2013 The Go Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
package packet
 | 
						|
 | 
						|
import (
 | 
						|
	"crypto"
 | 
						|
	"encoding/binary"
 | 
						|
	"fmt"
 | 
						|
	"io"
 | 
						|
	"strconv"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/keybase/go-crypto/openpgp/errors"
 | 
						|
	"github.com/keybase/go-crypto/openpgp/s2k"
 | 
						|
)
 | 
						|
 | 
						|
// SignatureV3 represents older version 3 signatures. These signatures are less secure
 | 
						|
// than version 4 and should not be used to create new signatures. They are included
 | 
						|
// here for backwards compatibility to read and validate with older key material.
 | 
						|
// See RFC 4880, section 5.2.2.
 | 
						|
type SignatureV3 struct {
 | 
						|
	SigType      SignatureType
 | 
						|
	CreationTime time.Time
 | 
						|
	IssuerKeyId  uint64
 | 
						|
	PubKeyAlgo   PublicKeyAlgorithm
 | 
						|
	Hash         crypto.Hash
 | 
						|
	HashTag      [2]byte
 | 
						|
 | 
						|
	RSASignature     parsedMPI
 | 
						|
	DSASigR, DSASigS parsedMPI
 | 
						|
}
 | 
						|
 | 
						|
func (sig *SignatureV3) parse(r io.Reader) (err error) {
 | 
						|
	// RFC 4880, section 5.2.2
 | 
						|
	var buf [8]byte
 | 
						|
	if _, err = readFull(r, buf[:1]); err != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if buf[0] < 2 || buf[0] > 3 {
 | 
						|
		err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if _, err = readFull(r, buf[:1]); err != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if buf[0] != 5 {
 | 
						|
		err = errors.UnsupportedError(
 | 
						|
			"invalid hashed material length " + strconv.Itoa(int(buf[0])))
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	// Read hashed material: signature type + creation time
 | 
						|
	if _, err = readFull(r, buf[:5]); err != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	sig.SigType = SignatureType(buf[0])
 | 
						|
	t := binary.BigEndian.Uint32(buf[1:5])
 | 
						|
	sig.CreationTime = time.Unix(int64(t), 0)
 | 
						|
 | 
						|
	// Eight-octet Key ID of signer.
 | 
						|
	if _, err = readFull(r, buf[:8]); err != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	sig.IssuerKeyId = binary.BigEndian.Uint64(buf[:])
 | 
						|
 | 
						|
	// Public-key and hash algorithm
 | 
						|
	if _, err = readFull(r, buf[:2]); err != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	sig.PubKeyAlgo = PublicKeyAlgorithm(buf[0])
 | 
						|
	switch sig.PubKeyAlgo {
 | 
						|
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA:
 | 
						|
	default:
 | 
						|
		err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
 | 
						|
		return
 | 
						|
	}
 | 
						|
	var ok bool
 | 
						|
	if sig.Hash, ok = s2k.HashIdToHash(buf[1]); !ok {
 | 
						|
		return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
 | 
						|
	}
 | 
						|
 | 
						|
	// Two-octet field holding left 16 bits of signed hash value.
 | 
						|
	if _, err = readFull(r, sig.HashTag[:2]); err != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	switch sig.PubKeyAlgo {
 | 
						|
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
 | 
						|
		sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
 | 
						|
	case PubKeyAlgoDSA:
 | 
						|
		if sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r); err != nil {
 | 
						|
			return
 | 
						|
		}
 | 
						|
		sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
 | 
						|
	default:
 | 
						|
		panic("unreachable")
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
 | 
						|
// called first.
 | 
						|
func (sig *SignatureV3) Serialize(w io.Writer) (err error) {
 | 
						|
	buf := make([]byte, 8)
 | 
						|
 | 
						|
	// Write the sig type and creation time
 | 
						|
	buf[0] = byte(sig.SigType)
 | 
						|
	binary.BigEndian.PutUint32(buf[1:5], uint32(sig.CreationTime.Unix()))
 | 
						|
	if _, err = w.Write(buf[:5]); err != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	// Write the issuer long key ID
 | 
						|
	binary.BigEndian.PutUint64(buf[:8], sig.IssuerKeyId)
 | 
						|
	if _, err = w.Write(buf[:8]); err != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	// Write public key algorithm, hash ID, and hash value
 | 
						|
	buf[0] = byte(sig.PubKeyAlgo)
 | 
						|
	hashId, ok := s2k.HashToHashId(sig.Hash)
 | 
						|
	if !ok {
 | 
						|
		return errors.UnsupportedError(fmt.Sprintf("hash function %v", sig.Hash))
 | 
						|
	}
 | 
						|
	buf[1] = hashId
 | 
						|
	copy(buf[2:4], sig.HashTag[:])
 | 
						|
	if _, err = w.Write(buf[:4]); err != nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil {
 | 
						|
		return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
 | 
						|
	}
 | 
						|
 | 
						|
	switch sig.PubKeyAlgo {
 | 
						|
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
 | 
						|
		err = writeMPIs(w, sig.RSASignature)
 | 
						|
	case PubKeyAlgoDSA:
 | 
						|
		err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
 | 
						|
	default:
 | 
						|
		panic("impossible")
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 |