diff --git a/contrib/crypto/cmsdetach b/contrib/crypto/cmsdetach index fdd888958..a48d30c67 100755 --- a/contrib/crypto/cmsdetach +++ b/contrib/crypto/cmsdetach @@ -7,8 +7,9 @@ message into a separate file. """ import argparse +from pathlib import Path -import asn1 +from asn1crypto.cms import ContentInfo, AuthEnvelopedData, EnvelopedData # Parse command-line arguments # @@ -16,64 +17,45 @@ parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter, ) -parser.add_argument("-d", "--data", metavar="FILE", +parser.add_argument("-d", "--data", metavar="FILE", type=Path, help="Write detached data (without envelope) to FILE") -parser.add_argument("-e", "--envelope", metavar="FILE", +parser.add_argument("-e", "--envelope", metavar="FILE", type=Path, help="Write envelope (without data) to FILE") parser.add_argument("-o", "--overwrite", action="store_true", help="Overwrite output files") -parser.add_argument("file", help="Input envelope file") +parser.add_argument("file", type=Path, help="Input envelope file") args = parser.parse_args() if args.data is None and args.envelope is None: parser.error("at least one of --data and --envelope is required") outmode = "wb" if args.overwrite else "xb" -# Create decoder +# Read input envelope # -decoder = asn1.Decoder() -with open(args.file, mode="rb") as fh: - decoder.start(fh.read()) +envelope = ContentInfo.load(args.file.read_bytes()) -# Create encoder +# Locate encrypted content info # -encoder = asn1.Encoder() -encoder.start() - -# Detach encrypted data -# -data = None -datastack = [ - asn1.Numbers.Sequence, 0, asn1.Numbers.Sequence, asn1.Numbers.Sequence -] -stack = [] -while stack or not decoder.eof(): - tag = decoder.peek() - if tag is None: - encoder.leave() - decoder.leave() - stack.pop() - elif tag.typ == asn1.Types.Constructed: - encoder.enter(nr=tag.nr, cls=tag.cls) - decoder.enter() - stack.append(tag.nr) - else: - (tag, value) = decoder.read() - if stack == datastack and tag.nr == 0: - data = value - else: - encoder.write(value, nr=tag.nr, cls=tag.cls) -envelope = encoder.output() -if data is None: +content = envelope["content"] +if type(content) is AuthEnvelopedData: + encinfo = content["auth_encrypted_content_info"] +elif type(content) is EnvelopedData: + encinfo = content["encrypted_content_info"] +else: parser.error("Input file does not contain any encrypted data") +# Detach encrypted content data +# +data = encinfo["encrypted_content"] +del encinfo["encrypted_content"] + # Write envelope (without data), if applicable # if args.envelope: - with open(args.envelope, mode=outmode) as fh: - fh.write(envelope) + with args.envelope.open(mode=outmode) as fh: + fh.write(envelope.dump()) # Write data (without envelope), if applicable # if args.data: - with open(args.data, mode=outmode) as fh: - fh.write(data) + with args.data.open(mode=outmode) as fh: + fh.write(data.contents)