Skip to content

Instantly share code, notes, and snippets.

@mRB0
Last active August 27, 2018 12:36
Show Gist options
  • Save mRB0/64b0499408b88803961aa6eea14d9bb8 to your computer and use it in GitHub Desktop.
Save mRB0/64b0499408b88803961aa6eea14d9bb8 to your computer and use it in GitHub Desktop.
Jython scripts to encrypt and decrypt symmetrically using OpenPGP format using BouncyCastle
#!/usr/bin/env jython
import sys
sys.path.append('bcprov-jdk15on-160.jar')
sys.path.append('bcpg-jdk15on-160.jar')
import itertools
from org.python.core.io import StreamIO
import jarray
from java.nio.charset import Charset
from java.util import Date
from org.bouncycastle.openpgp import *
from org.bouncycastle.openpgp.bc import *
from org.bouncycastle.openpgp.operator import *
from org.bouncycastle.openpgp.operator.bc import *
from org.bouncycastle.bcpg import *
def objectFactoryIterator(objectFactory):
try:
yield objectFactory.nextObject()
except e:
print("(error getting object: {})", e)
def dprint(depth, what):
print(" " * depth + what)
compressionTypes = {
CompressionAlgorithmTags.BZIP2: "bzip2",
CompressionAlgorithmTags.UNCOMPRESSED: "uncompressed",
CompressionAlgorithmTags.ZIP: "zip",
CompressionAlgorithmTags.ZLIB: "zlib"
}
formatTags = {
ord(PGPLiteralData.BINARY): "binary",
ord(PGPLiteralData.TEXT): "text",
ord(PGPLiteralData.UTF8): "utf-8 text"
}
class Decryptor(object):
def __init__(self, filename, passphrase):
self.decryptedCount = 0
self.passphrase = passphrase
self.filename = filename
with open(self.filename, 'rb') as inputFile:
objectFactory = BcPGPObjectFactory(inputFile)
self.handleObjectFactory(0, objectFactory)
def handleObjectFactory(self, depth, objectFactory):
for i, pgpObj in enumerate(objectFactoryIterator(objectFactory)):
dprint(depth, "Object {} is a {!r}".format(i, pgpObj))
self.handlePGPObject(depth + 1, pgpObj)
def handlePBEEncryptedData(self, depth, encryptedData):
dprint(depth, "Decrypt")
clearDataStream = encryptedData.getDataStream(BcPBEDataDecryptorFactory(self.passphrase, BcPGPDigestCalculatorProvider()))
try:
self.handleObjectFactory(depth + 1, BcPGPObjectFactory(clearDataStream))
finally:
clearDataStream.close()
if encryptedData.isIntegrityProtected():
dprint(depth, "Encrypted data was integrity protected; valid = {}".format(encryptedData.verify()))
def handleCompressedData(self, depth, compressedData):
algorithm = compressedData.getAlgorithm()
dprint(depth, "Uncompress compressed data (algorithm={})".format(compressionTypes.get(algorithm, algorithm)))
uncompressedDataStream = compressedData.getDataStream()
try:
self.handleObjectFactory(depth + 1, BcPGPObjectFactory(uncompressedDataStream))
finally:
uncompressedDataStream.close()
def handleLiteralData(self, depth, literalData):
formatTag = literalData.getFormat()
dprint(depth, "Literal data, format={}, modified={}".format(
formatTags.get(formatTag, formatTag),
literalData.getModificationTime())
)
inputStream = literalData.getInputStream()
try:
filename = "/tmp/decrypted{}".format("" if self.decryptedCount == 0 else "-{}".format(self.decryptedCount + 1))
with open(filename, 'wb') as outputFile:
buf = jarray.zeros(2048, 'b')
totalBytesRead = 0
for bytesRead in itertools.takewhile(lambda br: br != -1, (inputStream.read(buf) for _ in itertools.repeat(0))):
outputFile.write(buf[0:bytesRead])
totalBytesRead += bytesRead
self.decryptedCount += 1
dprint(depth, "Saved {} bytes to {}".format(totalBytesRead, filename))
finally:
inputStream.close()
def handlePGPObject(self, depth, pgpObj):
dprint(depth, "Handle {!r}".format(pgpObj))
if isinstance(pgpObj, PGPEncryptedDataList):
for encryptedData in pgpObj:
self.handlePGPObject(depth + 1, encryptedData)
elif isinstance(pgpObj, PGPPBEEncryptedData):
self.handlePBEEncryptedData(depth + 1, pgpObj)
elif isinstance(pgpObj, PGPCompressedData):
self.handleCompressedData(depth + 1, pgpObj)
elif isinstance(pgpObj, PGPLiteralData):
self.handleLiteralData(depth + 1, pgpObj)
else:
dprint(depth, "Skipping unsupported PGP object {!r}".format(pgpObj))
def decrypt(filename, passphrase):
Decryptor(filename, passphrase)
if __name__ == '__main__':
if len(sys.argv) < 3:
print("usage: {} encryptedFile passphrase".format(sys.argv[0]))
else:
decrypt(sys.argv[1], sys.argv[2])
#!/usr/bin/env jython
from __future__ import division
import sys
sys.path.append('bcprov-jdk15on-160.jar')
sys.path.append('bcpg-jdk15on-160.jar')
import os
import itertools
from java.nio.charset import Charset
from java.util import Date
from org.bouncycastle.openpgp import PGPEncryptedDataGenerator, PGPCompressedDataGenerator, PGPLiteralDataGenerator
from org.bouncycastle.bcpg import SymmetricKeyAlgorithmTags
from org.bouncycastle.openpgp.operator.bc import BcPBEKeyEncryptionMethodGenerator, BcPGPDataEncryptorBuilder
bufferSize = 65536
def encrypt(filename, outputFile, passphrase):
builder = BcPGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.AES_256)
builder.setWithIntegrityPacket(True)
generator = PGPEncryptedDataGenerator(builder)
encryptionMethod = BcPBEKeyEncryptionMethodGenerator(passphrase)
generator.addMethod(encryptionMethod)
def writeFile(outputStream):
with open(filename, 'rb') as inFile:
totalBytesRead = 0
fileSize = os.path.getsize(filename)
for data in itertools.takewhile(lambda b: b, (inFile.read(bufferSize) for _ in itertools.repeat(0))):
outputStream.write(data)
totalBytesRead += len(data)
print("{}/{} ({:.2f}%)".format(totalBytesRead, fileSize, totalBytesRead / fileSize * 100))
import jarray
buf = jarray.zeros(bufferSize, 'b')
print("Writing to {}".format(outputFile))
with open(outputFile, 'wb') as outputFile:
generatorStream = generator.open(outputFile, buf)
try:
compressorStream = PGPCompressedDataGenerator(PGPCompressedDataGenerator.ZIP).open(generatorStream)
try:
buf2 = jarray.zeros(bufferSize, 'b')
literalStream = PGPLiteralDataGenerator().open(compressorStream, PGPLiteralDataGenerator.BINARY, os.path.basename(filename), Date(), buf2)
try:
writeFile(literalStream)
finally:
literalStream.close()
finally:
compressorStream.close()
finally:
generatorStream.close()
if __name__ == '__main__':
if len(sys.argv) < 4:
print("usage: {} plaintextFile outputFile passphrase".format(sys.argv[0]))
else:
encrypt(sys.argv[1], sys.argv[2], sys.argv[3])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment