Is there a way to load a crypted file (that is a jar file), decrypted it (so obtains the real byte array) and use it without create a file on filesystem and launch it?
byte[] jarBytes=Decrypter.decrypt("my\\encrypted\\jar\\file");
//use jarBytes to execute an application without create a real File with this bytes...
Sure.
The input stream can come from a resource (i.e., on the classpath). The bytes can be manipulated as required.
See this post for an example of loading the jar from a directory. Your version would be almost identical, except for where the bytes come from originally, and with an additional transformation step.
If anybody is that interested in your code they'll either just a) reverse-engineer your class loader, or b) just use your class loader as-is and not worry about reverse-engineering the encrypted code... but good luck anyway :)
Like this?
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decValue = c.doFinal(data);
Related
Have to begin moving in-house, local machine only Java framework into a private but online repo for staff only, however, the current framework requires a properties class which includes sensitive information (usernames, passwords etc) to login to the database and other technology the framework uses.
As a result, pushing the latest framework will include all of said individuals usernames/passwords, which is a security concern.
I've been asked to "Encrypt the password so when it's uploaded it's hidden" and then "Decrypt the password during runtime, so that information can be used to execute the code, as without the login data, the framework will not work".
While there is much better solutions (ie just don't upload the properties class, rework framework to not need the properties class etc), this is apparently unacceptable as it "works this way".
I'm struggling on the logic of this request, but furthermore how this task could actually be accomplished.
There's a few solutions I pinged about having it in a private notepad on your system only, but again apparently unacceptable.
It "needs to just be within a new Java Class".
Is this request possible, and if so, what sort of approach could I take? So the sensitive information within the properties class is encrypted if someone downloads the framework, but when executed, that information is decrypted and the framework runs. Framework is being uploaded to Bitbucket.
(Not asking for the code, just asking for help working out how this could be achieved, if at all, because it seems to be a very strange request or am I missing something?)
Here is the snippet to upload your data to the server. os must be a valid output stream used for upload.
OutputStream os = ... /* your upload stream */
OutputStream gzipos = new GZIPOutputStream(os);
CryptoAlgorithm = "RSA";
Cipher cipher = Cipher.getInstance(CryptoAlgorithm);
cipher.init(Cipher.ENCRYPT_MODE, PuK);
CipherOutputStream cos = new CipherOutputStream(gzipos, cipher);
DataOutputStream dos = new DataOutputStream(cos);
dos.write... /* use it as a normal data output stram /*
I use DataOutputStream because I used binary data in my implementation. Still, you can also use a normal writer:
Writer w = new OutputStreamWriter(cos);
And, for the download snippet:
CryptoAlgorithm = "RSA";
...
Cipher cipher = Cipher.getInstance(CryptoAlgorithm);
cipher.init(Cipher.DECRYPT_MODE, PK);
CipherInputStream cis = new CipherInputStream(new GZIPInputStream(is), cipher);
DataInputStream dis = new DataInputStream(cis);
If you used a writer, obviously you'll need to change the last declaration accordingly:
Reader r = new InputStreamReader(cis);
Of course you need a Key Pair of
PrivateKey PK;
PublicKey Puk;
Those two needs to be saved locally (you need to chose how to, just google it and chose how you want to save them, there're several options).
Now, not knowing how well you know RSA, I'll explain a couple of things:
IMPORTANT before goint to production make sure to have your key pair saved and backupped! Multiple times in different media, if possible. If you lose those keys, your data becomes unreadable, thus lost forever!
Really, protect those keys with evertything you've got!
you use the PublicKey to crypt because this way only those who have the private key can uncrypt it, because, normally, you can distribute the PublicKey, and everybody with the public key can decrypt what was crypted with the PriveteKey. This is used for electronic signatures because only the owner of the PrivateKey can write a document that can be opened with the relative PublicKey. On the opposite, everybody can use the PublicKey to cipher a document but only the one with the associated private key can read it. That's why, if you store protected data, you use the public key to cipher and the private to uncipher. Right now it doesn't matter to you, but better be prepared for the future.
you can use the algorithm you fancy, but the most used is RSA and it's the one you can find the most informations on.
I compress the data before chiphering it not for saving space, but to maximize the randomization of the data, thus making harder to brute-force decipher them. Still, there's a problem: GZip protocol puts GZ before any file compressed with said protocol as signature. You can manually remove that signature before ciphering and add it manually after deciphering, but it become a little more complex to handle. You can bypass the compression part if you want (or find another algorithm to compress/uncompress).
I was given a public key id, and being asked to use this public key id to encrypt a .txt file. I can find a reference on how to perform this, but in C# language using Bouncycastle and nothing with Java.
The specific public key id is provided by the encrypted-file recipient. Decryption is done by the encrypted-file recipient, therefore I have no concern on any decryption or private key id, if these info are essential which is beyond my knowledge for time being.
I am using Java and very new with encryption, please direct me to any LATEST java application examples or tutorial that encrypt a text file using specific public key id given instead of generated ones. Thanks!
You can use „raw“ Bouncy Castle for Java or one of several wrappers around the API. For using Bouncy Castle you need to understand the OpenPGP RFC (rfc4880).
Alternatively you can use existing wrappers like e.g. Bouncy GPG:
final String original_message = "I love deadlines. I like the whooshing sound they make as they fly by. Douglas Adams";
// Most likely you will use one of the KeyringConfigs.... methods.
// These are wrappers for the test.
KeyringConfig keyringConfigOfSender = Configs
.keyringConfigFromResourceForSender();
ByteArrayOutputStream result = new ByteArrayOutputStream();
try (
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(result, 16384 * 1024);
final OutputStream outputStream = BouncyGPG
.encryptToStream()
.withConfig(keyringConfigOfSender)
.withStrongAlgorithms()
.toRecipients("recipient#example.com", "sender#example.com")
.andSignWith("sender#example.com")
.binaryOutput()
.andWriteTo(bufferedOutputStream);
// Maybe read a file or a webservice?
final ByteArrayInputStream is = new ByteArrayInputStream(original_message.getBytes())
) {
Streams.pipeAll(is, outputStream);
// It is very important that outputStream is closed before the result stream is read.
// The reason is that GPG writes the signature at the end of the stream.
// This is triggered by closing the stream.
// In this example outputStream is closed via the try-with-resources mechanism of Java
}
result.close();
byte[] chipertext = result.toByteArray();
I'm have encrypted a text file on Linux using:
gpg --cipher-algo AES256 -c file.txt
That command asks for a passphrase, let's say we enter "123" here.
This file can be trivially decrypted:
gpg -d file.txt.gpg
Now I like to decrypt this file in Java, but can't quite find out how to do this using the passphrase "123". Specifically, it's not entirely clear what the salt and initial vector is, and what else is needed.
GnuPG implements the OpenPGP protocol, which is not directly support by Java's native classes. OpenPGP has its own file format, but also uses a slightly different variant of the CFB mode.
Instead of implementing all that on your own, better go for the Bouncy Castle library. It also provides an example how to decrypt a symmetrically encrypted message, which boils down to those relevant calls to decrypt an OutputStream out (some more code to determine the used algorithm parameter and compression is also provided in the linked example):
PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(
new JcePGPDataEncryptorBuilder(algorithm).setSecureRandom(
new SecureRandom()).setProvider("BC"));
encGen.addMethod(
new JcePBEKeyEncryptionMethodGenerator(passPhrase).setProvider("BC"));
OutputStream encOut = encGen.open(out, compressedData.length);
I've got this function that encrypts a file, the encryption bit seems to be working, but i can't get it to overwrite the current file.
FileInputStream inputStream = new FileInputStream(input); // Selects file to encrypt
cipher.init(Cipher.ENCRYPT_MODE, secret, ivSpec); // Sets up the encryption
// Creates an the output stream, the encryption is performed here
CipherOutputStream cos = new CipherOutputStream(new FileOutputStream(input + ".secure"), cipher);
byte[] block = new byte[8];
int i;
while ((i = inputStream.read(block)) != -1) // Reads the file
{
cos.write(block, 0, i); // Writes the new file
}
cos.close();
This is working fine, i end up with an encrypted file with original_file_name.txt.secure, but i want it to overwrite the original file. If i remove the .secure bit it doesn't write the file properly.
How can I overwrite the file original file with the encrypted text?
If you remove the .secure part, you'll be trying to read from the file at the same time that you're writing to it. This is not a very good idea...
The best approach would be to do as you've done, and then if all has gone well, you can delete the original file and rename the old one to match its name, using Files.move().
In fact, if you pass the right options to Files.move(), you can get it to overwrite the existing file, meaning that you won't need to delete the original first.
This solves the simultaneous read/write problem you're having, but it's also a whole lot safer for an application like this. If your application crashes or there's a power cut in the middle of encrypting, and you're encrypting in place, then you're completely screwed. If you do it this way, then power failure in the middle still leaves you with your old file intact. You'll always have the complete old file around until the complete new file is ready.
By the way, you should make use of a BufferedInputStream too, rather than just using a raw FileInputStream. And I can't see an inputStream.close() anywhere.
I have an encryption algorithm (AES) that accepts a file converted to array byte and encrypt it.
Since I am going to process a very large files, the JVM may go out of memory.
I am planing to read the files in multiple byte arrays, each containing some part of the file. Then I iteratively feed the algorithm. Finally, I merge them to produce an encrypted file.
So my question is: Is there any way to read a file part by part to multiple byte arrays?
I thought I could use the following to read the file to a byte array:
IOUtils.toByteArray(InputStream input).
And then split the array into multiple bytes using:
Arrays.copyOfRange()
But I am afraid that the code that reads a file to ByteArray will make the JVM to go out of memory.
Look up cipher streams in Java. You can use them to encrypt/decrypt streams on the fly so you don't have to store the whole thing in memory. All you have to do is copy the regular FileInputStream for your source file to the CipherOutputStream that's wrapping your FileOutputStream for the encrypted sink file. IOUtils even conveniently contains a copy(InputStream, OutputStream) method to do this copy for you.
For example:
public static void main(String[] args) {
encryptFile("exampleInput.txt", "exampleOutput.txt");
}
public static void encryptFile(String source, String sink) {
FileInputStream fis = null;
try {
fis = new FileInputStream(source);
CipherOutputStream cos = null;
try {
cos = new CipherOutputStream(new FileOutputStream(sink), getEncryptionCipher());
IOUtils.copy(fis, cos);
} finally {
if (cos != null)
cos.close();
}
} finally {
if (fis != null)
fis.close();
}
}
private static Cipher getEncryptionCipher() {
// Create AES cipher with whatever padding and other properties you want
Cipher cipher = ... ;
// Create AES secret key
Key key = ... ;
cipher.init(Cipher.ENCRYPT_MODE, key);
}
If you need to know the number of bytes that were copied, you can use IOUtils.copyLarge instead of IOUtils.copy if the file sizes exceed Integer.MAX_VALUE bytes (2 GB).
To decrypt the file, do the same thing, but use CipherInputStream instead ofCipherOutputStream and initialize your Cipher using Cipher.DECRYPT_MODE.
Take a look here for more info on cipher streams in Java.
This will save you space because you won't need to store byte arrays of your own anymore. The only stored byte[] in this system is the internal byte[] of the Cipher, which will get cleared each time enough input is entered and an encrypted block is returned by Cipher.update, or on Cipher.doFinal when the CipherOutputStream is closed. However, you don't have to worry about any of this since it's all internal and everything is managed for you.
Edit: note that this can result in certain encryption exceptions being ignored, particularly BadPaddingException and IllegalBlockSizeException. This behavior can be found in the CipherOutputStream source code. (Granted, this source is from the OpenJDK, but it probably does the same thing in the Sun JDK.) Also, from the CipherOutputStream javadocs:
This class adheres strictly to the semantics, especially the failure semantics, of its ancestor classes java.io.OutputStream and java.io.FilterOutputStream. This class has exactly those methods specified in its ancestor classes, and overrides them all. Moreover, this class catches all exceptions that are not thrown by its ancestor classes.
The bolded line here implies that the cryptographic exceptions are ignored, which they are. This may cause some unexpected behavior while trying to read an encrypted file, especially for block and/or padding encryption algorithms like AES. Make a mental note of this that you will get zero or partial output for the encrypted (or decrypted for CipherInputStream) file.
If you're using IOUtils, perhaps you should consider IOUtils.copyLarge()
public static long copyLarge(InputStream input,
OutputStream output,
long inputOffset,
long length)
and specify a ByteArrayOutputStream as the output. You can then iterate through and load sections of your file using offset/length.
From the doc:
Copy some or all bytes from a large (over 2GB) InputStream to an
OutputStream, optionally skipping input bytes.