def extractAlgoAndDigest(checksum):
  """Given a checksum string formatted as ``<algo>:<digest>`` returns
  the tuple ``(algo, digest)``.

  ``<algo>`` is expected to be `SHA256`, `SHA512`, or `MD5`.
  ``<digest>`` is expected to be the full length hexdecimal digest.

  :raises ValueError: if checksum is incorrectly formatted.
  """
  if checksum is None:
    return None, None
  if len(checksum.split(':')) != 2:
    raise ValueError("invalid checksum '%s'. Expected format is '<algo>:<digest>'." % checksum)
  (algo, digest) = checksum.split(':')
  expected_algos = ['SHA256', 'SHA512', 'MD5']
  if algo not in expected_algos:
    raise ValueError("invalid algo '%s'. Algo must be one of %s" % (algo, ", ".join(expected_algos)))
  expected_digest_length = {'SHA256': 64, 'SHA512': 128, 'MD5': 32}
  if len(digest) != expected_digest_length[algo]:
    raise ValueError("invalid digest length %d. Expected digest length for %s is %d" % (len(digest), algo, expected_digest_length[algo]))
  return algo, digest