func checkInlineSignature(body string, keysrc KeySource) (*VerifyStatus, []byte) { b, _ := clearsign.Decode([]byte(body)) if b == nil { return new(VerifyStatus), nil } status := checkSignature(keysrc, b.Bytes, b.ArmoredSignature) if isVerifiedSignature(status) { return status, b.Plaintext } return status, nil }
// DecodeCheckSignature parses the inline signed PGP text, checks the signature, // and returns plain text if the signature matches. func DecodeCheckSignature(r io.Reader, armoredPublicKey string) ([]byte, error) { data, err := ioutil.ReadAll(r) if err != nil { return nil, err } b, _ := clearsign.Decode(data) if b == nil { return nil, &NotPGPSignedError{} } keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(armoredPublicKey)) if err != nil { return nil, fmt.Errorf("failed to parse public key: %v", err) } _, err = openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body) if err != nil { return nil, err } return b.Plaintext, nil }
func checkGPG(file *File) (state SigState, err error) { var signer *openpgp.Entity var cs *clearsign.Block keypath := path.Join(os.Getenv("HOME"), "/.gnupg/pubring.gpg") keys, err := os.Open(keypath) if err != nil { fmt.Printf("Could not open public keyring at %s\n", keypath) os.Exit(2) } keyring, err := openpgp.ReadKeyRing(keys) if err != nil { fmt.Printf("Error reading public keyring: %s\n", err) os.Exit(2) } if *flagClear { cs, _ = clearsign.Decode(file.content) if cs == nil { fmt.Printf("Problem decoding clearsign signature from file %s\n", file.name) os.Exit(2) } lsig, err := ioutil.ReadAll(cs.ArmoredSignature.Body) if err != nil { fmt.Printf("Problem reading signature from %s. Are you sure this file is clearsigned?: %s\n", file.name, err) os.Exit(2) } if len(lsig) > 0 { file.signature = lsig file.content = cs.Bytes *flagBin = true } } if *flagBin { signer, err = openpgp.CheckDetachedSignature(keyring, bytes.NewReader(file.content), bytes.NewReader(file.signature)) } else { signer, err = openpgp.CheckArmoredDetachedSignature(keyring, bytes.NewReader(file.content), bytes.NewReader(file.signature)) } if err != nil { fmt.Printf("Invalid signature or public key not present: %s\n", err) os.Exit(2) } state.sig = signer.PrimaryKey.KeyIdString() l := len(*flagKeyid) if l > 0 { var rid string // Force the local id to be all uppercase lid := strings.ToUpper(*flagKeyid) // check the number of chars on the remote id to see if it's a // short or long id. If it's not 8 or 16, it's not valid. switch l { case 8: rid = signer.PrimaryKey.KeyIdShortString() case 16: rid = signer.PrimaryKey.KeyIdString() } if len(rid) == 0 { fmt.Printf("You did not specify a valid GPG keyid length. Must be 8 or 16 characters.") os.Exit(2) } if lid != rid { fmt.Printf("The remote file was not signed by the expected GPG Public key. Expected %s and got %s\n", lid, rid) os.Exit(2) } } // Due to how clearsign works, the detached signature has to be // processed using the Bytes field, but the stripped content is located // in the Plaintext field. As we've verified the signature was valid // we can now fix the content if *flagClear { file.content = cs.Plaintext } state.success = true return state, nil }