def encode_ascii_armor(data, crc=None): if crc is None: crc = crc24(bytearray(data)) crc = crc.to_bytes(3, "big") crc = base64.b64encode(crc).decode("ascii") data = base64.b64encode(data).decode("ascii") data = "\n".join(data[i:i + 64] for i in range(0, len(data), 64)) return PGP_ARMOR_BASE.format(data, crc)
def test_crc24(self): self.assertEqual(0xb704ce, crc24(bytearray(b""))) self.assertEqual(0x21cf02, crc24(bytearray(b"123456789"))) self.assertEqual(0xe84567, crc24(repeat(0, 1024 * 1024)))
def post_save(self, sender, instance, created, **kwargs): if created: data = instance.file.read() pgp = None try: pgp = pgpdump.AsciiData(data) except PgpdumpException: pgp = pgpdump.BinaryData(data) instance.file.save(instance.file.name, ContentFile(pgp.data)) crc = crc24(pgp.data) crc_bin = crc.to_bytes(3, "big") instance.crc24 = base64.b64encode(crc_bin).decode("utf-8") instance.save() # parse packets index = 0 last_pubkey = None last_userid = None for packet in pgp.packets(): index += 1 if (not isinstance(packet, PublicKeyPacket) and not isinstance(packet, UserIDPacket) and not isinstance(packet, SignaturePacket)): continue if isinstance(packet, PublicKeyPacket): is_sub = isinstance(packet, PublicSubkeyPacket) creation_time = make_aware(packet.creation_time, utc) expir = None if packet.expiration_time is not None: expir = make_aware(packet.expiration_time, utc) algo = packet.raw_pub_algorithm bits = 0 if algo in (1, 2, 3): bits = len(bin(packet.modulus)[2:]) elif algo == 17: bits = len(bin(packet.prime)[2:]) elif algo in (16, 20): bits = len(bin(packet.prime)[2:]) fingerprint = packet.fingerprint.lower().decode('utf-8') keyid = packet.key_id.lower().decode('utf-8') last_pubkey = PGPPublicKeyModel.objects.create( index=index, key=instance, is_sub=is_sub, creation_time=creation_time, expiration_time=expir, algorithm=algo, bits=bits, fingerprint=fingerprint, keyid=keyid) elif isinstance(packet, UserIDPacket): userid = packet.data.decode("utf-8") last_userid = PGPUserIDModel.objects.create(index=index, key=instance, userid=userid) elif isinstance(packet, SignaturePacket) and last_userid: creation_time = make_aware(packet.creation_time, utc) expir = None if packet.expiration_time is not None: expir = make_aware(packet.expiration_time, utc) keyid = packet.key_id.lower().decode('utf-8') PGPSignatureModel.objects.create( index=index, key=instance, pkey=last_pubkey, userid=last_userid, type=packet.raw_sig_type, pka=packet.raw_pub_algorithm, hash=packet.raw_hash_algorithm, creation_time=creation_time, expiration_time=expir, keyid=keyid)
# Only keep the first uid, self-signatures, and public keys/subkeys if isinstance(packet, UserIDPacket): if has_uid: continue has_uid = True elif isinstance(packet, SignaturePacket): if (packet.key_id not in keys and packet.raw_sig_type not in (0x18, 0x19)): continue elif isinstance(packet, (PublicKeyPacket, PublicSubkeyPacket)): keys.append(packet.key_id) else: continue # RFC 4880, 4.2 tag = 0x80 | (packet.raw << 2) | length_type data.append(bytes(bytearray((tag, )))) data.append(bytes(length)) data.append(bytes(packet.data)) data = b''.join(data) crc = struct.pack('>i', crc24(bytearray(data)))[1:] data = base64.b64encode(data).decode('ascii') print('-----BEGIN PGP PUBLIC KEY BLOCK-----') print() for off in range(0, len(data), 64): print(data[off:off + 64]) print('={}'.format(base64.b64encode(crc).decode('ascii'))) print('-----END PGP PUBLIC KEY BLOCK-----')
def test_crc24(self): self.assertEqual(0xB704CE, crc24(bytearray(b""))) self.assertEqual(0x21CF02, crc24(bytearray(b"123456789"))) self.assertEqual(0xE84567, crc24(repeat(0, 1024 * 1024)))