func (vr *VerifyRequest) VerifySignature() bool { armorData := reArmor(vr.CamliSig) block, _ := armor.Decode(bytes.NewBufferString(armorData)) if block == nil { return vr.fail("can't parse camliSig armor") } var p packet.Packet var err error p, err = packet.Read(block.Body) if err != nil { return vr.fail("error reading PGP packet from camliSig: " + err.Error()) } sig, ok := p.(*packet.Signature) if !ok { return vr.fail("PGP packet isn't a signature packet") } if sig.Hash != crypto.SHA1 && sig.Hash != crypto.SHA256 { return vr.fail("I can only verify SHA1 or SHA256 signatures") } if sig.SigType != packet.SigTypeBinary { return vr.fail("I can only verify binary signatures") } hash := sig.Hash.New() hash.Write(vr.bp) // payload bytes err = vr.PublicKeyPacket.VerifySignature(hash, sig) if err != nil { return vr.fail(fmt.Sprintf("bad signature: %s", err)) } vr.SignerKeyId = vr.PublicKeyPacket.KeyIdString() return true }
func (expk *extPGPPrivateKey) sign(content []byte) (*packet.Signature, error) { if expk.bitLen < 4096 { return nil, fmt.Errorf("signing needs at least a 4096 bits key, got %d", expk.bitLen) } out, err := expk.doSign(content) if err != nil { return nil, err } badSig := fmt.Sprintf("bad %s produced signature: ", expk.from) sigpkt, err := packet.Read(bytes.NewBuffer(out)) if err != nil { return nil, fmt.Errorf(badSig+"%v", err) } sig, ok := sigpkt.(*packet.Signature) if !ok { return nil, fmt.Errorf(badSig+"got %T", sigpkt) } if sig.Hash != crypto.SHA512 { return nil, fmt.Errorf(badSig + "expected SHA512 digest") } err = expk.pubKey.verify(content, sig) if err != nil { return nil, fmt.Errorf(badSig+"it does not verify: %v", err) } return sig, nil }
func trySig(filename string) (bool, error) { sigFile, err := os.Open(filename) if err != nil { return true, err } defer sigFile.Close() b, err := armor.Decode(sigFile) if err != nil && err != io.EOF { return true, err } if b == nil { return false, nil } // Read the signature file pack, err := packet.Read(b.Body) if err != nil { return true, err } // Was it really a signature file ? If yes, get the Signature if signature, ok := pack.(*packet.Signature); !ok { return false, nil } else { fmt.Printf("Signature made %s\n", signature.CreationTime.Format(time.RFC3339)) // Signature made Wed 05 Aug 2015 11:48:13 PM UTC using RSA key ID F553000C // Primary key fingerprint: EF64 BCCB 58BC F501 FEDA 0582 0581 2930 F553 000C // binary signature, digest algorithm SHA256 return true, nil } }
func decodeV1(b []byte, kind string) (packet.Packet, error) { if len(b) == 0 { return nil, fmt.Errorf("cannot decode %s: no data", kind) } buf := make([]byte, base64.StdEncoding.DecodedLen(len(b))) n, err := base64.StdEncoding.Decode(buf, b) if err != nil { return nil, fmt.Errorf("cannot decode %s: %v", kind, err) } if n == 0 { return nil, fmt.Errorf("cannot decode %s: base64 without data", kind) } buf = buf[:n] if buf[0] != v1 { return nil, fmt.Errorf("unsupported %s format version: %d", kind, buf[0]) } rd := bytes.NewReader(buf[1:]) pkt, err := packet.Read(rd) if err != nil { return nil, fmt.Errorf("cannot decode %s: %v", kind, err) } if rd.Len() != 0 { return nil, fmt.Errorf("%s has spurious trailing data", kind) } return pkt, nil }
func checkPublicKey(ab *AssertionBase, fingerprintName string) (*packet.PublicKey, error) { pubKeyBody := ab.Body() if len(pubKeyBody) == 0 { return nil, fmt.Errorf("expected public key, not empty body") } format, key, err := splitFormatAndBase64Decode(pubKeyBody) if err != nil { return nil, fmt.Errorf("public key: %v", err) } if format != "openpgp" { return nil, fmt.Errorf("unsupported public key format: %q", format) } pkt, err := packet.Read(bytes.NewBuffer(key)) if err != nil { return nil, fmt.Errorf("could not parse public key data: %v", err) } pubk, ok := pkt.(*packet.PublicKey) if !ok { return nil, fmt.Errorf("expected public key, got instead: %T", pkt) } fp, err := hex.DecodeString(ab.Header(fingerprintName)) if err != nil { return nil, fmt.Errorf("could not parse %v header: %v", fingerprintName, err) } if len(fp) == 0 { return nil, fmt.Errorf("missing %v header", fingerprintName) } if bytes.Compare(fp, pubk.Fingerprint[:]) != 0 { return nil, fmt.Errorf("public key does not match provided fingerprint") } return pubk, nil }
func (dbs *databaseSuite) TestPublicKey(c *C) { pk := testPrivKey1 keyID := pk.PublicKey().ID() err := dbs.db.ImportKey(pk) c.Assert(err, IsNil) pubk, err := dbs.db.PublicKey(keyID) c.Assert(err, IsNil) c.Check(pubk.ID(), Equals, keyID) // usual pattern is to then encode it encoded, err := asserts.EncodePublicKey(pubk) c.Assert(err, IsNil) data, err := base64.StdEncoding.DecodeString(string(encoded)) c.Assert(err, IsNil) c.Check(data[0], Equals, uint8(1)) // v1 // check details of packet const newHeaderBits = 0x80 | 0x40 c.Check(data[1]&newHeaderBits, Equals, uint8(newHeaderBits)) c.Check(data[2] < 192, Equals, true) // small packet, 1 byte length c.Check(data[3], Equals, uint8(4)) // openpgp v4 pkt, err := packet.Read(bytes.NewBuffer(data[1:])) c.Assert(err, IsNil) pubKey, ok := pkt.(*packet.PublicKey) c.Assert(ok, Equals, true) c.Check(pubKey.PubKeyAlgo, Equals, packet.PubKeyAlgoRSA) c.Check(pubKey.IsSubkey, Equals, false) fixedTimestamp := time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC) c.Check(pubKey.CreationTime.Equal(fixedTimestamp), Equals, true) // hash of blob content == hash of key h384 := sha3.Sum384(data) encHash := base64.RawURLEncoding.EncodeToString(h384[:]) c.Check(encHash, DeepEquals, testPrivKey1SHA3_384) }
// CheckDetachedSignature takes a signed file and a detached signature and // returns the signer if the signature is valid. If the signer isn't known, // ErrUnknownIssuer is returned. func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { p, err := packet.Read(signature) if err != nil { return } var issuerKeyId uint64 var hashFunc crypto.Hash var sigType packet.SignatureType switch sig := p.(type) { case *packet.Signature: if sig.IssuerKeyId == nil { return nil, errors.StructuralError("signature doesn't have an issuer") } issuerKeyId = *sig.IssuerKeyId hashFunc = sig.Hash sigType = sig.SigType case *packet.SignatureV3: issuerKeyId = sig.IssuerKeyId hashFunc = sig.Hash sigType = sig.SigType default: return nil, errors.StructuralError("non signature packet found") } h, wrappedHash, err := hashForSignature(hashFunc, sigType) if err != nil { return } _, err = io.Copy(wrappedHash, signed) if err != nil && err != io.EOF { return } keys := keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign) if len(keys) == 0 { return nil, errors.ErrUnknownIssuer } for _, key := range keys { switch sig := p.(type) { case *packet.Signature: err = key.PublicKey.VerifySignature(h, sig) case *packet.SignatureV3: err = key.PublicKey.VerifySignatureV3(h, sig) } if err == nil { return key.Entity, nil } } if err == nil { err = errors.ErrUnknownIssuer } return nil, err }
// GetPublicKey converts an ASCII-armored public key representation // into an OpenPGP key. func GetPublicKey(buf []byte) (*packet.PublicKey, error) { keyRdr, err := armor.Decode(bytes.NewBuffer(buf)) if err != nil { return nil, err } keyData, err := packet.Read(keyRdr.Body) if err != nil { return nil, err } key, ok := keyData.(*packet.PublicKey) if !ok { return nil, errors.New("Invalid public key") } return key, nil }
// Returns the key ID used to sign a message. This method is extracted // from `openpgp.CheckDetachedSignature()`, which only reports that a // key wasn't found, not *which* key wasn't found. func signerKeyId(signature []byte) (uint64, error) { p, err := packet.Read(bytes.NewReader(signature)) if err != nil { return 0, err } switch sig := p.(type) { case *packet.Signature: if sig.IssuerKeyId == nil { return 0, errors.StructuralError("signature doesn't have an issuer") } return *sig.IssuerKeyId, nil case *packet.SignatureV3: return sig.IssuerKeyId, nil default: return 0, errors.StructuralError("non signature packet found") } }
func decodeOpenpgp(formatAndBase64 []byte, kind string) (packet.Packet, error) { if len(formatAndBase64) == 0 { return nil, fmt.Errorf("empty %s", kind) } format, data, err := splitFormatAndBase64Decode(formatAndBase64) if err != nil { return nil, fmt.Errorf("%s: %v", kind, err) } if format != "openpgp" { return nil, fmt.Errorf("unsupported %s format: %q", kind, format) } pkt, err := packet.Read(bytes.NewReader(data)) if err != nil { return nil, fmt.Errorf("could not decode %s data: %v", kind, err) } return pkt, nil }
func parsePubKey(r io.Reader) (*packet.PublicKey, error) { block, _ := armor.Decode(r) if block == nil { return nil, errors.New("can't parse armor") } var p packet.Packet var err error p, err = packet.Read(block.Body) if err != nil { return nil, err } pk, ok := p.(*packet.PublicKey) if !ok { return nil, errors.New("PGP packet isn't a public key") } return pk, nil }
func Verify(payload string, signature []byte, pubkey *packet.PublicKey) error { // decode and read the signature block, err := armor.Decode(bytes.NewBuffer(signature)) if err != nil { return err } pkt, err := packet.Read(block.Body) if err != nil { return err } sig, ok := pkt.(*packet.Signature) if !ok { return fmt.Errorf("could not parse the signature") } if sig.Hash != crypto.SHA256 || sig.Hash != crypto.SHA512 { return fmt.Errorf("was not a SHA-256 or SHA-512 signature") } if sig.SigType != packet.SigTypeBinary { return fmt.Errorf("was not a binary signature") } // verify the signature hash := sig.Hash.New() _, err = hash.Write([]byte(payload)) if err != nil { return err } err = pubkey.VerifySignature(hash, sig) if err != nil { return err } return nil }
func main() { b, err := armor.Decode(p512Key) if err != nil { log.Fatal(err) } // p, err := ioutil.ReadAll(b.Body) // if err != nil { // log.Fatal(err) // } // for i := range p { // fmt.Printf("%#02x, ", p[i]) // } p, err := packet.Read(b.Body) if err != nil { log.Fatal(err) } if p, ok := p.(*packet.PrivateKey); ok { log.Println(p.PublicKey.PubKeyAlgo) } }
func (dbs *databaseSuite) TestImportKey(c *C) { privk, err := asserts.GeneratePrivateKeyInTest() c.Assert(err, IsNil) expectedFingerprint := hex.EncodeToString(privk.PublicKey.Fingerprint[:]) fingerp, err := dbs.db.ImportKey("account0", privk) c.Assert(err, IsNil) c.Check(fingerp, Equals, expectedFingerprint) keyPath := filepath.Join(dbs.rootDir, "private-keys-v0/account0", fingerp) info, err := os.Stat(keyPath) c.Assert(err, IsNil) c.Check(info.Mode().Perm(), Equals, os.FileMode(0600)) // secret // too white box? ok at least until we have more functionality fpriv, err := os.Open(keyPath) c.Assert(err, IsNil) pk, err := packet.Read(fpriv) c.Assert(err, IsNil) privKeyFromDisk, ok := pk.(*packet.PrivateKey) c.Assert(ok, Equals, true) c.Check(hex.EncodeToString(privKeyFromDisk.PublicKey.Fingerprint[:]), Equals, expectedFingerprint) }
func openArmoredPublicKeyFile(reader io.ReadCloser) (*packet.PublicKey, error) { defer reader.Close() var lr = io.LimitReader(reader, publicKeyMaxSize) block, _ := armor.Decode(lr) if block == nil { return nil, errors.New("Couldn't find PGP block in public key file") } if block.Type != "PGP PUBLIC KEY BLOCK" { return nil, errors.New("Invalid public key blob.") } p, err := packet.Read(block.Body) if err != nil { return nil, fmt.Errorf("Invalid public key blob: %v", err) } pk, ok := p.(*packet.PublicKey) if !ok { return nil, fmt.Errorf("Invalid public key blob; not a public key packet") } return pk, nil }
func privateKeyToAssertsKey(key []byte) (asserts.PrivateKey, string, error) { const errorInvalidKey = "error-invalid-key" // Validate the signing-key block, err := armor.Decode(bytes.NewReader(key)) if err != nil { return nil, errorInvalidKey, err } pkt, err := packet.Read(block.Body) if err != nil { return nil, errorInvalidKey, err } privk, ok := pkt.(*packet.PrivateKey) if !ok { return nil, errorInvalidKey, errors.New("Not a private key") } if _, ok := privk.PrivateKey.(*rsa.PrivateKey); !ok { return nil, errorInvalidKey, errors.New("Not an RSA private key") } return asserts.RSAPrivateKey(privk.PrivateKey.(*rsa.PrivateKey)), "", nil }
func (dbs *databaseSuite) TestPublicKey(c *C) { pk := asserts.OpenPGPPrivateKey(testPrivKey1) fingerp := pk.PublicKey().Fingerprint() keyid := pk.PublicKey().ID() err := dbs.db.ImportKey("account0", pk) c.Assert(err, IsNil) pubk, err := dbs.db.PublicKey("account0", keyid) c.Assert(err, IsNil) c.Check(pubk.Fingerprint(), Equals, fingerp) // usual pattern is to then encode it encoded, err := asserts.EncodePublicKey(pubk) c.Assert(err, IsNil) c.Check(bytes.HasPrefix(encoded, []byte("openpgp ")), Equals, true) data, err := base64.StdEncoding.DecodeString(string(encoded[len("openpgp "):])) c.Assert(err, IsNil) pkt, err := packet.Read(bytes.NewBuffer(data)) c.Assert(err, IsNil) pubKey, ok := pkt.(*packet.PublicKey) c.Assert(ok, Equals, true) c.Assert(pubKey.Fingerprint, DeepEquals, testPrivKey1.PublicKey.Fingerprint) }
func (s *SamplePacketSuite) TestUatRtt(c *gc.C) { f := testing.MustInput("uat.asc") defer f.Close() block, err := armor.Decode(f) c.Assert(err, gc.IsNil) var p packet.Packet for { p, err = packet.Read(block.Body) if err != nil { c.Assert(err, gc.Equals, io.EOF) break } uat, ok := p.(*packet.UserAttribute) if ok { var buf bytes.Buffer uat.Serialize(&buf) or := packet.NewOpaqueReader(bytes.NewBuffer(buf.Bytes())) op, _ := or.Next() c.Assert(buf.Bytes()[3:], gc.DeepEquals, op.Contents) } } }
// ReadPrivKey reads a PGP private key (either armored or simply base64 encoded). It panics on error. func ReadPrivKey(pk string) (asserts.PrivateKey, *rsa.PrivateKey) { rd := bytes.NewReader([]byte(pk)) blk, err := armor.Decode(rd) var body io.Reader if err == nil { body = blk.Body } else { rd.Seek(0, 0) // try unarmored body = base64.NewDecoder(base64.StdEncoding, rd) } pkt, err := packet.Read(body) if err != nil { panic(err) } pkPkt := pkt.(*packet.PrivateKey) rsaPrivKey, ok := pkPkt.PrivateKey.(*rsa.PrivateKey) if !ok { panic("not a RSA key") } return asserts.RSAPrivateKey(rsaPrivKey), rsaPrivKey }
func parseSignature(signature []byte) (Signature, error) { if len(signature) == 0 { return nil, fmt.Errorf("empty signature") } format, sigData, err := splitFormatAndBase64Decode(signature) if err != nil { return nil, fmt.Errorf("signature: %v", err) } if format != "openpgp" { return nil, fmt.Errorf("unsupported signature format: %q", format) } pkt, err := packet.Read(bytes.NewReader(sigData)) if err != nil { return nil, fmt.Errorf("could not parse signature data: %v", err) } sig, ok := pkt.(*packet.Signature) if !ok { return nil, fmt.Errorf("expected signature, got instead: %T", pkt) } if sig.IssuerKeyId == nil { return nil, fmt.Errorf("expected issuer key id in signature") } return openpgpSignature{sig}, nil }
func (cs Server) receiveSignedNonce(r io.Reader) (*packet.Signature, error) { block, _ := armor.Decode(r) if block == nil { return nil, errors.New("can't parse armor") } var p packet.Packet var err error p, err = packet.Read(block.Body) if err != nil { return nil, err } sig, ok := p.(*packet.Signature) if !ok { return nil, errors.New("PGP packet isn't a signature packet") } if sig.Hash != crypto.SHA1 && sig.Hash != crypto.SHA256 { return nil, errors.New("can only verify SHA1 or SHA256 signatures") } if sig.SigType != packet.SigTypeBinary { return nil, errors.New("can only verify binary signatures") } return sig, nil }