## read_json_old is just version before rbasak's patch
$ wget http://cloud-images.ubuntu.com/releases/streams/v1/com.ubuntu.cloud:released:download.sjson -O download.sjson
$ python ./go.py download.sjson
python at version: 2.7
pulled 1996100 bytes from download.sjson
read_signed: 0.113544940948
read_signed_old: 30.1770660877
$ python3 ./go.py download.sjson
python at version: 3.5
pulled 1996100 bytes from download.sjson
read_signed: 0.07613730430603027
read_signed_old: 6.195951700210571
$ cat go.py
#!/usr/bin/python3
from simplestreams.util import read_signed_old, read_signed, read_url
import sys
import time
url = sys.argv[1]
content = read_url(sys.argv[1]).decode()
sys.stdout.write("python at version: %d.%d\n" %
(sys.version_info.major, sys.version_info.minor))
sys.stdout.write("pulled %d bytes from %s\n" % (len(content), url))
keyring = None
if len(sys.argv) > 2:
keyring = sys.argv[2]
now = time.time()
for f in read_signed, read_signed_old:
sys.stdout.write("%s: " % f.__name__,)
before = time.time()
f(content, keyring)
sys.stdout.write("%s\n" % (time.time() - before))
=== modified file 'simplestreams/util.py'
--- simplestreams/util.py 2016-05-11 10:38:34 +0000
+++ simplestreams/util.py 2016-05-12 15:59:00 +0000
@@ -267,6 +267,55 @@
_HAS_GPGV = False
return _HAS_GPGV
+def read_signed_old(content, keyring=None, checked=True):
+ # ensure that content is signed by a key in keyring.
+ # if no keyring given use default.
+ if content.startswith(PGP_SIGNED_MESSAGE_HEADER):
+ if checked and keyring and has_gpgv():
+ cmd = ["gpgv", "--keyring=%s" % keyring, "-"]
+ elif checked:
+ # http://rfc-ref.org/RFC-TEXTS/2440/chapter7.html
+ cmd = ["gpg", "--batch", "--verify"]
+ if keyring:
+ cmd.append("--keyring=%s" % keyring)
+ cmd.append("-")
+ if checked:
+ try:
+ subp(cmd, data=content)
+ except subprocess.CalledProcessError as e:
+ LOG.debug("failed: %s\n out=%s\n err=%s" %
+ (' '.join(cmd), e.output[0], e.output[1]))
+ raise e
+
+ ret = {'body': '', 'signature': '', 'garbage': ''}
+ lines = content.splitlines()
+ i = 0
+ for i in range(0, len(lines)):
+ if lines[i] == PGP_SIGNED_MESSAGE_HEADER:
+ mode = "header"
+ continue
+ elif mode == "header":
+ if lines[i] != "":
+ mode = "body"
+ continue
+ elif lines[i] == PGP_SIGNATURE_HEADER:
+ mode = "signature"
+ continue
+ elif lines[i] == PGP_SIGNATURE_FOOTER:
+ mode = "garbage"
+ continue
+
+ # dash-escaped content in body
+ if lines[i].startswith("- ") and mode == "body":
+ ret[mode] += lines[i][2:] + "\n"
+ else:
+ ret[mode] += lines[i] + "\n"
+
+ return ret['body']
+ else:
+ raise SignatureMissingException("No signature found!")
+
+
def read_signed(content, keyring=None, checked=True):
# ensure that content is signed by a key in keyring.