// 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 os.Error) { var p packet.Packet for { p, err = packets.Next() if err == os.EOF { return } else if err != nil { if _, ok := err.(error.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, os.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, error.StructuralError("first packet was not a public/private key") } else { e.PrimaryKey = &e.PrivateKey.PublicKey } } var current *Identity EachPacket: for { p, err := packets.Next() if err == os.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 == os.EOF { return nil, io.ErrUnexpectedEOF } else if err != nil { return nil, err } sig, ok := p.(*packet.Signature) if !ok { return nil, error.StructuralError("user ID packet not followed by self-signature") } if sig.SigType == packet.SigTypePositiveCert && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId { if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, sig); err != nil { return nil, error.StructuralError("user ID self-signature invalid: " + err.String()) } current.SelfSignature = sig break } current.Signatures = append(current.Signatures, sig) } case *packet.Signature: if current == nil { return nil, error.StructuralError("signature packet found before user id packet") } 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, error.StructuralError("entity without any identities") } return e, nil }