How do I encrypt a PGP message through java's crypto extension? - encryption

Currently I'm using bouncy castle's libraries for the actual work and have found an example at sloanseaman.com that (after a little tweaking) works with v1.52.
I've also got a working example from developer.com of how to use the JCE interface and can even drop the bcprov in it and use some of it's algorithms.
public class CryptoUtil {
private static final String ALGORITHM = "IDEA/PGP/NoPadding";
public static void encryptFile(File keyFile, File plainTextFile, File encryptedFile) throws GeneralSecurityException, IOException {
Cipher desCipher = Cipher.getInstance(ALGORITHM);
desCipher.init(Cipher.ENCRYPT_MODE, readKeyFromFile(keyFile));
OutputStream out = new BufferedOutputStream(new FileOutputStream(encryptedFile));
InputStream in = new BufferedInputStream(new FileInputStream(plainTextFile));
while (in.available() > 0) {
// Read the next chunk of bytes...
byte[] cleartextBytes = new byte[in.available()];
in.read(cleartextBytes);
// Now, encrypt them and write them to the encrypted file...
byte[] encryptedBytes = desCipher.update(cleartextBytes);
out.write(encryptedBytes, 0, encryptedBytes.length);
}
// Take care of any pending padding operations
out.write(desCipher.doFinal());
in.close();
out.flush();
out.close();
System.out.println("Encrypted to " + encryptedFile);
}
But no matter what algorithm string I use, I can't get my JCE utility to encrypt the way that the bouncyCastle utility does.
The furthest I've gotten is using "IDEA/PGP/NoPadding" which allows me to encrypt and decrypt within itself, but the BC utility won't decrypt them, saying there's an unknown object in the stream.
Here is my source code
Do you guys know what combination of Algorithm, Mode, and Padding I would need to use for this? Are there other options that I need to apply somehow? I guessing I need to use BC's version of AlgorithmParametersSpi but I haven't figured out how to create that yet

You can't. While OpenPGP uses "normal" public/private and symmetric encryption algorithms, trouble starts with the modes. OpenPGP uses its own mode (a modified CFB mode), and also the whole OpenPGP packet syntax is not supported by Java's default libraries.
You'd at least need to reimplement the OpenPGP CFB mode in Java, or somehow rely on Bouncy Castle's implementation.
The OpenPGP CFB mode already includes a replacement for the initialization vector; no additional padding is used/required.

Related

Can't import ore create X509Certificate2 object from byte array

So I encountered a weird issue while trying importing .pfx file into x509 object.
For some reason, I don't understand, trying opening, or generating new object, in this manner doesn't work.
cert = new X509Certificate2();
cert.Import(byte []);
cert = new X509Certificate2(byte []);
The error I'm getting is:'X509Certificate is immutable on this platform. Use the equivalent constructor instead.'
I saw this issue: https://github.com/jitbit/AspNetSaml/issues/9
the only way I could make it work is to give an explicit path to the .pfx path which worked.
That's not my intention, however.
Any idea?
What should work for you, is one of the constructor overload.
Use the other constructor of X509Certificate2 class which takes two params. First one is the byteArray and second one is the password string.
byte[] certData;
var memorystream = new MemoryStream();
MyMethodToPopluateMemoryStream(memorystream);
certData = memorystream.ToArray();
cert = new X509Certificate2(certData,"CERT_PASSWORD");
This way you can avoid the deprecated Import method.
After few hours of struggle above code worked fine for me. I've tested this code on .net6 .
Happy Coding.

AES Decryption in Solidity Contract

I am trying to create a solidity contract that decrypts a message using the an AES key. The data to be decrypted is saved as a variable in the contract (this data is already encrypted). The user should be able to pass an AES key into the decrypt function, this function should decrypt and return the message.
I do not mind the key being exposed on the network. Would there be any way to achieve this?
Solidity currently (v0.8) doesn't support any of the AES algorithms.
If your goal is to perform an action (e.g. transfer funds) to a user providing the correct key, you could have them calculate a keccak256 (one-way) hash of some secret (e.g. the key) off-chain, and then submit the original key for validation (against the hash stored in the contract).
pragma solidity ^0.8;
contract MyContract {
// keccak256 hash of the string "foo"
bytes32 hash = 0x41b1a0649752af1b28b3dc29a1556eee781e4a4c3a1f7f53f90fa834de098c4d;
function guessThePassword(string memory _password) external view returns (bool) {
return keccak256(abi.encodePacked(_password)) == hash;
}
}
Mind that this approach (as well as your original approach from the question) is vulnerable to frontrunning. One of the ways to prevent frontrunning, is to use double hashing. You can see a code example in this contract that was used for a competition type "first submitting the correct password can withdraw funds".

outofmemoryexception when reading from smart card

I'm using .Net framework to develop an application that interact with Gemalto smart card (adding and retrieving),
I've successively done with the addition part, however when I try to read the data that I stored in the card I got an outOfMemoryException in the host application, can anyone figure out why does this happen?
this is the code in the host application that read from the card:
for (int i = 0; i < 5; i++)
{
try
{
string bookString = service.getBook(i);
}catch (Exception x) {
MessageBox.Show("an error occur");
}
}
and in app that is loaded on the card, I have this method:
public string getBook(int index)
{
return BookList[index].getBookID() + " , " + BookList[index].getBookDesc();
}
The Gemalto .NET Card contains both persistent memory and volatile
memory that are used for data storage. The persistent memory acts as
persistent storage for the card - data persists in it even after the
card is removed from a smart card reader. Volatile memory is reset
when the card loses power and cannot be used for persistent storage.
how you store your data, and how you fill the BookList with data ? please clarify more.
you have memory limitation of course, so you cannot store up to certain size, in this .net card you have 16KB of volatile memory (RAM) and 70KB of persistent memory (that contain assemblies, storage memory).
I tested in some Gemalto .net card and able to store 20KB of data in persistent storage memory, after that limit i get the same exception OutOfMemoryException (because the other 50KB is filled with files, assemblies).
This card is not designed to store database, records and so on, its used to store critical information like keys and passwords. So don't save more than this size and your code will be fine, or use any text compression algorithm (in the client application) to reduce the size before storage in card, but in the end don't try to store more than this ~XX KB.
update:
Because of this limitation you cannot store more than 70K in persistent storage, also you cannot retrieve more than 16KB from the card to client (because this data will be stored in local variable i.e volatile memory and then retrieved back to your client, and you have constrains also here).
So this is the source of your problem, you retrieve more than volatile memory can hold:
public string getBook(int index)
{
return bookList[index].getId() + " , " + bookList[index].getName();
}
before return value, this data will be in temporarily variable, and because you can't store more than 16KB you get the exception OutOfMemoryException.
the solution is to use this storage directly from the client (you have the reference so just use it):
public Book getTheBook(int index)
{
return bookList[index];
}
and from the client you can access Book functionality(make sure your Book is struct because marshalling is supported only for struct and primitive types in Gemalto .net card):
Console.WriteLine(service.getTheBook(0).getName());
You are attempting a task not typical for smart cards. Note, that cards have RAM in the range of a handful of kByte, to be divided between operating system and I/O buffer. The latter is unlikely to exceed 2 kByte (refer to the card manual for that) and even then you need to use extended length APDUs as mentioned in this answer. So the likely cause for your error is, that the data length exceeds the amount of RAM for the I/O buffer. While enlarging the buffer or using extended APDUs will stretch the limit, it is still easy to hit it with a really long description.
I got this exception only when attempting to retrieve long string (such as 100 words). I've done with adding part and that was accomplished by simply send a string of BookDesc.
public Book[] BookList=new Book[5];
public static int noOfBooks=0;
public string addBook(string bookDesc)
{
Book newBook=new Book();
newBook.setBookDesc(bookDesc);
newBook.setBookID(noOfBooks);
BookList[noOfBooks]=newBook;
noOfBooks++;
}

Using QTWebKit to display a website stored in memory

Currently I have my HTML, JS, CSS, graphics, etc stored locally on hard disk and access them using QWebFrame::SetUrl( QUrl::fromLocalFile( "appFolder\html\index.html" )). At some point I am going to need to encrypt the locally stored files so I'm looking for a way to either decrypt them as they're requested or to decrypt them all into memory and access them that way.
I know I can use QWebFrame::setContent( htmlData ) to load the HTML from memory so I can load the encrypted HTML file, decrypt it in memory and then display it that way, but how would I go about the other data (JS, CSS, graphics, etc) which is currently stored in subfolders?
Alternatively, is there a way I can intercept requests for access to all the HTML, JS, CSS, etc files and decrypt them as they're loaded?
By using my own NetworkAccessManager I can intercept calls to createRequest so I can see when each file is being loaded, but I can't see how to use this to decrypt the data on the fly. I can also connect a slot function to the finished(QNetworkReply*) signal, but at that point the data has already been read - the QIODevice's current position is pointing to the end of the file.
I'd be very grateful for any advice or pointers in the right direction.
I think in your case the best solution is to inherit QNetworkReply class and use this new class in reimplemented QNetworkAccessManager::createRequest() function.
In general, you should reimplement next virtual functions of QNetworkReply:
bytesAvailable(), readData(char *data, qint64 maxSize), close(), abort().
For example, readData should be the folowing:
qint64 NetworkReplyEx::readData(char *data, qint64 maxSize)
{
return m_buffer.read(data, maxSize);
}
where m_buffer is already decrypted data.
Also you need to add all necessary logic in this class to get encrypted data, decrypt this data...
In the end you should manually emit finished() signal inside new class, so QWebView or other related class will get decrypted html.

Issue using SocketConnection with a Blackberry using MDS

I am currently writing an app on the Blackberry to do a simple send and receive of some raw data to another TCP based device on my network. I am having the same problem in the Blackberry simulator w/ an MDS simulator running and using a physical phone talking to my company's MDS server. Note this problem does not happen when using wifi directly and not via MDS.
The problem is that the available() function on the InputStream returns zero unless I call read() first. If I call read first (knowing there is some data available .. thank you wireshark) the data comes back, and the subsequent call to available() indicates what data is left that I did not read. The problem is that I am not always going to be guaranteed that data will be there and so I could block. Is anyone aware of this, and is this a problem or something that is by design?
Is anyone aware of a way to test if the read() method(s) will block before calling them aside from available?
Here is basically what I am doing:
SocketConnection s = (SocketConnection)Connector.open("socket://1.2.3.4:port;deviceside=false", Connector.READ_WRITE);
OutputStream o = ((StreamConnection)s).openOutputStream();
InputStream i = ((StreamConnection)s).openInputStream();
o.write("hello");
Thread.sleep(sometime);
if (i.available() > 0) {
byte[] data = new data[10];
int bytesRead = i.read(data);
System.out.println("Read [" + new String(data) + "] (bytes = " + bytesRead + ")");
}
I have to comment out the if conditional for this to work.
The general contract of the InputStream.available() method is that it "Returns the number of bytes that can be read (or skipped over) from this input stream without blocking by the next caller of a method for this input stream." Hence in most implementations, it is no guarantee that it will return the Content Length of the stream that is being read. Hence it is better to read it in the following way
byte[] readFromStream(InputStream is) throws IOException
{
byte[] data = new byte[4096];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
int count = is.read(data, 0, data.length);
while (count != -1)
{
dos.write(data, 0, count);
count = is.read(data, 0, data.length);
}
data = baos.toByteArray();
return data;
}
You call the readFromStream() method and get the byte[] returned.
As I indicated in a comment above, I needed a way to determine if a device I am connecting to is not there, and I do that by seeing if our 'ping' returns any data. If the device is not there it will block. I cannot rely on that behavior. Another issue that crept up while solving this is that the read(...) methods of the RIM InputStream class block if you provide a buffer bigger than the data you want back. But how am I supposed to know how much data is there if available() returns 0? Reading byte-by-byte is about the only way to do this, but it still blocks if there is no data.
To address this I followed the theme of the 1st answer, but I put this method on its own thread and had it write to a separate byte buffer. I created a class that extended InputStream and implemented available() and read(...). Available returns how many bytes are in the byte buffer, and read only gives back however much is in the buffer or however much the caller requests, whichever is less.
This setup lets me use an InputStream interface, but behind the scenes it is just a continuously running reader thread that is alive until the connection is dropped. At that time the read, if blocked, will throw an exception to indicate the connection closed. This behavior is fine as it can be easily handled.
Thanks to all above who helped with this issue. Your thoughts help move towards the solution.

Resources