I want to set the encryption key size for Bluetooth in Android, but not able to find the files where the exact encryption happens. I have seen that BluetoothSocket class does take "encryption" as a boolean argument in constructor, but when I followed it to the JNI layer, found that it just makes system call of "setSocketOpt" . But in kernel code i was not able to find the place where its happening.
If anyone have idea where the actual encryption happens and what is the key
size used for encryption then please answer.
Encryption key size is set by the LMP layer. So, you will not be able to access it at the OS level (Host level). This is done in the Firmware (Controller level).
Related
I develop some codes and pack them into several shared libraries (*.so in Android OS). I would share them to some vendors but I want these libraries can be used only on one or more Android devices.
I tried to get the device unique id and check is the id legal or not, but it seems there is no any id that represents a unique device and can not be changed even the device is re-flashed. I know there is a CPUID under x86 windows system, but not similar thing under arm-based Android device. Also, for the sake of linux security mechanism, I can't get anything like MAC for flash id either from user space without root.
Any ways to achieve that ? Look forward to your advice. Thanks.
Even if you try to do that, someone can just decompile your library and revert these countermeasures. There is no way you can avoid that.
If this is not a concern to you, you can get the IMEI of the device. The downside is that there might not be one (most likely the case if it is a tablet without 3G). Here is how: How to get the device's IMEI/ESN programmatically in android?
If you want to get the MAC address you can try this (still, not guaranteed that it will work, plus it is easy to spoof): Getting MAC address in Android 6.0
This is also an interesting read, however most of these methods are likely to not uniquely identify a device once it has been reset: https://developer.android.com/training/articles/user-data-ids.html
I am developing a voice / video calling system in which there is browser to browser, Android to Android and Android to browser calling. Although I have managed to get that all working, I have run into a problem with the cryptos being used to encrypt the audio / video packets being sent between two clients. My system requires a certain set of cryptos, and I have managed to get that set working with Android to Android calling. However, the default cryptos being used in WebRTC enabled browsers are significantly weaker than the alternate crypto set being used for Android to Android calling. Thus, I have to "dumb down" the cryptos in the system so that I can have Android to browser calling.
Since I have no access to the code for WebRTC enabled browsers (and definitely cannot modify it) my only recourse is to somehow select or tell the peerconnection object which crypto level / set to use. I swear I have heard of this being done before, but I cannot find where I saw it nor anywhere that talks about doing it. So, I was wondering if anyone knew:
Is such a thing possible?
If possible, how does one set the cryptos for the call?
What cryptos are supported in Chrome and Firefox?
If I am remembering what I saw correctly, it was done somewhere along the lines of passing a JSON looking something like: { 'crypto' : 'AES....'} to the constraints parameter of webkitRTCPeerConnection. However, I could potentially be imagining all of this.
You can enable DTLS by passing the following to the PeerConnection constructor:
{ 'optional': [{'DtlsSrtpKeyAgreement': 'true'}]}
However, that doesn't let you pick the crypto algorithm. For that you could potentially munge the SDP with a different crypto line with the given SRTP key management parameters. However, I'm not sure offhand if anything other than the default is supported in Chrome. That may be a good question for the discuss-webrtc list.
I would like to encrypt data in my Android app. I have little experience in what the current state of encryption is, either for Android specifically or in general. I remember years ago that the US had laws that prevented software companies from exporting strong encryption technology. I'm not sure if any of that is applicable today considering that Android is open source code.
What I want to accomplish is to allow a user to encrypt data using only a password. I prefer to avoid using private/public keys because this probably requires having to enter in those two keys by the user. In my app, the user should be able to encrypt/decrypt data using a password. Their data will be sent from one mobile device to another and it should not be possible to decrypt their data on the receiving end without knowing the password. I do use SSL when sending the data but that isn't good enough because the data needs to remain encrypted on the server before it gets relayed to the receiving device. If a hacker had access to my server, they could potentially read the data. For this reason, I want to encrypt it on the sending device and only decrypt it on the receiving device.
A number of issues I need to resolve:
Is there an encryption API that will let me encrypt just using a password but if not, then I'll consider using private/public keys.
What are the current encryption algorithms that I can use and are they available internationally or does the US put some restriction on using them?
Would I be better off creating my own custom encryption algorithm and modify it from time to time to prevent hackers from easily breaking it? Or would you discourage this? If so, why? If I change algorithm regularly, I will need to include an algorithm ID in the data in order for the decryption code to recognize whether it can decrypt that current version of the algorithm.
I'm not looking for any "extremely hard to break" algorithm but something that should be adequate. The kind of data being stored are images, videos, audio and GPS data. It would be nice if the solution worked on Android 2.2 and above. I don't see why any algorithm shouldn't work on these versions since algorithms should be independent of an OS. Nevertheless, maybe Android does use a built-in algorithm for only certain versions?
Edit:
Code I am using now for some basic internal encryption in my app looks like this, but I have my doubts it's sufficient enough:
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
Originally, the above line was:
SecureRandom.getInstance("SHA1PRNG")
but Google changed this in 4.0 and this caused my code to break. Anything encrypted with my previous code could no longer be decrypted with the default API for 4.0. I personally found that a major issue with Google because they broke compatibility. What's to stop them from repeating this again in the future? My encryption/decryption cannot be dependent upon Google's choice of breaking compatibility.
I am also forced to use 128 bit encryption because apparently support for 192 and 256 bits is not necessarily available on all devices, persumably because of local government laws.
Is there an encryption API that will let me encrypt just using a
password but if not, then I'll consider using private/public keys.
I've written an open source Java library that encrypts data with a password, using 256-bit AES. You can this find this on GitHub: JNCryptor. This is compatible with the RNCryptor project for iOS.
This may work for you on Android, or at least you can see how the code works and adapt it as necessary. (If you don't find it works as you'd like, feel free to raise an issue and I will adjust the library).
What are the current encryption algorithms that I can use and are they
available internationally or does the US put some restriction on using
them?
There are a myriad of algorithms available, but you will be fine if you stick something very standard, such as AES.
As far as I know, the US still forbids exporting software that uses 256-bit AES key sizes. There may be other restrictions in other countries too. But I am not a lawyer.
Would I be better off creating my own custom encryption algorithm and
modify it from time to time to prevent hackers from easily breaking
it? Or would you discourage this?
Do not do this. Always use a well-known algorithm that has been subjected to extensive peer review. There should be no need to regularly change your choice of algorithm, unless it has been known to be compromised.
My team needs to develop a solution to encrypt binary data (stored as a byte[]) in the context of an Android application written in Java. The encrypted data will be transmitted and stored in various ways, during which data corruption cannot be ruled out. Eventually another Android application (again written in Java) will have to decrypt the data.
It has already been decided that the encryption algorithm has to be AES, with a key of 256 bits.
However I would like to make an informed decision about which AES implementation and/or "mode" we should use. I have read about something called GCM mode, and we have done some tests with it (using BouncyCastle/SpongyCastle), but it is not entirely clear to me what exactly AES-GCM is for and what it "buys" us in comparison to plain AES - and whether there are any trade-off's to be taken into account.
Here's a list of concerns/requirements/questions we have:
Padding: the data we need to encrypt will not always be a multiple of the 128 bits, so the AES implementation/mode should add padding, yet only when necessary.
I was under the impression that a plain AES implementation, such as provided by javax.crypto.Cipher, would not do that, but initial tests indicated that it does. So I'm guessing the padding requirement in itself is no reason to resort to something like GCM instead of "plain" AES. Is that correct?
Authentication: We need a foolproof way of detecting if data corruption has occurred. However, ideally we also want to detect when decryption is attempted with an incorrect key. Hence, we want to be able to differentiate between both of these cases. The reason I ended up considering GCM in the first place was due to this Stackoverflow question, where one of the responders seems to imply that making this distinction is possible using AES-GCM, although he does not provide a detailed explanation (let alone code).
Minimise overhead: We need to limit overhead on storage and transmission of the encrypted data. Therefore we wish to know whether, and to what extent, the choice for a specific AES implementation/mode influences the amount of overhead.
Encryption/decryption performance: Although it is not a primary concern we are wondering to what extent the choice of a specific AES implementation/mode influences encryption and decryption performance, both in terms of CPU time and memory footprint.
Thanks in advance for any advice, clarification and/or code examples.
EDIT: delnan helpfully pointed out there is no such thing as "plain AES". So to clarify, what I meant by that is using Java's built-in AES support.
Like so: Cipher localCipher = Cipher.getInstance("AES");
In 2012 the answer is to go for GCM, unless you have serious compatibility issues.
GCM is an Authenticated Encryption mode. It provides you with confidentiality (encryption), integrity, and authentication (MAC) in one go.
So far, the normal modes of operation have been ECB (which is the default for Java), CBC, CTR, OFB, and a few others. They all provided encryption only. Confidentiality by itself is seldom useful without integrity though; one had to combine such classic modes with integrity checks in an ad-hoc way. Since cryptography is hard to get right, often such combinations were insecure, slower than necessary or even both.
Authenticated Encryption modes have been (fairly recently) created by cryptographers to solve that problem. GCM is one of the most successful: it has been selected by NIST, it efficient, it is is patent free, and it can carry Additional Authenticated Data (that is, data which stays in the clear, but for which you can verify authenticity). For a description of other modes see this excellent article of Matthew Green.
Coming to your concerns:
Padding: by default, Java uses PKCS#7 padding. That works, but it is often vulnerable to padding oracle attacks which are best defeated with a MAC. GCM embeds already a MAC (called GMAC).
Authentication: AES-GCM only takes one AES key as input, not passwords. It will tell you if the AES key is wrong or the payload has been tampered with, but such conditions are treated as one. Instead, you should consider using an appropriate Key Derivation Algorithm like PBKDF2 or bcrypt to derive the AES key from the password. I don't think it is always possible to tell if the password is incorrect or if the payload has been modified, because the data necessary to verify the former can always be corrupted. You can encrypt a small known string (with ECB AES), send it along, and use it to verify if the password is correct.
Minimise overhead: At the end of the day, all modes leads to the same overhead (around 10-20 bytes) if you want authentication. Unless you are working with very small payloads, this point can be ignored.
Performance: GCM is pretty good in that it is an online mode (no need to buffer the whole payload, so less memory), it is parallelizable, and it requires one AES operation and one Galois multiplication per plaintext block. Classic modes like ECB are faster (one AES operation per block only), but - again - you must also factor in the integrity logic, which may end up being slower than GMAC.
Having said that, one must be aware that GCM security relies on a good random number generation for creation of the IV.
On Android, I need to retrieve the bytecode from the executing class at runtime.
If you're wondering why, the reason is that I'd like to compute a hash of it in order ton implement some anti-piracy mechanism that would check that the file hasn't been tampered.
Anyway, I'm trying it like this:
InputStream is = this.getClass().getClassLoader()
.getResourceAsStream("org/foo/bar");
Whichever parameter I pass in the getResourceAsStream(), it always return null.
Is there actually a way to get access ti the bytecode at runtime on Android?
Not sure if that is possible, you should trust the signature system used for APK's. The only hack that I have seen with these is wrapping that app in another app that contains the malicious code and Google fixed that ( I think ). Classes already have a hash code but I'm sure that will not give the same results to what you want to do.
If someone can change your code they will also disable your checks.
I have seen and tried a reverse engineering app to check the security of Android's byte code with an app of my own and it only worked on rooted systems and the disabled code is so horrendous it's unusable. It's not the same as dissembling a Java app.
Pirating a game does not require it to be modified.