/* ************************************************************************ # # DivConq # # http://divconq.com/ # # Copyright: # Copyright 2014 eTimeline, LLC. All rights reserved. # # License: # See the license.txt file in the project's top-level directory for details. # # Authors: # * Andy White # ************************************************************************ */ package divconq.pgp; import io.netty.buffer.ByteBuf; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.file.Path; import java.nio.file.Paths; import java.security.NoSuchProviderException; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import org.bouncycastle.bcpg.HashAlgorithmTags; import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; import org.bouncycastle.openpgp.PGPException; /** * Basic utility class, borrowed from Bouncy Castle since it was not * public access. * */ public class PGPUtil { public static String getDigestName( int hashAlgorithm) throws PGPException { switch (hashAlgorithm) { case HashAlgorithmTags.SHA1: return "SHA1"; case HashAlgorithmTags.MD2: return "MD2"; case HashAlgorithmTags.MD5: return "MD5"; case HashAlgorithmTags.RIPEMD160: return "RIPEMD160"; case HashAlgorithmTags.SHA256: return "SHA256"; case HashAlgorithmTags.SHA384: return "SHA384"; case HashAlgorithmTags.SHA512: return "SHA512"; case HashAlgorithmTags.SHA224: return "SHA224"; case HashAlgorithmTags.TIGER_192: return "TIGER"; default: throw new PGPException("unknown hash algorithm tag in getDigestName: " + hashAlgorithm); } } public static String getSignatureName( int keyAlgorithm, int hashAlgorithm) throws PGPException { String encAlg; switch (keyAlgorithm) { case PublicKeyAlgorithmTags.RSA_GENERAL: case PublicKeyAlgorithmTags.RSA_SIGN: encAlg = "RSA"; break; case PublicKeyAlgorithmTags.DSA: encAlg = "DSA"; break; case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT: // in some malformed cases. case PublicKeyAlgorithmTags.ELGAMAL_GENERAL: encAlg = "ElGamal"; break; default: throw new PGPException("unknown algorithm tag in signature:" + keyAlgorithm); } return getDigestName(hashAlgorithm) + "with" + encAlg; } public static String getSymmetricCipherName( int algorithm) { switch (algorithm) { case SymmetricKeyAlgorithmTags.NULL: return null; case SymmetricKeyAlgorithmTags.TRIPLE_DES: return "DESEDE"; case SymmetricKeyAlgorithmTags.IDEA: return "IDEA"; case SymmetricKeyAlgorithmTags.CAST5: return "CAST5"; case SymmetricKeyAlgorithmTags.BLOWFISH: return "Blowfish"; case SymmetricKeyAlgorithmTags.SAFER: return "SAFER"; case SymmetricKeyAlgorithmTags.DES: return "DES"; case SymmetricKeyAlgorithmTags.AES_128: return "AES"; case SymmetricKeyAlgorithmTags.AES_192: return "AES"; case SymmetricKeyAlgorithmTags.AES_256: return "AES"; case SymmetricKeyAlgorithmTags.CAMELLIA_128: return "Camellia"; case SymmetricKeyAlgorithmTags.CAMELLIA_192: return "Camellia"; case SymmetricKeyAlgorithmTags.CAMELLIA_256: return "Camellia"; case SymmetricKeyAlgorithmTags.TWOFISH: return "Twofish"; default: throw new IllegalArgumentException("unknown symmetric algorithm: " + algorithm); } } static public SecretKey makeSymmetricKey( int algorithm, byte[] keyBytes) throws PGPException { String algName = getSymmetricCipherName(algorithm); if (algName == null) { throw new PGPException("unknown symmetric algorithm: " + algorithm); } return new SecretKeySpec(keyBytes, algName); } static public void encryptFile(String outputFileName, String inputFileName, String encKeyFileName) throws IOException, NoSuchProviderException, PGPException { Path fileIn = Paths.get(inputFileName); Path fileOut = Paths.get(outputFileName); Path fileKey = Paths.get(encKeyFileName); OutputStream out = new BufferedOutputStream(new FileOutputStream(fileOut.toFile())); try { EncryptedFileStream pw = new EncryptedFileStream(); //pw.setAlgorithm(SymmetricKeyAlgorithmTags.NULL); pw.setFileName(fileIn.getFileName().toString()); pw.loadPublicKey(fileKey); pw.init(); FileInputStream in = new FileInputStream(fileIn.toFile()); byte[] ibuf = new byte[31 * 1024]; int len; while ((len = in.read(ibuf)) > 0) { pw.writeData(ibuf, 0, len); ByteBuf buf = pw.nextReadyBuffer(); while (buf != null) { out.write(buf.array(), buf.arrayOffset(), buf.readableBytes()); buf.release(); buf = pw.nextReadyBuffer(); } } in.close(); pw.close(); ByteBuf buf = pw.nextReadyBuffer(); while (buf != null) { out.write(buf.array(), buf.arrayOffset(), buf.readableBytes()); buf.release(); buf = pw.nextReadyBuffer(); } out.close(); } catch (Exception e) { System.err.println(e); e.printStackTrace(); } } /* * * TODO develop a packet reader/lister case 110: { byte[] in = Files.readAllBytes(Paths.get("/Work/Temp/Dest/story2.xml.gpg")); int idx = 0; while (idx < in.length) { int hdr = in[idx] & 0xFF; if ((hdr & 0x80) == 0) { System.out.println("invalid header encountered"); break; } boolean newPacket = ((hdr & 0x40) != 0); int tag = 0; int bodyLen = 0; int hdrLen = 1; boolean partial = false; if (newPacket) { tag = hdr & 0x3f; System.out.println("New Packet: " + HexUtil.charToHex(hdr) + " tag: " + tag); int l = in[idx + 1] & 0xFF; if (l < 192) { bodyLen = l; hdrLen = 2; } else if (l <= 223) { int b = in[idx + 2] & 0xFF; bodyLen = ((l - 192) << 8) + (b) + 192; hdrLen = 3; } else if (l == 255) { //bodyLen = (in[idx + 2] << 24) | (in[idx + 3] << 16) | (in[idx + 4] << 8) | in[idx + 5]; bodyLen = ((in[idx + 2] & 0xFF) << 24) | ((in[idx + 3] & 0xFF) << 16) | ((in[idx + 4] & 0xFF) << 8) | (in[idx + 5] & 0xFF); hdrLen = 6; } else { partial = true; bodyLen = 1 << (l & 0x1f); hdrLen = 2; } } else { tag = (hdr & 0x3f) >> 2; System.out.println("Old Packet: " + HexUtil.charToHex(hdr) + " tag: " + tag); int lengthType = hdr & 0x3; switch (lengthType) { case 0: hdrLen = 2; bodyLen = in[idx + 1] & 0xFF; break; case 1: hdrLen = 3; //bodyLen = (in[idx + 1] << 8) | in[idx + 2]; bodyLen = ((in[idx + 1] & 0xFF) << 8) | (in[idx + 2] & 0xFF); break; case 2: hdrLen = 5; //bodyLen = (in[idx + 1] << 24) | (in[idx + 2] << 16) | (in[idx + 3] << 8) | in[idx + 4]; bodyLen = ((in[idx + 1] & 0xFF) << 24) | ((in[idx + 2] & 0xFF) << 16) | ((in[idx + 3] & 0xFF) << 8) | (in[idx + 4] & 0xFF); break; case 3: partial = true; break; default: throw new IOException("unknown length type encountered"); } } System.out.println("- Length: " + bodyLen + " partial: " + partial + " hdr len: " + hdrLen); idx += bodyLen + hdrLen; } System.out.println("end of file"); break; } * */ }