ability to forward detached encrypted attachments(no inline)#1611
ability to forward detached encrypted attachments(no inline)#1611
Conversation
ec3981e to
2ec6e7d
Compare
| fun isEncrypted(): Boolean { | ||
| val fileExtension = FilenameUtils.getExtension(name) | ||
| return fileExtension.equals(Constants.PGP_FILE_EXT, true) | ||
| } |
There was a problem hiding this comment.
It's usually more complex than that. For example see
public treatAs = (): Attachment$treatAs => {
if (this.treatAsValue) { // pre-set
return this.treatAsValue;
} else if (['PGPexch.htm.pgp', 'PGPMIME version identification', 'Version.txt', 'PGPMIME Versions Identification'].includes(this.name)) {
return 'hidden'; // PGPexch.htm.pgp is html alternative of textual body content produced by PGP Desktop and GPG4o
} else if (this.name === 'signature.asc' || this.type === 'application/pgp-signature') {
return 'signature';
} else if (!this.name && !this.type.startsWith('image/')) { // this.name may be '' or undefined - catch either
return this.length < 100 ? 'hidden' : 'encryptedMsg';
} else if (this.name === 'msg.asc' && this.length < 100 && this.type === 'application/pgp-encrypted') {
return 'hidden'; // mail.ch does this - although it looks like encrypted msg, it will just contain PGP version eg "Version: 1"
} else if (Attachment.encryptedMsgNames.includes(this.name)) {
return 'encryptedMsg';
} else if (this.name.match(/(\.pgp$)|(\.gpg$)|(\.[a-zA-Z0-9]{3,4}\.asc$)/g)) { // ends with one of .gpg, .pgp, .???.asc, .????.asc
return 'encryptedFile';
} else if (this.name.match(/(cryptup|flowcrypt)-backup-[a-z0-9]+\.(key|asc)$/g)) {
return 'privateKey';
} else if (this.type === 'application/pgp-keys') {
return 'publicKey';
} else if (this.name.match(/^(0|0x)?[A-F0-9]{8}([A-F0-9]{8})?.*\.asc$/g)) { // name starts with a key id
return 'publicKey';
} else if (this.name.toLowerCase().includes('public') && this.name.match(/[A-F0-9]{8}.*\.asc$/g)) { // name contains the word "public", any key id and ends with .asc
return 'publicKey';
} else if (this.name.match(/\.asc$/) && this.hasData() && Buf.with(this.getData().subarray(0, 100)).toUtfStr().includes('-----BEGIN PGP PUBLIC KEY BLOCK-----')) {
return 'publicKey';
} else if (this.name.match(/\.asc$/) && this.length < 100000 && !this.inline) {
return 'encryptedMsg';
} else {
return 'plainFile';
}
};There was a problem hiding this comment.
Maybe I had to choose a better name for this method. It just check that an attachment can be an encrypted file. Like file.txt.pgp should be an encrypted file.
But now I see it should be improved. At least it should cover the following
if (this.name.match(/(\.pgp$)|(\.gpg$)|(\.[a-zA-Z0-9]{3,4}\.asc$)/g)) { // ends with one of .gpg, .pgp, .???.asc, .????.asc
return 'encryptedFile';
@tomholub maybe you have more ideas. I need to mark an attachment as decrypt_before_sending.
There was a problem hiding this comment.
Yes, that's what I meant - at least that.
There was a problem hiding this comment.
can be renamed into something like isPossiblyEncrypted
There was a problem hiding this comment.
Good idea, or couldBeEncrypted
| var tempFileForDecryptionPurposes: File? = null | ||
| try { | ||
| val finalSrcInputStream = if (shouldBeDecryptedBeforeProcess) { | ||
| tempFileForDecryptionPurposes = File.createTempFile("tmp", null, destFile.parentFile) |
There was a problem hiding this comment.
If that's an actual file, and it contains plain - not encrypted data, then this is forbidden. We cannot save that locally, even temporarily, even if it's in app's own storage.
There was a problem hiding this comment.
Are we talking about tempFileForDecryptionPurposes? Do you mean I have not to use a temp file for decryption purposes? Have I to do it on the fly?
There was a problem hiding this comment.
The plain file can never be saved to the device when forwarding.
That means no intermediary files, unless that intermediary file is properly encrypted.
But better would be to download / decrypt / re-encrypt in single stream. The re-encrypted file could be saved temporarily before uploading it, that would be ok.
There was a problem hiding this comment.
Case 1: original message was encrypted, forwarded message will be encrypted too
I can do the following: I have input stream of encrypted file. I decrypt it to byte array (RAM. Actually it is not good for performance), then I encrypt it and save to a temporary file.
Looks good?
There was a problem hiding this comment.
You can do that. How will you encrypt it? Already with the final public keys? Do you know them at that point?
There was a problem hiding this comment.
Anything is possible
I wanted to say that it's possible for Java/Kotlin world. Just not sure that it's possible for PGPainless/Bouncy Castle. Anyway, I will check it tomorrow.
There was a problem hiding this comment.
Hha, you are totally right 👍. It's a good idea. I can just move all this logic to the next step. As for me manipulation with attachments will be better to do at this stage, to be much clearer. Then the next step will be responsible just for sending... But security reasons encourage me to do file manipulation at the last stage(sending).
There was a problem hiding this comment.
When I talked about steps I meant the following: we have 3 different services
- Service that creates MIME message
- Service that downloads forwarded atts(all things in the current PR relate to it)
- Service that sends MIME messages.
There was a problem hiding this comment.
I also think it' good idea. Then you don't need to re-encrypt encrypted message. If you were about to re-encrypt, you would have to generate random temporary key for symmetric encryption algorithm (for example, AES-256), held only in memory, and then encrypt data with it, then later decrypt with it. Not sure if BC is required for this, JDK itself should be capable of symmetric encryption/decryption with some widely accepted algorithms.
There was a problem hiding this comment.
In the context of forwarding encrypted attachments, the re-encrypt here means encrypting it with the recipient's public keys. Since that's what you have to do before sending it out.
|
I've added the requested changes. I hope it will be enough for now. Unfortunately, I'm not happy with this realization. Because some logic is located in the wrong place(in my opinion). If we have |
This PR added the ability to forward any attachments.
It means we can forward an encrypted message with detached attachments as an encrypted message(in that case we will download, decrypt and encrypt attachments with new pub keys before sending) or as a standard message(in that case we will download and decrypt attachments before sending)
close #1538
Tests (delete all except exactly one):
To be filled by reviewers
I have reviewed that this PR... (tick whichever items you personally focused on during this review):