Source File
public_key.go
Belonging Package
golang.org/x/crypto/openpgp/packet
oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23}
)
const maxOIDLength = 8
func ( io.Reader) ( []byte, error) {
:= make([]byte, maxOIDLength)
if _, = readFull(, [:1]); != nil {
return
}
:= [0]
if int() > len() {
= errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int()))
return
}
= [:]
_, = readFull(, )
return
}
func ( *ecdsaKey) ( io.Reader) ( error) {
if .oid, = parseOID(); != nil {
return
}
.p.bytes, .p.bitLength, = readMPI()
return
}
func ( *ecdsaKey) ( io.Writer) ( error) {
:= make([]byte, maxOIDLength+1)
[0] = byte(len(.oid))
copy([1:], .oid)
if _, = .Write([:len(.oid)+1]); != nil {
return
}
return writeMPIs(, .p)
}
func ( *ecdsaKey) () (*ecdsa.PublicKey, error) {
var elliptic.Curve
if bytes.Equal(.oid, oidCurveP256) {
= elliptic.P256()
} else if bytes.Equal(.oid, oidCurveP384) {
= elliptic.P384()
} else if bytes.Equal(.oid, oidCurveP521) {
= elliptic.P521()
} else {
return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", .oid))
}
, := elliptic.Unmarshal(, .p.bytes)
if == nil {
return nil, errors.UnsupportedError("failed to parse EC point")
}
return &ecdsa.PublicKey{Curve: , X: , Y: }, nil
}
func ( *ecdsaKey) () int {
return 1 + len(.oid) + 2 + len(.p.bytes)
}
type kdfHashFunction byte
type kdfAlgorithm byte
type ecdhKdf struct {
KdfHash kdfHashFunction
KdfAlgo kdfAlgorithm
}
func ( *ecdhKdf) ( io.Reader) ( error) {
:= make([]byte, 1)
if _, = readFull(, ); != nil {
return
}
:= int([0])
if < 3 {
return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa())
}
= make([]byte, )
if _, = readFull(, ); != nil {
return
}
:= int([0])
.KdfHash = kdfHashFunction([1])
.KdfAlgo = kdfAlgorithm([2])
if != 0x01 {
return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa())
}
return
}
func ( *ecdhKdf) ( io.Writer) ( error) {
type PublicKey struct {
CreationTime time.Time
PubKeyAlgo PublicKeyAlgorithm
PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey
Fingerprint [20]byte
KeyId uint64
IsSubkey bool
n, e, p, q, g, y parsedMPI
func ( time.Time, *rsa.PublicKey) *PublicKey {
:= &PublicKey{
CreationTime: ,
PubKeyAlgo: PubKeyAlgoRSA,
PublicKey: ,
n: fromBig(.N),
e: fromBig(big.NewInt(int64(.E))),
}
.setFingerPrintAndKeyId()
return
}
func ( time.Time, *elgamal.PublicKey) *PublicKey {
:= &PublicKey{
CreationTime: ,
PubKeyAlgo: PubKeyAlgoElGamal,
PublicKey: ,
p: fromBig(.P),
g: fromBig(.G),
y: fromBig(.Y),
}
.setFingerPrintAndKeyId()
return
}
func ( time.Time, *ecdsa.PublicKey) *PublicKey {
:= &PublicKey{
CreationTime: ,
PubKeyAlgo: PubKeyAlgoECDSA,
PublicKey: ,
ec: new(ecdsaKey),
}
switch .Curve {
case elliptic.P256():
.ec.oid = oidCurveP256
case elliptic.P384():
.ec.oid = oidCurveP384
case elliptic.P521():
.ec.oid = oidCurveP521
default:
panic("unknown elliptic curve")
}
.ec.p.bytes = elliptic.Marshal(.Curve, .X, .Y)
var [6]byte
_, = readFull(, [:])
if != nil {
return
}
if [0] != 4 {
return errors.UnsupportedError("public key version")
}
.CreationTime = time.Unix(int64(uint32([1])<<24|uint32([2])<<16|uint32([3])<<8|uint32([4])), 0)
.PubKeyAlgo = PublicKeyAlgorithm([5])
switch .PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
= .parseRSA()
case PubKeyAlgoDSA:
= .parseDSA()
case PubKeyAlgoElGamal:
= .parseElGamal()
case PubKeyAlgoECDSA:
.ec = new(ecdsaKey)
if = .ec.parse(); != nil {
return
}
.PublicKey, = .ec.newECDSA()
case PubKeyAlgoECDH:
.ec = new(ecdsaKey)
if = .ec.parse(); != nil {
return
}
.ecdh = new(ecdhKdf)
if = .ecdh.parse(); != nil {
return
.PublicKey, = .ec.newECDSA()
default:
= errors.UnsupportedError("public key type: " + strconv.Itoa(int(.PubKeyAlgo)))
}
if != nil {
return
}
.setFingerPrintAndKeyId()
return
}
:= sha1.New()
.SerializeSignaturePrefix()
.serializeWithoutHeaders()
copy(.Fingerprint[:], .Sum(nil))
.KeyId = binary.BigEndian.Uint64(.Fingerprint[12:20])
}
func ( *PublicKey) ( io.Reader) ( error) {
.n.bytes, .n.bitLength, = readMPI()
if != nil {
return
}
.e.bytes, .e.bitLength, = readMPI()
if != nil {
return
}
if len(.e.bytes) > 3 {
= errors.UnsupportedError("large public exponent")
return
}
:= &rsa.PublicKey{
N: new(big.Int).SetBytes(.n.bytes),
E: 0,
}
for := 0; < len(.e.bytes); ++ {
.E <<= 8
.E |= int(.e.bytes[])
}
.PublicKey =
return
}
func ( *PublicKey) ( io.Reader) ( error) {
.p.bytes, .p.bitLength, = readMPI()
if != nil {
return
}
.q.bytes, .q.bitLength, = readMPI()
if != nil {
return
}
.g.bytes, .g.bitLength, = readMPI()
if != nil {
return
}
.y.bytes, .y.bitLength, = readMPI()
if != nil {
return
}
:= new(dsa.PublicKey)
.P = new(big.Int).SetBytes(.p.bytes)
.Q = new(big.Int).SetBytes(.q.bytes)
.G = new(big.Int).SetBytes(.g.bytes)
.Y = new(big.Int).SetBytes(.y.bytes)
.PublicKey =
return
}
func ( *PublicKey) ( io.Reader) ( error) {
.p.bytes, .p.bitLength, = readMPI()
if != nil {
return
}
.g.bytes, .g.bitLength, = readMPI()
if != nil {
return
}
.y.bytes, .y.bitLength, = readMPI()
if != nil {
return
}
:= new(elgamal.PublicKey)
.P = new(big.Int).SetBytes(.p.bytes)
.G = new(big.Int).SetBytes(.g.bytes)
.Y = new(big.Int).SetBytes(.y.bytes)
.PublicKey =
return
}
func ( *PublicKey) ( io.Writer) {
var uint16
switch .PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+= 2 + uint16(len(.n.bytes))
+= 2 + uint16(len(.e.bytes))
case PubKeyAlgoDSA:
+= 2 + uint16(len(.p.bytes))
+= 2 + uint16(len(.q.bytes))
+= 2 + uint16(len(.g.bytes))
+= 2 + uint16(len(.y.bytes))
case PubKeyAlgoElGamal:
+= 2 + uint16(len(.p.bytes))
+= 2 + uint16(len(.g.bytes))
+= 2 + uint16(len(.y.bytes))
case PubKeyAlgoECDSA:
+= uint16(.ec.byteLen())
case PubKeyAlgoECDH:
+= uint16(.ec.byteLen())
+= uint16(.ecdh.byteLen())
default:
panic("unknown public key algorithm")
}
+= 6
.Write([]byte{0x99, byte( >> 8), byte()})
return
}
func ( *PublicKey) ( io.Writer) ( error) {
:= 6 // 6 byte header
switch .PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+= 2 + len(.n.bytes)
+= 2 + len(.e.bytes)
case PubKeyAlgoDSA:
+= 2 + len(.p.bytes)
+= 2 + len(.q.bytes)
+= 2 + len(.g.bytes)
+= 2 + len(.y.bytes)
case PubKeyAlgoElGamal:
+= 2 + len(.p.bytes)
+= 2 + len(.g.bytes)
+= 2 + len(.y.bytes)
case PubKeyAlgoECDSA:
+= .ec.byteLen()
case PubKeyAlgoECDH:
+= .ec.byteLen()
+= .ecdh.byteLen()
default:
panic("unknown public key algorithm")
}
:= packetTypePublicKey
if .IsSubkey {
= packetTypePublicSubkey
}
= serializeHeader(, , )
if != nil {
return
}
return .serializeWithoutHeaders()
}
func ( *PublicKey) ( io.Writer) ( error) {
var [6]byte
[0] = 4
:= uint32(.CreationTime.Unix())
[1] = byte( >> 24)
[2] = byte( >> 16)
[3] = byte( >> 8)
[4] = byte()
[5] = byte(.PubKeyAlgo)
_, = .Write([:])
if != nil {
return
}
switch .PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
return writeMPIs(, .n, .e)
case PubKeyAlgoDSA:
return writeMPIs(, .p, .q, .g, .y)
case PubKeyAlgoElGamal:
return writeMPIs(, .p, .g, .y)
case PubKeyAlgoECDSA:
return .ec.serialize()
case PubKeyAlgoECDH:
if = .ec.serialize(); != nil {
return
}
return .ecdh.serialize()
}
return errors.InvalidArgumentError("bad public-key algorithm")
}
func ( *PublicKey) () bool {
return .PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && .PubKeyAlgo != PubKeyAlgoElGamal
}
func ( *PublicKey) ( hash.Hash, *Signature) ( error) {
if !.CanSign() {
return errors.InvalidArgumentError("public key cannot generate signatures")
}
.Write(.HashSuffix)
:= .Sum(nil)
if [0] != .HashTag[0] || [1] != .HashTag[1] {
return errors.SignatureError("hash tag doesn't match")
}
if .PubKeyAlgo != .PubKeyAlgo {
return errors.InvalidArgumentError("public key and signature use different algorithms")
}
switch .PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
, := .PublicKey.(*rsa.PublicKey)
= rsa.VerifyPKCS1v15(, .Hash, , padToKeySize(, .RSASignature.bytes))
if != nil {
return errors.SignatureError("RSA verification failure")
}
return nil
case PubKeyAlgoDSA:
:= (.Q.BitLen() + 7) / 8
if len() > {
= [:]
}
if !dsa.Verify(, , new(big.Int).SetBytes(.DSASigR.bytes), new(big.Int).SetBytes(.DSASigS.bytes)) {
return errors.SignatureError("DSA verification failure")
}
return nil
case PubKeyAlgoECDSA:
:= .PublicKey.(*ecdsa.PublicKey)
if !ecdsa.Verify(, , new(big.Int).SetBytes(.ECDSASigR.bytes), new(big.Int).SetBytes(.ECDSASigS.bytes)) {
return errors.SignatureError("ECDSA verification failure")
}
return nil
default:
return errors.SignatureError("Unsupported public key algorithm used in signature")
}
}
func ( *PublicKey) ( hash.Hash, *SignatureV3) ( error) {
if !.CanSign() {
return errors.InvalidArgumentError("public key cannot generate signatures")
}
:= make([]byte, 5)
[0] = byte(.SigType)
binary.BigEndian.PutUint32([1:], uint32(.CreationTime.Unix()))
.Write()
:= .Sum(nil)
if [0] != .HashTag[0] || [1] != .HashTag[1] {
return errors.SignatureError("hash tag doesn't match")
}
if .PubKeyAlgo != .PubKeyAlgo {
return errors.InvalidArgumentError("public key and signature use different algorithms")
}
switch .PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
:= .PublicKey.(*rsa.PublicKey)
if = rsa.VerifyPKCS1v15(, .Hash, , padToKeySize(, .RSASignature.bytes)); != nil {
return errors.SignatureError("RSA verification failure")
}
return
case PubKeyAlgoDSA:
.SerializeSignaturePrefix()
.serializeWithoutHeaders()
.SerializeSignaturePrefix()
.serializeWithoutHeaders()
return
}
func ( *PublicKey) ( *PublicKey, *Signature) error {
, := keySignatureHash(, , .Hash)
if != nil {
return
}
if = .VerifySignature(, ); != nil {
return
}
if .EmbeddedSignature == nil {
return errors.StructuralError("signing subkey is missing cross-signature")
if , = keySignatureHash(, , .EmbeddedSignature.Hash); != nil {
return errors.StructuralError("error while hashing for cross-signature: " + .Error())
}
if := .VerifySignature(, .EmbeddedSignature); != nil {
return errors.StructuralError("error while verifying cross-signature: " + .Error())
}
}
return nil
}
func ( signingKey, crypto.Hash) ( hash.Hash, error) {
if !.Available() {
return nil, errors.UnsupportedError("hash function")
}
= .New()
.SerializeSignaturePrefix()
.serializeWithoutHeaders()
return
}
func ( *PublicKey) ( *Signature) ( error) {
, := keyRevocationHash(, .Hash)
if != nil {
return
}
return .VerifySignature(, )
}
func ( *PublicKey) ( string, *PublicKey, *Signature) ( error) {
, := userIdSignatureHash(, , .Hash)
if != nil {
return
}
return .VerifySignature(, )
}
func ( *PublicKey) ( string, *PublicKey, *SignatureV3) ( error) {
, := userIdSignatureV3Hash(, , .Hash)
if != nil {
return
}
return .VerifySignatureV3(, )
}
func ( *PublicKey) () string {
return fmt.Sprintf("%X", .Fingerprint[12:20])
}
func ( *PublicKey) () string {
return fmt.Sprintf("%X", .Fingerprint[16:20])
}
func ( *PublicKey) () ( uint16, error) {
switch .PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
= .n.bitLength
case PubKeyAlgoDSA:
= .p.bitLength
case PubKeyAlgoElGamal:
= .p.bitLength
default:
= errors.InvalidArgumentError("bad public-key algorithm")
}
return
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |