During the unsuccessful attempt of habrasuicid in the comments on the article on psychological assistance to a child injured by SMS , I told about my dream in which Stalin fed the bound Durov with chocolate cookies, and the public key of Google Play went out of base64 in place of smoke from Stalin. This dream I had a dream after a long and tedious reversing of the mobile protocol Google Play. There, in the comments, I was offered to write a separate article about it. Well, actually this article is. In it, I propose to talk about my dream, as well as the EncryptedPasswd parameter in the POST request to android.clients.google.com/auth android.clients.google.com/auth . EncryptedPasswd field interested me so much. A couple of years ago, using Google Apps traffic interception, it was determined that the Android device’s login on Google Play is performed using a request of the following type:POST / auth HTTP / 1.1 Content-Type: application / x-www-form-urlencoded Content-Length: 404 Host: android.clients.google.com Connection: Keep-Alive User-Agent: GoogleLoginService / 1.3 (a10 JZO54K) accountType = HOSTED_OR_GOOGLE & Email = testemail% 40gmail.com & has_permission = 1 & add_account = 1 & EncryptedPasswd = AFcb4KS9WAU3NI_-jdMDSueqT-oO1-WN2B9pxB-te_Elx3MElC9B2TgAaWqkY7kiQSnGFEwaY1KVkizxadGsRnFnHa7vlRCrB4Me1XnHBuOz9oi48eBcm0rC7r8QaC_GPp1YPI8OFa0fZU_dTJypganc2tREsgE-_TJQSKWkA7zSWnsq8g% 3D% 3D & service = ac2dm & source = android & androidId = 378b05ab23e0e8e9 & device_country = ua & operatorCountry = ua & lang = en & sdk_version = 16
EncryptedPasswd parameter. Enhanced googling gave only that EncryptedPasswd - this is possibly a google account password encrypted with the Google public key. And yet, no more technical details. This vague answer, of course, did not suit me, and I climbed inside com.google.android.gsf.login .com.google.android.gsf.loginservice.PasswordEncrypter class - this is the one that is responsible for encrypting the password. Reverse engineering of this class showed that encryption ... but I will not bother my dear reader with tons of Dalvik bytecode, I'd rather give you a working javascript in Java (the encoder is so-so): // Google private static final String googleDefaultPublicKey = "AAAAgMom/1a/v0lblO2Ubrt60J2gcuXSljGFQXgcyZWveWLEwo6prwgi3iJIZdodyhKZQrNWp5nKJ3srRXcUW+F1BD3baEVGcmEgqaLZUNBjm057pKRI16kB0YppeGx5qIQ5QjKzsR8ETQbKLNWgRY0QRNVz34kMJR3P/LgHax/6rmf5AAAAAwEAAQ=="; // : // login - myemail@gmail.com // password - // : // base64 // ! , // login+password // 80 ( - // ) @SuppressWarnings("static-access") public static String encrypt(String login, String password) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, UnsupportedEncodingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { // Google login public base64 // PublicKey SHA-1 : // 1. Google login public base64 byte[] byte[] binaryKey = Base64.decode(googleDefaultPublicKey, 0); // 2. BigInteger int i = readInt(binaryKey, 0); byte [] half = new byte[i]; System.arraycopy(binaryKey, 4, half, 0, i); BigInteger firstKeyInteger = new BigInteger(1, half); // 3. BigInteger int j = readInt(binaryKey, i + 4); half = new byte[j]; System.arraycopy(binaryKey, i + 8, half, 0, j); BigInteger secondKeyInteger = new BigInteger(1, half); // 4. SHA-1 signature: // signature[0] = 0 ( !) // signature[1...4] = 4 SHA-1 byte[] sha1 = MessageDigest.getInstance("SHA-1").digest(binaryKey); byte[] signature = new byte[5]; signature[0] = 0; System.arraycopy(sha1, 0, signature, 1, 4); // 5. BigInteger' // PublicKey publicKey = KeyFactory.getInstance("RSA"). generatePublic(new RSAPublicKeySpec(firstKeyInteger, secondKeyInteger)); // : // 1. Cipher: Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA1ANDMGF1PADDING"); // 2. "\u0000" : String combined = login + "\u0000" + password; // 3. : byte[] plain = combined.getBytes("UTF-8"); // 4. cipher.init(cipher.PUBLIC_KEY, publicKey); byte[] encrypted = cipher.doFinal(plain); // 5. output 133 : // output[0] = 0 ( 0) // output[1...4] = 4 SHA-1 // output[5...132] = + ( "\u0000") byte[] output = new byte [133]; System.arraycopy(signature, 0, output, 0, signature.length); System.arraycopy(encrypted, 0, output, signature.length, encrypted.length); // ! output base64 :) return Base64.encodeToString(output, Base64.URL_SAFE + Base64.NO_WRAP); } // , 4 int private static int readInt(byte[] arrayOfByte, int start) { return 0x0 | (0xFF & arrayOfByte[start]) << 24 | (0xFF & arrayOfByte[(start + 1)]) << 16 | (0xFF & arrayOfByte[(start + 2)]) << 8 | 0xFF & arrayOfByte[(start + 3)]; } / 1a / v0lblO2Ubrt60J2gcuXSljGFQXgcyZWveWLEwo6prwgi3iJIZdodyhKZQrNWp5nKJ3srRXcUW + F1BD3baEVGcmEgqaLZUNBjm057pKRI16kB0YppeGx5qIQ5QjKzsR8ETQbKLNWgRY0QRNVz34kMJR3P / LgHax / 6rmf5AAAAAwEAAQ =="; // Google private static final String googleDefaultPublicKey = "AAAAgMom/1a/v0lblO2Ubrt60J2gcuXSljGFQXgcyZWveWLEwo6prwgi3iJIZdodyhKZQrNWp5nKJ3srRXcUW+F1BD3baEVGcmEgqaLZUNBjm057pKRI16kB0YppeGx5qIQ5QjKzsR8ETQbKLNWgRY0QRNVz34kMJR3P/LgHax/6rmf5AAAAAwEAAQ=="; // : // login - myemail@gmail.com // password - // : // base64 // ! , // login+password // 80 ( - // ) @SuppressWarnings("static-access") public static String encrypt(String login, String password) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, UnsupportedEncodingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { // Google login public base64 // PublicKey SHA-1 : // 1. Google login public base64 byte[] byte[] binaryKey = Base64.decode(googleDefaultPublicKey, 0); // 2. BigInteger int i = readInt(binaryKey, 0); byte [] half = new byte[i]; System.arraycopy(binaryKey, 4, half, 0, i); BigInteger firstKeyInteger = new BigInteger(1, half); // 3. BigInteger int j = readInt(binaryKey, i + 4); half = new byte[j]; System.arraycopy(binaryKey, i + 8, half, 0, j); BigInteger secondKeyInteger = new BigInteger(1, half); // 4. SHA-1 signature: // signature[0] = 0 ( !) // signature[1...4] = 4 SHA-1 byte[] sha1 = MessageDigest.getInstance("SHA-1").digest(binaryKey); byte[] signature = new byte[5]; signature[0] = 0; System.arraycopy(sha1, 0, signature, 1, 4); // 5. BigInteger' // PublicKey publicKey = KeyFactory.getInstance("RSA"). generatePublic(new RSAPublicKeySpec(firstKeyInteger, secondKeyInteger)); // : // 1. Cipher: Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA1ANDMGF1PADDING"); // 2. "\u0000" : String combined = login + "\u0000" + password; // 3. : byte[] plain = combined.getBytes("UTF-8"); // 4. cipher.init(cipher.PUBLIC_KEY, publicKey); byte[] encrypted = cipher.doFinal(plain); // 5. output 133 : // output[0] = 0 ( 0) // output[1...4] = 4 SHA-1 // output[5...132] = + ( "\u0000") byte[] output = new byte [133]; System.arraycopy(signature, 0, output, 0, signature.length); System.arraycopy(encrypted, 0, output, signature.length, encrypted.length); // ! output base64 :) return Base64.encodeToString(output, Base64.URL_SAFE + Base64.NO_WRAP); } // , 4 int private static int readInt(byte[] arrayOfByte, int start) { return 0x0 | (0xFF & arrayOfByte[start]) << 24 | (0xFF & arrayOfByte[(start + 1)]) << 16 | (0xFF & arrayOfByte[(start + 2)]) << 8 | 0xFF & arrayOfByte[(start + 3)]; } EncryptedPasswd parameter. If you have any questions or clarifications - please in the comments.AAAAgMom / 1a / v0lblO2Ubrt60J2gcuXSljGFQXgcyZWveWLEwo6prwgi3iJIZdodyhKZQrNWp5nKJ3srRXcUW + F1BD3baEVGcmEgqaLZUNBjm057pKRI16kB0YppeGx5qIQ5QjKzsR8ETQbKLNWgRY0QRNVz34kMJR3P / LgHax / 6rmf5AAAAAwEAAQ ==
Source: https://habr.com/ru/post/220521/
All Articles