Example #1
0
/*
  Reads and returns the next DER encoded SEQUENCE from r,
  which may optionally be base64 encoded and may be preceded
  by "garbage". The returned data will always be DER bytes
  without preceding garbage and NOT base64 encoded.
  The SEQUENCE will only be recognized as valid if
  it does not contain APPLICATION or PRIVATE tags or
  tags >= 31.
  This function takes care not to read more bytes than
  necessary which allows the function to be called
  multiple times on a stream of concatenated SEQUENCEs.
*/
func ReadNextSEQUENCE(r io.Reader) ([]byte, error) {
	b := []byte{0}
	var err error
	var n int
	space := true
	var eaters deque.Deque
	for {
		n, err = r.Read(b)
		if err != nil {
			return nil, err
		}
		if n == 0 {
			return nil, io.EOF
		}
		if b[0] == 0x30 { // SEQUENCE
			eaters.Push(newRawEater())
		}
		if b[0] > ' ' {
			if space {
				eaters.Push(newBase64Eater())
			}
			space = false
		} else {
			space = true
		}

		for i := 0; i < eaters.Count(); {
			result := eaters.At(i).(eater).Eat(b[0])
			switch result {
			case -1: // error
				eaters.RemoveAt(i)
			case 0: // ok, need more data
				i++
			case 1: // done
				return eaters.At(i).(eater).Data(), nil
			}
		}
	}
}