use of org.cyanogenmod.pushsms.bencode.BEncodedDictionary in project PushSms by koush.
the class GcmSocket method write.
@Override
public void write(ByteBufferList bb) {
try {
assert registration != null;
// construct a gcm json post object
JsonObject post = new JsonObject();
JsonArray regs = new JsonArray();
regs.add(new JsonPrimitive(registration.registrationId));
post.add("registration_ids", regs);
JsonObject data = new JsonObject();
post.add("data", data);
// serialize the unencrypted message
BEncodedDictionary envelope = new BEncodedDictionary();
// plop in the data we want to deliver
envelope.put("p", bb.getAllByteArray());
// include a sequence number to prevent replay attacks
envelope.put("lsn", registration.localSequenceNumber++);
// let the other end know what their sequence number is
// just in case we're out of sync
envelope.put("rsn", registration.remoteSequenceNumber);
// sign the data so authenticity can be verified
BEncodedDictionary signedMessage = new BEncodedDictionary();
byte[] signedEnvelope = envelope.toByteArray();
Signature signer = Signature.getInstance("SHA1withRSA");
signer.initSign(gcmConnectionManager.privateKey);
signer.update(signedEnvelope);
byte[] signature = signer.sign();
signedMessage.put("d", signedEnvelope);
signedMessage.put("s", signature);
// generate a symmetric key to be encrypted by the remote public key,
// and encrypt that. Asymmetric keys have payload limitations.
// http://en.wikipedia.org/wiki/Hybrid_cryptosystem
// http://stackoverflow.com/questions/6788018/android-encryption-decryption-with-aes
// see also the added benefit of multi recipient scenarios:
// http://security.stackexchange.com/questions/20134/in-pgp-why-not-just-encrypt-message-with-recipients-public-key-why-the-meta-e/20145#20145
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = new SecureRandom();
keyGenerator.init(128, secureRandom);
byte[] symmetricKey = keyGenerator.generateKey().getEncoded();
// Signature AND message should both be encrypted, as much as possible should be opaque:
// http://stackoverflow.com/questions/6587023/should-i-encrypt-the-signature
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(symmetricKey, "AES"));
byte[] encryptedSignedMessage = cipher.doFinal(signedMessage.toByteArray());
// Encrypt the asymmetric key so only the remote can decrypt it, and
// thus decrypt the message payload
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, registration.remotePublicKey);
byte[] encryptedSymmetricKey = cipher.doFinal(symmetricKey);
// put the encrypted symmetric key and encrypted payload into the JSON, and send it off
BEncodedDictionary payload = new BEncodedDictionary();
// though right now we only put in a single encrypted symmetric key,
// wrap that key in an array. this will future proof the protocol
// for later possible multi recipient scenarios.
BEncodedList encryptedSymmetricKeys = new BEncodedList();
encryptedSymmetricKeys.add(encryptedSymmetricKey);
payload.put("esk", encryptedSymmetricKeys);
payload.put("esm", encryptedSignedMessage);
// now base64 the entire encrypted payload
data.add("p", new JsonPrimitive(Base64.encodeToString(payload.toByteArray(), Base64.NO_WRAP)));
// include our claimed number, as we would a text, so the other end can find us
data.addProperty("f", gcmConnectionManager.from);
// ship it
Ion.with(context).load("https://android.googleapis.com/gcm/send").setHeader("Authorization", "key=" + gcmConnectionManager.gcmApiKey).setJsonObjectBody(post).as(GcmResults.class).setCallback(new FutureCallback<GcmResults>() {
@Override
public void onCompleted(Exception e, GcmResults result) {
if (result == null || result.failure != 0 || result.success == 0) {
if (e == null) {
e = new Exception("gcm server failure");
// to trigger a refresh
if (registration.isRegistered())
registration.unregister();
}
report(e);
return;
}
currentBackoff = GRACE_DEFAULT;
}
});
} catch (Exception e) {
Log.e(LOGTAG, "Send exception", e);
report(e);
}
}
use of org.cyanogenmod.pushsms.bencode.BEncodedDictionary in project PushSms by koush.
the class SmsSocket method write.
@Override
public void write(ByteBufferList bb) {
final int thisMessageId = messageId++;
int parts = (bb.remaining() / 100) + 1;
int i = 0;
while (bb.hasRemaining()) {
BEncodedDictionary dict = new BEncodedDictionary();
dict.put("m", thisMessageId);
dict.put("c", parts);
dict.put("i", i++);
byte[] bytes = new byte[Math.min(bb.remaining(), 100)];
bb.get(bytes);
dict.put("d", bytes);
SmsManager.getDefault().sendDataMessage(number, null, smsPort, dict.toByteArray(), null, null);
}
}
Aggregations