// readArmored reads an armored block with the given type. func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) { block, err := armor.Decode(r) if err != nil { return } if block.Type != expectedType { return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type) } return block.Body, nil }
// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file. func ReadArmoredKeyRing(r io.Reader) (EntityList, error) { block, err := armor.Decode(r) if err == io.EOF { return nil, errors.InvalidArgumentError("no armored data found") } if err != nil { return nil, err } if block.Type != PublicKeyType && block.Type != PrivateKeyType { return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type) } return ReadKeyRing(block.Body) }
// Decode finds the first clearsigned message in data and returns it, as well // as the suffix of data which remains after the message. func Decode(data []byte) (b *Block, rest []byte) { // start begins with a newline. However, at the very beginning of // the byte array, we'll accept the start string without it. rest = data if bytes.HasPrefix(data, start[1:]) { rest = rest[len(start)-1:] } else if i := bytes.Index(data, start); i >= 0 { rest = rest[i+len(start):] } else { return nil, data } // Consume the start line. _, rest = getLine(rest) var line []byte b = &Block{ Headers: make(textproto.MIMEHeader), } // Next come a series of header lines. for { // This loop terminates because getLine's second result is // always smaller than its argument. if len(rest) == 0 { return nil, data } // An empty line marks the end of the headers. if line, rest = getLine(rest); len(line) == 0 { break } i := bytes.Index(line, []byte{':'}) if i == -1 { return nil, data } key, val := line[0:i], line[i+1:] key = bytes.TrimSpace(key) val = bytes.TrimSpace(val) b.Headers.Add(string(key), string(val)) } firstLine := true for { start := rest line, rest = getLine(rest) if bytes.Equal(line, endText) { // Back up to the start of the line because armor expects to see the // header line. rest = start break } // The final CRLF isn't included in the hash so we don't write it until // we've seen the next line. if firstLine { firstLine = false } else { b.Bytes = append(b.Bytes, crlf...) } if bytes.HasPrefix(line, dashEscape) { line = line[2:] } line = bytes.TrimRight(line, " \t") b.Bytes = append(b.Bytes, line...) b.Plaintext = append(b.Plaintext, line...) b.Plaintext = append(b.Plaintext, lf) } // We want to find the extent of the armored data (including any newlines at // the end). i := bytes.Index(rest, end) if i == -1 { return nil, data } i += len(end) for i < len(rest) && (rest[i] == '\r' || rest[i] == '\n') { i++ } armored := rest[:i] rest = rest[i:] var err error b.ArmoredSignature, err = armor.Decode(bytes.NewBuffer(armored)) if err != nil { return nil, data } return b, rest }