Encrypt in Android and Decrypt in Node JS (Asymmetric Encryption) - android

I have been trying to encrypt a string in android with private key and decrypt in node js with public key.
private final static String PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDxJtyHARAMe69K0OoqoO+1yfXr\n" +
"jfWFums8HLOjArJNyVJapUC4Dr0Rcj0e4wAy1QCQJsxCl8OeitiVAugoML39ZdCMPENc9u/LEGVU\n" +
"lCB8B3tjB9FoDWzKEqI6CXP5Ga80dNRNakC7/aCUFdVdvYA+m4UNtbzP+KB+RrQQkA9TPBSm/25P\n" +
"anBkCHrmRQIeC2RQz4eTjkpSpA97fmUsTjSOUrAl94OGdZ2EiWUMZuN7lF26/DUsrLlHB15l4f12\n" +
"HfsvVyRGCkWK9pg0LLoJpCEq8IJExsrTBOT6QHT3Vx2oKFsHVp6sg2Lknk+W8ioRvLPGb6CPHu4I\n" +
"q70bCcyVLu0lAgMBAAECggEAa3aq7YqesUFo80k4IPkI+ZTffzIKyKYzZV1Q/AKWnK1rgrODrMH8\n" +
"pUqoTBxSmVRsZNC1U7O32+356CWceVSHReXaUrQEPOhaIb7TuSYtd7gJ1y7Dtb/NzBsTqhNOWCKG\n" +
"/jRV642+/UdgCL3WEGkDPmMlnt9vHaqpMrylP4BDJA6Tjef9/AcJ0Df+bn+hCA0ICs1i3PXmMWaS\n" +
"emJ/DK38caumYyuRYF/o26seU/gY0vMqwf2MH9Anb/f9RxfOtx6MlKd1SnotuYahFU0/rNSNmK/G\n" +
"oFKPFWBX3e0nTdIz4VQtiSKScHsLkaSwSBP2kN3TK2MFRpyLylOD7C7wtM+mvQKBgQD+liJhlF5T\n" +
"7C0zSQ2t0mGLkoL58U8eA8TZg2VXb/wl6FmTtQ3dQ+QhFIs4xgO+fCiZfjgA5RPLIvbP71vLHsYH\n" +
"3/R+zwkQtZy4IvT5jgK4beXsIuQVtN69rwBoWvB1XDDOZlozoG/6RvNMstHeXBH11rzQSZAFzCaJ\n" +
"u9YyIZy1HwKBgQDyfaGcaqPaso2IH/Iy7Xnu1YzsElE82KAv4tvmnzNpWWeQ8k+q8P4vwDCTR206\n" +
"D6Vt68B6UpZH5BkiyQ1CUBMU4XJR2+JXQjMQg/T1QpK0mBLOTTZhbJa+61hoKwfgmjnYTLra4yUW\n" +
"prq6jOxxAkQs0dCX5PrsI2L3/wbAJ5HxOwKBgQDAS+rARe9R+IzTthRs/QHNCOeBnzGhfDtOCJ+d\n" +
"geq1P2GZ3iIQxV0lV30pbvgZA3MvLVVj56QhxdEjkqqFLENsY08sEXnJc0RjGZRsg0WuxOPsjxY1\n" +
"Bx9Pq0XljPsfynjbDhiH8mFibAEOJ+u5x1WRmZeYxFfS6TcaxhSuXREfBQKBgQCvWmoj0nnrDHOM\n" +
"nI1ohpJGQ+dET3qvpXcxKbwbacSjyiM6jf9OfjdSEIkP9/bkpavbcUAfNNm34xrKLNmJup4R23Xv\n" +
"/DIRJ64Fo2bgdOPh9Jak2PEaQoxAQ7AKpBNuOBjccaAt6VRIrQkbHg1dK2Zhgth0/wD1AiHvdFxN\n" +
"WFARQQKBgAsPKujqLWyQjpFiqk51/mbGP0xnK6QQI4981pG9UkHRugL5EIUwe4mBSa2v9nIsqJ29\n" +
"Qk2pvaILZWUniVzcK4stbx1ML3HEcpsTi0/w49Abl0k/0ycmErey63bSgf5fszGti/MBOLVagxsa\n" +
"7srdWq2DntK5AHy7gSk+WcMiHF8v";
private final static String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8SbchwEQDHuvStDqKqDvtcn16431hbpr\n" +
"PByzowKyTclSWqVAuA69EXI9HuMAMtUAkCbMQpfDnorYlQLoKDC9/WXQjDxDXPbvyxBlVJQgfAd7\n" +
"YwfRaA1syhKiOglz+RmvNHTUTWpAu/2glBXVXb2APpuFDbW8z/igfka0EJAPUzwUpv9uT2pwZAh6\n" +
"5kUCHgtkUM+Hk45KUqQPe35lLE40jlKwJfeDhnWdhIllDGbje5Rduvw1LKy5RwdeZeH9dh37L1ck\n" +
"RgpFivaYNCy6CaQhKvCCRMbK0wTk+kB091cdqChbB1aerINi5J5PlvIqEbyzxm+gjx7uCKu9GwnM\n" +
"lS7tJQIDAQAB";
public String encryptedString(String plain) throws Exception {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(PRIVATE_KEY, Base64.DEFAULT));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey key = keyFactory.generatePrivate(keySpec);
byte[] dataToBytes = plain.getBytes("UTF-8");
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, key);
return Base64.encodeToString(cipher.doFinal(dataToBytes), Base64.DEFAULT);
}
I am encrypting with above code and trying to decrypt with below code. Its not working.
var NodeRSA = require('node-rsa');
var key = new NodeRSA();
key.importKey(privateKeyData, 'pkcs8-private');
key.importKey(publicKeyData, 'pkcs8-public');
var decrypted = key.decryptPublic(encrypted, 'utf8');
The process is:
I have generated a key pair and saved them statically on both sides.
Encrypting and Decrypting on Android and NodeJs individually works very well.
But its not working as i wanted, Asymmetric client-server encryption.
I also found that the two encrypted strings created by Android and NodeJs are not same.
Can anyone show me a solution or point me to an alternative for asymmetric encryption which works on Android and NodeJs.

Related

How to encrypt the Key and IV which used in AES Encryption Model in android App

I have android application which has payment gateway and another services.Iam using AES Model to encrypt and decrypt data between the app and the server.Iam using KEY and IV constants which stored in android class. My problem is how to encrypt these constants ( IV and Key) in the android application to prevent any attacker to make decompile for the APK file and show these constants.
You have to Encrypt the Key with a RSA Public Key and only the Server knows the privatekey for this public key and can decrypt it.
You decrypt the AES Key with the private key on the serverside and use the decrypted AES Key to decrypt your original message.
//Edit
This is an example for the Java Code in Android Studio. My RSA Public key is stored in the shared preferences.
When the app is installed it makes a call to a Server, where a RSA Key pair is produced, both keys are saved in a Database and the Public Key is sent to the Device and saved in the shared preferences. Whenever something Needs to be Encrypted the stored Public Key is created and used for Encryption and only the Server knows the private key.
byte[] ENCRYPTED_AES_KEY_IN_BYTE = null;
String ENCRYPTED_AES_KEY;
cipher = null;
cipher = Cipher.getInstance("RSA/NONE/OAEPwithSHA-1andMGF1Padding");
// Get the shared preferences where the public key is stored
// SharedPreferences preferences = getApplicationContext().getSharedPreferences(preferences,Context.MODE_PRIVATE);
// get the Publickey stored as string in the shared preferences
String stringkey = preferences.getString(PUBLICKEY,"");
// create a public RSA Key from the stored key
X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.decode(stringkey,Base64.DEFAULT));
KeyFactory keyFactory;
PublicKey key =null;
keyFactory = KeyFactory.getInstance("RSA");
key = keyFactory.generatePublic(spec);
//Encrypt the AES key with the RSA public key
cipher.init(Cipher.ENCRYPT_MODE, key);
ENCRYPTED_AES_KEY_IN_BYTES = AES_KEY.getEncoded();
ENCRYPTED_AES_KEY_IN_BYTE = cipher.doFinal(ENCRYPTED_AES_KEY_IN_BYTE);
ENCRYPTED_AES_KEY = Base64.encodeToString(ENCRYPTED_AES_KEY_IN_BYTE,Base64.DEFAULT);
//ENCRYPTED_AES_KEY is now the Encrypted AES Key as string
// EDIT #2
Create a RSA KEY pair at the server
$rsa = new Crypt_RSA();
$rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS8);
$rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS8);
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
extract($rsa->createKey());
$publickey = str_replace("-----BEGIN PUBLIC KEY-----\r\n","",$publickey);
$publickey = str_replace("-----END PUBLIC KEY-----","",$publickey);
$privatekey = str_replace("-----BEGIN PRIVATE KEY-----\r\n","",$privatekey);
$privatekey = str_replace( "-----END PRIVATE KEY-----","",$privatekey);
the privatekey is saved to a Database and the Publickey is sent to the Client to Encrypt data.
To Decrypt the Data on the Serverside again
$rsa = new Crypt_RSA();
$rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS8);
$rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS8);
$rsa->setEncryptionMode( CRYPT_RSA_ENCRYPTION_OAEP);
$IV = base64_decode($IV);
$AESkey = base64_decode($AESkey);
$rsa->loadKey($privatekey);
$AESkey = $rsa->decrypt($AESkey);
// replace empty spaces with a + , this is something which can happen when you use a http request
$encrypteddata = str_replace(" ", "+", $encrypteddata);
$encrypteddata = base64_decode($encrypteddata);
$method = "AES-256-CBC";
$decrypteddata = openssl_decrypt($encrypteddata, $method, $AESkey, OPENSSL_RAW_DATA,$IV);
In this Code is not included how you store the privatekey in a Database and how you get it back from the Database.

How to store and retrieve an RSA public key in Android keystore which is generated from server side application?

The server side application generate an RSA key pair,and as a part of key exchange process i get this public key from server and now i want to store this key inside android KeyStore. I have seen examples with generating rsa key pair using KeyGenerator and storing them in android KeyStore but i have no clue on how to store an already generated RSA public key. Any help would be highly appreciated.
I'm not sure what parts are confusing you, or what exactly you are trying to achieve. KeyStore can only hold three types of entries: symmetric keys, private keys, and certificates. Therefore, if you want to store a public key it must be formatted into a certificate. Whether your application uses any of the other features of X509 certificates is up to you.
It's also not clear if you want to use any old keystore on Android, or the AndroidKeyStore. The latter offers enhanced features, but whether you need them or not is dependent on your threat model. In any event, here is an example that shows how to import a google public key into the Android Keystore, how to set some properties on it, and how to use it to encrypt an AES key.
import android.security.keystore.KeyProperties;
import android.security.keystore.KeyProtection;
import android.util.Base64;
import android.util.Log;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
public class MainActivity extends AppCompatActivity {
private static final String THE_CERT = "-----BEGIN CERTIFICATE-----\n" +
"MIIIPjCCByagAwIBAgIIWcyJ5Cnzp3UwDQYJKoZIhvcNAQELBQAwSTELMAkGA1UE\n" +
"BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl\n" +
"cm5ldCBBdXRob3JpdHkgRzIwHhcNMTgwMzEzMTgzMDQ1WhcNMTgwNjA1MTgxNjAw\n" +
"WjBmMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN\n" +
"TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEVMBMGA1UEAwwMKi5n\n" +
"b29nbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtXqeeS6r\n" +
"sLfE5dx5asD7dngw0Dev9rhgDYM9kAuV9VxbZJ2ehZM4Nk1zGGSlqidgRWsVSNrx\n" +
"qb513IyrtxDSvTTGh8ihFGNTL/H61e+cYU565RCw4siOU0IevyhynPVh8D38pe5U\n" +
"bkGDmkiP7tOVozQE+3Q7l6xaIvlq9hIAb0aTWdJ6AOm3r/iMRdiUv/kxIienQ4v/\n" +
"RY/h3K/llz1E+S+TAyM2+As8o2nRMGrp9/hg8zIs3CLLv2km9VS/fgTQrM5pcfDf\n" +
"iX6Tgzb+6RSGHnT7GgNA3R1LXo96gnwf3zlX3SqpvV8pQf2Y3TxhLRB7J28yZFef\n" +
"P6d9t2EqlHZv+wIDAQABo4IFCzCCBQcwEwYDVR0lBAwwCgYIKwYBBQUHAwEwggPh\n" +
"BgNVHREEggPYMIID1IIMKi5nb29nbGUuY29tgg0qLmFuZHJvaWQuY29tghYqLmFw\n" +
"cGVuZ2luZS5nb29nbGUuY29tghIqLmNsb3VkLmdvb2dsZS5jb22CFCouZGI4MzM5\n" +
"NTMuZ29vZ2xlLmNuggYqLmcuY2+CDiouZ2NwLmd2dDIuY29tghYqLmdvb2dsZS1h\n" +
"bmFseXRpY3MuY29tggsqLmdvb2dsZS5jYYILKi5nb29nbGUuY2yCDiouZ29vZ2xl\n" +
"LmNvLmlugg4qLmdvb2dsZS5jby5qcIIOKi5nb29nbGUuY28udWuCDyouZ29vZ2xl\n" +
"LmNvbS5hcoIPKi5nb29nbGUuY29tLmF1gg8qLmdvb2dsZS5jb20uYnKCDyouZ29v\n" +
"Z2xlLmNvbS5jb4IPKi5nb29nbGUuY29tLm14gg8qLmdvb2dsZS5jb20udHKCDyou\n" +
"Z29vZ2xlLmNvbS52boILKi5nb29nbGUuZGWCCyouZ29vZ2xlLmVzggsqLmdvb2ds\n" +
"ZS5mcoILKi5nb29nbGUuaHWCCyouZ29vZ2xlLml0ggsqLmdvb2dsZS5ubIILKi5n\n" +
"b29nbGUucGyCCyouZ29vZ2xlLnB0ghIqLmdvb2dsZWFkYXBpcy5jb22CDyouZ29v\n" +
"Z2xlYXBpcy5jboIUKi5nb29nbGVjb21tZXJjZS5jb22CESouZ29vZ2xldmlkZW8u\n" +
"Y29tggwqLmdzdGF0aWMuY26CDSouZ3N0YXRpYy5jb22CCiouZ3Z0MS5jb22CCiou\n" +
"Z3Z0Mi5jb22CFCoubWV0cmljLmdzdGF0aWMuY29tggwqLnVyY2hpbi5jb22CECou\n" +
"dXJsLmdvb2dsZS5jb22CFioueW91dHViZS1ub2Nvb2tpZS5jb22CDSoueW91dHVi\n" +
"ZS5jb22CFioueW91dHViZWVkdWNhdGlvbi5jb22CByoueXQuYmWCCyoueXRpbWcu\n" +
"Y29tghphbmRyb2lkLmNsaWVudHMuZ29vZ2xlLmNvbYILYW5kcm9pZC5jb22CG2Rl\n" +
"dmVsb3Blci5hbmRyb2lkLmdvb2dsZS5jboIcZGV2ZWxvcGVycy5hbmRyb2lkLmdv\n" +
"b2dsZS5jboIEZy5jb4IGZ29vLmdsghRnb29nbGUtYW5hbHl0aWNzLmNvbYIKZ29v\n" +
"Z2xlLmNvbYISZ29vZ2xlY29tbWVyY2UuY29tghhzb3VyY2UuYW5kcm9pZC5nb29n\n" +
"bGUuY26CCnVyY2hpbi5jb22CCnd3dy5nb28uZ2yCCHlvdXR1LmJlggt5b3V0dWJl\n" +
"LmNvbYIUeW91dHViZWVkdWNhdGlvbi5jb22CBXl0LmJlMGgGCCsGAQUFBwEBBFww\n" +
"WjArBggrBgEFBQcwAoYfaHR0cDovL3BraS5nb29nbGUuY29tL0dJQUcyLmNydDAr\n" +
"BggrBgEFBQcwAYYfaHR0cDovL2NsaWVudHMxLmdvb2dsZS5jb20vb2NzcDAdBgNV\n" +
"HQ4EFgQU2Xh9D7F5dJYCBqsWcKChI16NReswDAYDVR0TAQH/BAIwADAfBgNVHSME\n" +
"GDAWgBRK3QYWG7z2aLV29YG2u2IaulqBLzAhBgNVHSAEGjAYMAwGCisGAQQB1nkC\n" +
"BQEwCAYGZ4EMAQICMDAGA1UdHwQpMCcwJaAjoCGGH2h0dHA6Ly9wa2kuZ29vZ2xl\n" +
"LmNvbS9HSUFHMi5jcmwwDQYJKoZIhvcNAQELBQADggEBAFxBsH2U6j4KzZbNcyN1\n" +
"UGiJnMn64DIXH8wsWrFEGAq3ONRhPgKd3AnbaBUdNdrRgOhfA3RtLvvnxsKn0rX6\n" +
"Oz8+p5DZxJooUgWlet9NounLDe5um6m5NqLIGefdI49Ukn6IwBtCO5DD7rZTygTa\n" +
"B499H9N0ixI9wGBdlZ37tOpCxayNb08eizU1uQEhb1/oxnXf0e6trPfC8krDL0Ks\n" +
"Pyf3JgB5oBTiNAfix2zme1FrpXcKehOj2urnLQRr5EpminCJ+0uHI1sqiJbcSHrU\n" +
"6TPQcOzZ7/haw1yY2bpy+sB4oXUMaNJxh6e2AiCeVf4MtX9EsYEnhsfc2XS50J32\n" +
"nKo=\n" +
"-----END CERTIFICATE-----";
private void doExample() {
try {
X509Certificate googleCert = (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(new ByteArrayInputStream(THE_CERT.getBytes(StandardCharsets.UTF_8)));
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
KeyProtection keyProtection = new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_VERIFY)
.setDigests(KeyProperties.DIGEST_SHA1, KeyProperties.DIGEST_SHA256)
.setRandomizedEncryptionRequired(true)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
.setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PSS)
.setUserAuthenticationRequired(false)
.build();
keyStore.load(null);
keyStore.setEntry("googlecert", new KeyStore.TrustedCertificateEntry(googleCert), keyProtection);
// Now use the entry
KeyGenerator aesKeygen = KeyGenerator.getInstance("AES");
aesKeygen.init(128);
Key aesKey = aesKeygen.generateKey();
// Wrap key for transport
KeyStore keyStore2 = KeyStore.getInstance("AndroidKeyStore");
keyStore2.load(null);
Certificate googleCert2 = keyStore2.getCertificate("googlecert");
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/OAEPwithSHA-256andMGF1Padding");
rsaCipher.init(Cipher.WRAP_MODE, googleCert2);
byte[] rsaEncrypted = rsaCipher.wrap(aesKey);
Log.d("crypt", Base64.encodeToString(rsaEncrypted, Base64.DEFAULT));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

How to secure webservice URL?

I have an android app with web service urls. If anyone decrypts my apk file, the webservice url will become visible.I am using HTTP POST for calling web service.
Anyone can read the code by decompiling the apk file from this site.
My registration page url got hacked and sending bulk request to this url with post data. I was using a API_KEY and send the API_KEY with post data. API_KEY was stored in gradle.properties file.
I did not used
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'` when its got hacked.
After some search, i know that there is no 100% secure methods to hide url.
My code for registration is :
String link = "http://xxxxxxxxxx.php";
String data = URLEncoder.encode("name", "UTF-8") + "=" + URLEncoder.encode(name, "UTF-8");
data += "&" + URLEncoder.encode("phone", "UTF-8") + "=" + URLEncoder.encode(phone, "UTF-8");
data += "&" + URLEncoder.encode("password", "UTF-8") + "=" + URLEncoder.encode(password, "UTF-8");
URL url = new URL(link);
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();
I don't know if it is the correct method to post data to a Url.
How can i secure my source code?
Can i store all my web service url in server?
I am beginner to android. Please help!
I use it this in all android application I developed
gradle.properties
API = http://ec2xxxxx.compute.amazonaws.com
API_KEY = $2c11SoL/NjJ28
create utils.gradle
utils.gradle
class Utils {
static def r = new Random(System.currentTimeMillis())
}
def String toJavaCodeString(String string) {
byte[] b = string.getBytes();
int c = b.length;
StringBuilder sb = new StringBuilder();
sb.append("(new Object() {");
sb.append("int t;");
sb.append("public String toString() {");
sb.append("byte[] buf = new byte[");
sb.append(c);
sb.append("];");
for (int i = 0; i < c; ++i) {
int t = Utils.r.nextInt();
int f = Utils.r.nextInt(24) + 1;
t = (t & ~(0xff << f)) | (b[i] << f);
sb.append("t = ");
sb.append(t);
sb.append(";");
sb.append("buf[");
sb.append(i);
sb.append("] = (byte) (t >>> ");
sb.append(f);
sb.append(");");
}
sb.append("return new String(buf);");
sb.append("}}.toString())");
return sb.toString();}
ext.toJavaCodeString = this.&toJavaCodeString
build.gradle
apply from: "utils.gradle"
android {
defaultConfig {
buildConfigField 'String', 'API', toJavaCodeString(API)
buildConfigField 'String', 'API_KEY', toJavaCodeString(API_KEY)
}}
and access your private url;
public static final String API = BuildConfig.API;
There is no way to protect "secret" information such as URLs embedded in an APK. A determined / motivated hacker can defeat any scheme you care to design ... if he / she has access to a platform where your app is being run.
In order for your app to run, the app running on the user's device needs to be able to decrypt the hidden URL. The user can either intercept the URL in decrypted form in the app's address space, or he / she can reverse engineer the algorithm and decryption key you are using to do the decryption.
Another "attack" is that your app needs to use the URL to make a request. That request can be intercepted on the users device before it is protected by the SSL / TLS channel to your (presumably) HTTPS enabled service.
And on top of that, if you embed a "secret" URL into an app and that secret is compromised and you have to turn off / relocate your server, then you are making problems for all (legitimate, paying, etc) users of your app. They won't be happy campers.
The correct approach is to make your service secure ... and use some kind of authentication mechanism so that hackers need more than just the URL to make requests. Users can / should be issued with individual credentials (e.g. auth keys), and you need to implement a way to invalidate a given users' credentials at the server end.
"URL" stands for Universal Resource Locator. The whole point of a URL is to access some kind of resource, and to do this, you obviously have to tell the network you are connecting to what it is you want to fetch.
Now if you are worried that a hacker can access your source code, then surely he can also hook up Wireshark or Fiddler and simply observe what connections your app is making, and what info you are passing along and receiving back.
Sorry, but I simply can't see any good way around this.
If you're worried about your server/services being hacked or DOS`ed, I think you had better focus on securing them as well as you can, rather than trying to hide them.
I have fixed this in two ways
Encrypted the URL in my code with my private key and on request call i decrypted it again,
public static String encryptIt(String value) {
try {
DESKeySpec keySpec = new DESKeySpec(new byte[]{105, 107, 18, 51, 114, 83, 51, 120, 121});
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(keySpec);
byte[] clearText = value.getBytes("UTF8");
// Cipher is not thread safe
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key);
// Log.d("aa", "Encrypted: " + value + " -> " + encrypedValue);
return Base64.encodeToString(cipher.doFinal(clearText), Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
and decript it by using this
public static String decryptIt(String value) {
try {
DESKeySpec keySpec = new DESKeySpec(new byte[]{105, 107, 18, 51, 114, 83, 51, 120, 121});//cryptoPass.getBytes("UTF8"));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(keySpec);
byte[] encrypedPwdBytes = Base64.decode(value, Base64.DEFAULT);
// cipher is not thread safe
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decrypedValueBytes = (cipher.doFinal(encrypedPwdBytes));
// Log.d("aa", "Decrypted: " + value + " -> " + decrypedValue);
return new String(decrypedValueBytes);
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
note in my case that the private key is new byte[]{105, 107, 18, 51, 114, 83, 51, 120, 121} i think it was $ecrEt or something like i forget it.
so if they decompile the APK they wan't be able to find the service link inside you code.
so the base url will be like this public static final String ROOT_API = "aHR0cHSC86LSy9tbS2JpuZW50aWtoYWAbGUJhdC5qbw==";
2- Also you have to add progaurd to your code
BUT, they can smurfing the netweok and find the url if the hacker is advance person, in this case you have to user SSl certificate "https" and make the webserivce POST.
hope you got my point.

Android - generating PKCS#10 requests

I'm trying to create certificate requests according to PKCS#10.
X509v3 Key Usage should be set to: Digital Signature, Key Encipherment.
This is what I've found so far, but since I use latest bouncycastle (1.52) the X509Extension.keyUsage is deprecated.
public static PKCS10CertificationRequest generateCSRFile(KeyPair keyPair, KeyUsage keyUsage) throws IOException, OperatorCreationException {
String principal = "CN=" + Utils.getCertificateCommonName() + ", O=" + Utils.getCertificateOrganization();
AsymmetricKeyParameter privateKey = PrivateKeyFactory.createKey(keyPair.getPrivate().getEncoded());
AlgorithmIdentifier signatureAlgorithm = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1WITHRSA");
AlgorithmIdentifier digestAlgorithm = new DefaultDigestAlgorithmIdentifierFinder().find("SHA-1");
ContentSigner signer = new BcRSAContentSignerBuilder(signatureAlgorithm, digestAlgorithm).build(privateKey);
PKCS10CertificationRequestBuilder csrBuilder = new JcaPKCS10CertificationRequestBuilder(new X500Name(principal), keyPair.getPublic());
ExtensionsGenerator extensionsGenerator = new ExtensionsGenerator();
extensionsGenerator.addExtension(X509Extension.basicConstraints, true, new BasicConstraints(true));
extensionsGenerator.addExtension(X509Extension.keyUsage, true, keyUsage);
csrBuilder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, extensionsGenerator.generate());
PKCS10CertificationRequest csr = csrBuilder.build(signer);
return csr;
}
Is there another way to add KeyUsage?
Basically this is what I'm trying to achieve:
Generate certificate requests with PKCS#10
Create two certificates from two keypairs (Digital Signature + Key Encipherment and Non Repudiation).
Save the private keys from the certificate requests in PKCS#12.
I'm quite new when it comes to cryptography.
Does this work for you? X509Extension seems to be replaceable with Extension. Not sure on the Android context though.
public static PKCS10CertificationRequest generateCSRFile(KeyPair keyPair, KeyUsage keyUsage) throws IOException, OperatorCreationException {
String principal = "CN=" + Utils.getCertificateCommonName() + ", O=" + Utils.getCertificateOrganization();
AsymmetricKeyParameter privateKey = PrivateKeyFactory.createKey(keyPair.getPrivate().getEncoded());
AlgorithmIdentifier signatureAlgorithm = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1WITHRSA");
AlgorithmIdentifier digestAlgorithm = new DefaultDigestAlgorithmIdentifierFinder().find("SHA-1");
ContentSigner signer = new BcRSAContentSignerBuilder(signatureAlgorithm, digestAlgorithm).build(privateKey);
PKCS10CertificationRequestBuilder csrBuilder = new JcaPKCS10CertificationRequestBuilder(new X500Name(principal), keyPair.getPublic());
ExtensionsGenerator extensionsGenerator = new ExtensionsGenerator();
extensionsGenerator.addExtension(Extension.basicConstraints, true, new BasicConstraints(true));
extensionsGenerator.addExtension(Extension.keyUsage, true, keyUsage);
csrBuilder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, extensionsGenerator.generate());
PKCS10CertificationRequest csr = csrBuilder.build(signer);
return csr;
}

Authorization request header OAuth 2.0

I am trying to implement OAuth 2.0 on a project I am working on. I am able to authenicate with the authenication server however I am having problems with the resource server. We are using a MAC token(spec). You can see in 3.1 of the spec that I need to send a Authorization request header which includes the following. I can't make any sense of that. Can somebody show me what I am suppose to do here?
credentials = "MAC" [ RWS 1#param ]
param = id /
nonce /
body-hash /
ext /
mac
id = "id" "=" <"> plain-string <">
nonce = "nonce" "=" <"> 1*DIGIT ":" plain-string <">
body-hash = "bodyhash" "=" <"> plain-string <">
ext = "ext" "=" <"> plain-string <">
mac = "mac" "=" <"> plain-string <">
plain-string = 1*( %x20-21 / %x23-5B / %x5D-7E )
UPDATE
I feel I am getting somewhere but feel like I am still so far from solving this problem.
So I am building something like the following
StringBuilder header = new StringBuilder("MAC ").append("id=\"").append(sharedPrefs.getString(Constants.ACCESS_TOKEN, "error")).append("\",nonce=\"").append(createNonce()).
append("\",bodyhash=\"").append(bodyHash).append("\",mac=\"").append(mac).append("\"");
I calculate the body hash like so
public static String SHA256(String text) throws UnsupportedEncodingException {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] shahash = new byte[40];
md.update(text.getBytes("iso-8859-1"), 0, text.length());
shahash = md.digest();
return Base64.encodeToString(shahash, Base64.DEFAULT);
}
And the mac like this
private String hmacSHA256(String data) throws Exception {
String key = sharedPrefs.getString(Constants.SECRET, "error");
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secretKey);
byte[] hmacData = mac.doFinal(data.getBytes("UTF-8"));
//Log.i(TAG, "BYTE ARRAY TO STRING: " + Base64.encodeToString(hmacData, Base64.DEFAULT));
String value = Base64.encodeToString(hmacData, Base64.DEFAULT);
return value;
}
I am having problems as the server just doesn't respond. This is really driving me crazy, I can't image that this documentation is clear to anybody.
you need to be aware that the MAC access authentication scheme is an extension of the oauth2 protocol, similar to the HTTP Basic access, but optional, so there is no need to implement this in every resource server.
So if you make an unauthenticated request and the resource server respond something like:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: MAC
The MAC, means that you are allowed to use this scheme of authentication.
The most common authentication scheme implemented nowadays for oauth2-based resource servers is: bearer.
If you still have concerns about how to implement this spec, there is an excelent source for Android on Github to accomplish it. And probably the java class you need is this.
Have fun!

Categories

Resources