We are having an android app which a decrypting and encrypting large (up to 100MB) files over HTTP-Streams.
Therefore, we are using CipherInputStreams and CipherOutputStreams which works fine for AES/CBC/PKCS7Padding. We recently switched to AES/GCM/NoPadding. Now the encryption and decryption is inacceptable slow for files over roughly 50MB.
Debugging into the android source code, reveals the issues: https://android.googlesource.com/platform/libcore/+/master/ojluni/src/main/java/javax/crypto/CipherInputStream.java#112
This method has byte buffer "oBuffer" which is reallocated and increased by 512bits until it can hold the whole message (see line: https://android.googlesource.com/platform/libcore/+/master/ojluni/src/main/java/javax/crypto/CipherInputStream.java#121)
I am aware of the note over this method which stated that in AEAD ciphers the whole message has to be buffered. This is one issue, because we cannot hold the whole message into a memory buffer. Another issue is that the oBuffer is constantly reallocated.
Is there any solution for using GCM with a streaming API?
Splitting the file into the parts and chaining is a solution for you.
Assume that you divide the file into n parts. Encrypt each of them with AES-GCM with the following additions. Prefix each part before encryption as follows;
tag_0 = ''
for i from 1 to n
ciphertextBlock_i, tag_i = AES-GCM( i:n || tag_i-1 || plaintextBlock_i)
prefix each part with the part number as i:n
prefix each part except the first one with the authentication tag of the previous part.
With these, you have now a chain that can be controlled after decryption. You can detect, additions, deletions. The order is under your control, you can send even without the order. However, you need to check the prefix.
You can also
add the part size, and
add the time of encryption, too if you fear from the replay attack.
Related
I am implementing the AES encryption algorithm in GCM operating mode in an android application.
My IDE (Intellij Idea) tells me that to use javax.crypto.spec.GCMParameterSpec the condition android.os.Build.VERSION.SDK_INT> = android.os.Build.VERSION_CODES.KITKAT is required.
I tried when the condition is not verified to use a javax.crypto.spec.GCMParameterSpec of which I downloaded the source file and included it in my project, but with it the encryption operations do not work correctly (the decrypted data does not match to original data or java.security.InvalidAlgorithmParameterException: IV must be specified in GCM mode).
Do you have any ideas to suggest on how I can also support previous versions of Android KITKAT?
Thanks in advance.
Initial versions of Android based on Java 6 did not give you GCMParameterSpec, but they would use IvParameterSpec instead. Besides the (usually 12 byte) IV, the GCMParameterSpec will give you two additional operations: the support for additional data and the tag size.
Now the tag size is not too much of a problem: first of all, usually the full 128 bits / 16 bytes are used. Furthermore you can just remove those bytes from the end of the ciphertext until you reach the required tag size, e.g. remove 4 bytes / 32 bits to get a tag size of 96 bits.
The additional data is a problem, as far as I know there is no way to specify those, at least not if you require a Cipher instance. You could of course use GCMBlockCipher instead, but then you'd not use Cipher and any possible acceleration provided by the platform (as Bouncy is software only).
And yes, as indicated, it is perfectly possible to implement GCM mode yourself for Android, as you don't need to sign any providers. Of course, you'd have to use a different GCMParameterSpec implementation, and it would be a good idea only to use the provider for the older platform, so some runtime switching seems to be required.
Background:
I have an obfuscated C code. Obfuscation can only protect the algorithm logic, but cannot hide the variable values from dynamic analysis. I want to further hide some values (e.g., a char array) from memory debug.
Platform: mobile client-side (not related to remote server)
Assume I have a secret char array:
char secret[15] = {"hide this value"};
Is it possible to hide this value in this way:
for every element i, secret[i] = x1[i] XOR x2[i]
Only define and store char x1[ ] and char x2[ ] in the memory
When need to use secret[ ] every time, call x1[ ] XOR x2[ ]. So secret[ ] cannot be found through memory debug (dynamic analysis)
Or any other ways?
If an adversary has the ability to freely examine the working memory of your program, such as via a debugger, then within the program there are no secrets from them. In particular, encrypting data in memory is not a reliable safeguard because you have to decrypt it to use it, at which point it can be easily be intercepted. But also, the decryption key must be somewhere in memory, where your adversary can find it, thereby obtaining the ability to decrypt your in-memory encrypted data at will.
Obfuscating your code is not a reliable safeguard, either. It may slow down your adversary, but with skill and / or good tools, they will sort out what's what in time. In fact, supposing that you strip debugging symbols from the executable and do not provide source code, the only obfuscation that even is visible is external function and variable names (so don't bother obfuscating anything else).
Protect sensitive data by not putting it in unprivileged hands in the first place. If you deliver data to an untrustworthy device or program, then you should consider it compromised.
Anything you're discussing right now is just ways to obfuscate your data. If somebody wanted to debug or disassemble, they would clearly see what was happening and could find the key. Even without disassembly, seeing two strings, someone could XOR each character just out of curiosity. Given that, an XOR is still a good option and it keeps your data pretty obscure when both strings are unprintable. To further this, it would be interesting if you used a certain hash of a file or string to generate the key to XOR.
Now, given that, there are many resources on string obfuscation in binaries and in C that you can research.
Rather than obfuscation on its own, hashing or encryption could be used. This really depends on what the string/key is used for. If you are willing to comment more details, I can help out more.
Here are a few great resources:
- Stack Exchange: Protect Data Stored in Binary
- Binary/String Obfuscation in C
I've been trying to decompile and extract useful data from an APK for some time now. This data is stored in CSV files inside an "assets" folder. Unfortunately, the developers got smart, and have begun encrypting these CSVs starting in July. I've exhausted every way I know of to try and turn these files into readable versions of themselves without any success. But then, I realized, there are a few files in the assets folder that haven't changed since well before July—thus, I have both the decrypted and encrypted versions of these files. Using this knowledge, is it possible to predict the encryption pattern that all other files in the directory went through?
I'm fairly sure that it was encrypted bit-level, not byte-level since there are a lot of unknown characters (represented as special question marks) while trying to read these CSVs using Notepad/TextEdit/Atom in UTF-8 mode (or any other mode except UTF-16, really).
You're talking about a "known plain text" attack. No modern, widely used
method is vulnerable to this kind of attack, but many home grown encryption
methods are. Even with known text, you need to know or guess a lot about
the details of the encryption algorithm.
A better plan might be to hack the software that you know is doing the
decrypting, which must contain both the algorithm and the key.
You'd have better luck simply guessing based on the encrypted output. You'll need to familiarize yourself with characteristics of the output of algorithms and compare against what you see. This is probably a lot easier for hashes but you're talking about encryption. To answer your question though, it's unlikely that you're going to be able to use an unencrypted version of a file to break the encrypted one. You might try encrypting that file using different algorithms and comparing the results. That might give you the algo but could take longer.
Alternatively, here are some tools I found that might be able to automate the process for you...
https://code.google.com/archive/p/aligot/
https://bitbucket.org/daniel_plohmann/simplifire.idascope
https://www.aldeid.com/wiki/IDA-Pro/plugins/FindCrypt2
To crack it, you're also going to need to find the key that was used to encrypt it. Since it's a program that obvious must be decrypted to use, that key shouldn't be impossible to find. It's either in the apk or on a server somewhere in which case use wireshark but I'm guessing it's embedded.
They might be usig DexGuard or ProGuard. Here's a related post What methods are being used to protect this Android APK: Reflection? Encryption? How do I reverse engineer it and analyze it?
If it's ProGuard you might start with something like this: http://proguard.sourceforge.net/manual/retrace/examples.html
Here's some info on that: How to decode ProGuard's obfuscated code precisely?
I'm using ISO 8859-1 (Latin extended ASCII char set) in my C application. When I strcpy/strcat the portions of the string together, it works fine. But when I use sprintf("%s %s"), on some runtimes (particularly certain versions of Android), the string will truncate when an extended ASCII character (specifically é, although I haven't tried others) is hit.
I thought %s was just supposed to copy the bytes until '\0' was hit. I suspect that strcpy/strcat works because it does do just that, without any formatting. What could possibly be going on here?
I should note that I'm not viewing the text using printf(), rather my own text rendering engine which handles ISO-8859-1 just fine.
UPDATE:
To clarify, I have an NDK app, which is keeping the string in C, and passing it to my OpenGL based text rendering engine. If I pass the full string as a char* literal, it displays fine. If I sprintf() the portions together, it gets truncated at the é character.
For example:
char buffer[1024];
strcpy(buffer, "This is ");
strcat(buffer, "the string I want to diésplay.");
That shows up fine. But this:
sprintf(buffer, "%s%s", "This is ", "the string I want to diésplay.");
Prints as:
This is the string I want to di
The behavior of s[n]printf() is specified differently than the behavior of string-manipulation functions such as strcpy() and strcat(). The printf-family functions are all required to produce the same byte sequences when presented identical formats and print items. The only difference is in where those bytes are sent. Thus, if your C library were built such that it performed a transformation on string data (maybe a transcoding) when printing to the standard streams via printf(), then it would perform that same transformation when printing to a string via sprintf().
The "f" in "printf" is for "formatted". The standard neither says nor implies that formatting a string must mean dumping its bytes to the output verbatim, so a transcoding or other transformation such as I hypothesized above is not out of the question. In fact, the docs for some versions of these functions indicate locale-dependence ("Note that the length of the strings produced is locale-dependent and difficult to predict"), so transcoding in particular is a real possibility.
Any specific explanation of the third-party observations you describe would necessarily be speculative, as you have not presented nearly enough code or data to make a confident diagnosis. I am inclined to suspect an issue revolving around running the program in a locale that uses a character encoding differing from the one used internally by the program. If so, then you may be able to reproduce the problem locally by varying the locale in which you run, and you may be able to address it by ensuring one way or another that your program always runs in a suitable locale. Among other things, you might use the getlocale() and setlocale() functions to help here, especially if you want to limit the scope in which you exercise locale control.
Since ultimately you are relying on printf-family functions only for string manipulation, however, I think it would be better to use the workaround presented in the question: as much as possible, use C's dedicated string-manipulation functions, such as strcpy() and strncat(), to perform your string building. Since you are not relying on the stdio functions for your actual output, this should be fine.
I found an android app named Super Erase that deletes files and folder permanently from android device so that the file deleted cant be recovered anymore..here is the application i am talking about ...but i was wondering how to that and i know it is made with android studio ..i tried the regular way to delete file.delete() but still the file can be recovered.can i have any help .
For starters, secure file deletion on flash media is a complex problem, with no quick and easy answers. The paper Reliably Erasing Data From Flash-Based Solid State Drives gives a good overview of the problems, the potential solutions, and their limitations. They conclude that
For sanitizing entire disks, ... software techniques work most, but not
all, of the time. We found that none of the available software
techniques for sanitizing individual files were effective. [emphasis added]
NIST 800-88 also has a good overview of the technology trends contributing to the problem, along with some minimum recommendations (appendix A) for Android devices. However they tend to be either whole-disk erasure (factory reset), or rely on cryptographic erasure (CE), rather than being general file erasure methods.
But all is not lost. Even if you can't sanitize individual files, you could hope to wipe all the unallocated space after deleting files. The article Secure Deletion on Log-structured File Systems (Reardon, et al.) describes a fairly promising way to do that in user-mode software. Android's internal memory uses (always?) a log-structured file system.
This paper's "purging" method does not require kernel-level access, and doesn't seem to require any native code on Android. (Note that the term "purging" is used a little differently in documents like NIST 800-88.) The basic idea is to delete all the sensitive data, then fill in the remaining space on the drive with a junk data file, and finally delete the junk data file.
While that takes more time and effort than just overwriting the deleted files themselves (several times in different patterns), it seems to be very robust even when you have to deal with the possibility of wear-leveling and log-structure FS.
Caveat and Further Measures
The main caveat for me is about the conditions mentioned by Reardon et al. in the above paper:
Purging will work for any log-structured file system provided both the
user’s disk quota is unlimited and the file system always performs
garbage collection to reclaim even a single chunk of memory before
declaring that the drive is unwritable. [emphasis mine]
The second condition seems pretty likely to be fulfilled, but I don't know about the first one. Does Android (or some manufacturers' versions of it) enforce quotas on disk space used by apps? I have not found any info about user quotas, but there are quotas for other niches like browser persistent storage. Does Android reserve some space for system use, or for each app's caching, for example, that can't be used for other things? If so, it should help (albeit with no guarantees) if we begin purging immediately after the sensitive files are deleted, so there is little time for other filesystem activity to stake a claim to the recently freed space.
Maybe we could mitigate these risks by cyclical purging:
Determine the remaining space available (call it S) on the relevant partition, e.g. using File.getUsableSpace()
Write a series of files to the partition; each one is, say, 20% of the initial S (subject to file size limits).
When we run out of space, delete the first couple of files that we created, then write another file or two as space allows.
Repeat that last step a few times, until you've reached a threshold you're satisfied with. Maybe up to the point where you've written 2*S worth of filler files; tweak that number to balance speed against thoroughness. How much you actually need to do this would be an area for more research.
Delete the remaining filler files.
The idea with cyclical purging is that if we run out of quota to overwrite all free space, deleting the filler files just written will free up more quota; and then the way log-structured filesystems allocate new blocks should allow us to continue overwriting the remaining blocks of free space in sequence, rather than rewriting the same space again.
I'm implementing this method in a test app, and will post it when it's working.
What about FAT-formatted microSD cards?
Would the same methods work on external storage or microSD cards? FAT is block-structured, so would the purge method apply to FAT-formatted SD cards?
On most contemporary flash memory devices, such as CompactFlash and
Secure Digital cards, [wear leveling] techniques are implemented in
hardware by a built-in microcontroller. On such devices, wear leveling
is transparent and most conventional file systems can be used on them
as-is. (https://en.wikipedia.org/wiki/Wear_leveling)
...which suggests to me that even on a FAT-formatted SD card, wear leveling means that the traditional Gutmann methods would not work (see his "Even Further Epilogue") and that a method like "purging" would be necessary.
Whether purging is sufficient, depends on your security parameters. Wear leveling seems to imply that a block could potentially be "retired" at any time, in which case there is no way to erase it without bypassing the microcontroller's wear leveling. AFAIK this can't be done in software, even if you had kernel privileges; you'd have to design special hardware.
However, "retiring" a bad block should be a fairly rare event relative to the life of the media, so for many scenarios, a purging method would be secure enough.
Erasing the traces
Note that Gutmann's method has an important strength, namely, to erase possible traces of old data on the storage media that could remain even after a block is overwritten with new data. These traces could theoretically be read by a determined attacker with lots of resources. A truly thorough approach to secure deletion would augment a method like Gutmann's with purging, rather than replacing it.
However, on log-structured and wear-leveled filesystems, the much bigger problem is trying to ensure that the sensitive blocks get overwritten at all.
Do existing apps use these methods?
I don't have any inside information about apps in the app store, but looking at reviews for apps like iShredder would suggest that at best, they use methods like Reardon's "purging." For example, they can take several hours to do a single-pass wipe of 32GB of free space.
Also note limitations: The reviews on some of the secure deletion apps say that in some cases, the "deleted" files were still accessible after running the "secure delete" operation. Of course we take these reviews with a grain of salt -- there is a possibility of user error. Nevertheless, I wouldn't assume these apps are effective, without good testing.
iShredder 4 Enterprise helpfully names some of the algorithms they use, in their app description:
Depending on the edition, the iShredder™ package comes with deletion
algorithms such as DoD 5220.22-M E, US Air Force (AFSSI-5020), US Army
AR380-19, DoD 5220.22-M ECE, BSI/VS-ITR TL-03423 Standard,
BSI-VS-2011, NATO Standard, Gutmann, HMG InfoSec No.5, DoD 5220.22 SSD
and others.
This impressive-sounding list gives us some pointers for further research. It's not clear how these methods are used -- singly or in combination -- and in particular whether any of them are represented as being effective on their own. We know that Gutmann's method would not be. Similarly, DoD 5220.22-M, AFSSI-5020, AR380-19, and Infosec No. 5 specify Gutmann-like procedures for overwriting sectors on hard drives, which would not be effective for flash-based media. In fact, "The U.S. Department of Defense no longer references DoD 5220.22-M as a method for secure HDD erasure", let alone for flash-based media, so this reference is misleading to the uninformed. (The DoD is said to reference NIST 800-88 instead.) "DoD 5220.22 SSD" sounds promising, but I can't find any informative references for it. I haven't chased down the other algorithms listed, but the results so far are not encouraging.
When you delete file with standard methods like file.delete() or runtime.exec("rm -f my_file") the only job that kernel does is removing info about file from auxiliary filesystem structures. But storage sectors that contain actual data remain untouched. And because of this recovering is possible.
This gives an idea about how we can try to remove file entirely - we should erase all sectors somehow. Easiest approach is to rewrite all file content with random data few times. After each pass we must flush file buffers to ensure that new content is written to storage. All existing methods of secure file removal spin around above principle. For example this one. Note that there is no universal method that works well across all storage types and filesystems. I guess you should experiment by yourself and try to implement some of the existing approaches or design your own. E.g. you can start from next:
Overwrite and flush file 10 times with random data (use FileOutputStream methods). Note!!! Don't use zeros or another low entropy data. Some filesystems may optimize such sparse files and leave some sectors with original content. You can use /dev/urandom file as source of random data (this is a virtual file and it is endless). It gives better results and works faster then well-known Random class.
Rename and move file 10 times. Choose new file names randomly.
Then truncate file with FileChannel.truncate().
And finally remove file with File.delete().
Of course you can write all logic in native code, it may be even somewhat easier than in Java. Described algorithm is just an example. Try doing in that way.
The standard filesystem API won't give you a simple function call for that.
You will have to use the underlaying native API for FileIO. Although I have never used it, theres a library for that:
https://github.com/johanneslumpe/react-native-fs
There are two answers to this question.
First, to answer the direct question of how some of these apps might be doing secure single file delete: what you do is actually open the file and replace the contents with zeros many times. The method sounds stupid, but I have worked with filesystem-level encryption on Android in the past and I found that the above holds true for many secure file delete solutions out there. For a seemingly compliant security, you can repeat writing zeros 7 times (or whatever the NIST standards specify for your hardware type).
Charset charset = StandardCharsets.UTF_8;
String content = new String(Files.readAllBytes(path), charset);
content = content.replaceAll("*", "0");
Files.write(path, content.getBytes(charset));
The right answer to this question is however different. On modern SSD drives and operating systems, it is insecure to delete single files. Therefore, these apps don't really offer a compelling product. Modern operating systems store fragments of the file in different places, and it is possible that even after you have zeroed out the most recent version of the file block-by-block and also overwrote all metadata, that a fragment from an older version of the file might be left over in another part of the drive.
The only secure way to delete sensitive content from a disk is to zero out the entire disk multiple times before discarding the disk.
#LarsH's answer about wiping all unallocated space after deleting files is compelling, but perhaps impractical. If you simply want to secure delete files so no one can scan the disk to recover it, then a better solution is the full-disk encryption. This was in-fact the entire appeal of full-disk encryption. This is why Apple stopped supporting secure file delete in their Mac OSX and iOS, and switched to full-disk encryption as default on all iPhones. Android phones have full-disk encryption as well now.
EDIT:
If you are looking for a true solution for a customer, your best bet is to use single file encryption. Once you destroy your key which only your app would know, there is no way to decrypt the file even if someone found it on the disk.
There exists no real solution for deleting files securely on SSDs. You can only give a false sense of security to non-technical people who still remember the old HDD days.