Python
Node.js
Go
Swift
Kotlin
import base64
import os
import requests
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
DEVICE_ID = "YOUR_DEVICE_ID"
API_BASE = "https://api.sendbag.cc"
def encrypt_field(plaintext: str, aes_key: bytes) -> str:
"""Encrypt a field with AES-256-GCM. Returns Base64(nonce || ciphertext || tag)"""
nonce = os.urandom(12)
aesgcm = AESGCM(aes_key)
ciphertext_with_tag = aesgcm.encrypt(nonce, plaintext.encode(), None)
return base64.b64encode(nonce + ciphertext_with_tag).decode()
def send_encrypted_notification(title: str, body: str, subtitle: str = ""):
# 1. Fetch public key
resp = requests.get(f"{API_BASE}/api/notifications/users/{DEVICE_ID}/public-key")
public_key_b64 = resp.json()["publicKey"]
public_key_der = base64.b64decode(public_key_b64)
public_key = serialization.load_der_public_key(public_key_der)
# 2. Generate AES key
aes_key = os.urandom(32)
# 3. Encrypt fields with AES-GCM
encrypted_title = encrypt_field(title, aes_key)
encrypted_subtitle = encrypt_field(subtitle, aes_key)
encrypted_body = encrypt_field(body, aes_key)
# 4. Encrypt AES key with RSA-OAEP-SHA256
encrypted_key = public_key.encrypt(
aes_key,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# 5. Send notification
requests.post(f"{API_BASE}/api/notifications", json={
"deviceId": DEVICE_ID,
"title": encrypted_title,
"subtitle": encrypted_subtitle,
"body": encrypted_body,
"plain": False,
"encryptedKey": base64.b64encode(encrypted_key).decode()
})
send_encrypted_notification("Hello", "This is E2E encrypted!")
const crypto = require('crypto');
const DEVICE_ID = 'YOUR_DEVICE_ID';
const API_BASE = 'https://api.sendbag.cc';
function encryptField(plaintext, aesKey) {
// Generate 12-byte nonce
const nonce = crypto.randomBytes(12);
// Encrypt with AES-256-GCM
const cipher = crypto.createCipheriv('aes-256-gcm', aesKey, nonce);
const ciphertext = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
const tag = cipher.getAuthTag();
// Format: nonce || ciphertext || tag
return Buffer.concat([nonce, ciphertext, tag]).toString('base64');
}
async function sendEncryptedNotification(title, body, subtitle = '') {
// 1. Fetch public key
const keyResp = await fetch(`${API_BASE}/api/notifications/users/${DEVICE_ID}/public-key`);
const { publicKey: publicKeyB64 } = await keyResp.json();
const publicKeyDer = Buffer.from(publicKeyB64, 'base64');
// 2. Generate AES key
const aesKey = crypto.randomBytes(32);
// 3. Encrypt fields with AES-GCM
const encryptedTitle = encryptField(title, aesKey);
const encryptedSubtitle = encryptField(subtitle, aesKey);
const encryptedBody = encryptField(body, aesKey);
// 4. Encrypt AES key with RSA-OAEP-SHA256
const publicKey = crypto.createPublicKey({ key: publicKeyDer, format: 'der', type: 'spki' });
const encryptedKey = crypto.publicEncrypt(
{ key: publicKey, oaepHash: 'sha256', padding: crypto.constants.RSA_PKCS1_OAEP_PADDING },
aesKey
).toString('base64');
// 5. Send notification
await fetch(`${API_BASE}/api/notifications`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
deviceId: DEVICE_ID,
title: encryptedTitle,
subtitle: encryptedSubtitle,
body: encryptedBody,
plain: false,
encryptedKey
})
});
}
sendEncryptedNotification('Hello', 'This is E2E encrypted!');
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/json"
"io"
"net/http"
)
const (
deviceID = "YOUR_DEVICE_ID"
apiBase = "https://api.sendbag.cc"
)
func encryptField(plaintext string, aesKey []byte) (string, error) {
block, _ := aes.NewCipher(aesKey)
gcm, _ := cipher.NewGCM(block)
nonce := make([]byte, 12)
io.ReadFull(rand.Reader, nonce)
ciphertext := gcm.Seal(nil, nonce, []byte(plaintext), nil)
// Format: nonce || ciphertext || tag (tag is appended by Seal)
combined := append(nonce, ciphertext...)
return base64.StdEncoding.EncodeToString(combined), nil
}
func sendEncryptedNotification(title, body, subtitle string) error {
// 1. Fetch public key
resp, _ := http.Get(apiBase + "/api/notifications/users/" + deviceID + "/public-key")
defer resp.Body.Close()
var keyData struct{ PublicKey string `json:"publicKey"` }
json.NewDecoder(resp.Body).Decode(&keyData)
publicKeyDer, _ := base64.StdEncoding.DecodeString(keyData.PublicKey)
pubKey, _ := x509.ParsePKIXPublicKey(publicKeyDer)
rsaPubKey := pubKey.(*rsa.PublicKey)
// 2. Generate AES key
aesKey := make([]byte, 32)
io.ReadFull(rand.Reader, aesKey)
// 3. Encrypt fields with AES-GCM
encTitle, _ := encryptField(title, aesKey)
encSubtitle, _ := encryptField(subtitle, aesKey)
encBody, _ := encryptField(body, aesKey)
// 4. Encrypt AES key with RSA-OAEP-SHA256
encKey, _ := rsa.EncryptOAEP(sha256.New(), rand.Reader, rsaPubKey, aesKey, nil)
// 5. Send notification
payload, _ := json.Marshal(map[string]interface{}{
"deviceId": deviceID, "title": encTitle, "subtitle": encSubtitle,
"body": encBody, "plain": false,
"encryptedKey": base64.StdEncoding.EncodeToString(encKey),
})
http.Post(apiBase+"/api/notifications", "application/json", bytes.NewReader(payload))
return nil
}
import Foundation
import CryptoKit
let deviceId = "YOUR_DEVICE_ID"
let apiBase = "https://api.sendbag.cc"
func encryptField(_ plaintext: String, key: SymmetricKey) throws -> String {
let nonce = AES.GCM.Nonce()
let data = Data(plaintext.utf8)
let sealedBox = try AES.GCM.seal(data, using: key, nonce: nonce)
// Format: nonce || ciphertext || tag
let combined = nonce + sealedBox.ciphertext + sealedBox.tag
return combined.base64EncodedString()
}
func sendEncryptedNotification(title: String, body: String, subtitle: String = "") async throws {
// 1. Fetch public key
let keyURL = URL(string: "\(apiBase)/api/notifications/users/\(deviceId)/public-key")!
let (keyData, _) = try await URLSession.shared.data(from: keyURL)
let keyJson = try JSONDecoder().decode([String: String].self, from: keyData)
let publicKeyData = Data(base64Encoded: keyJson["publicKey"]!)!
// Import RSA public key
var error: Unmanaged?
let publicKey = SecKeyCreateWithData(
publicKeyData as CFData,
[kSecAttrKeyType: kSecAttrKeyTypeRSA, kSecAttrKeyClass: kSecAttrKeyClassPublic] as CFDictionary,
&error
)!
// 2. Generate AES key
let aesKey = SymmetricKey(size: .bits256)
// 3. Encrypt fields with AES-GCM
let encTitle = try encryptField(title, key: aesKey)
let encSubtitle = try encryptField(subtitle, key: aesKey)
let encBody = try encryptField(body, key: aesKey)
// 4. Encrypt AES key with RSA-OAEP-SHA256
let aesKeyData = aesKey.withUnsafeBytes { Data($0) }
let encryptedKey = SecKeyCreateEncryptedData(
publicKey, .rsaEncryptionOAEPSHA256, aesKeyData as CFData, &error
)! as Data
// 5. Send notification
var request = URLRequest(url: URL(string: "\(apiBase)/api/notifications")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try JSONEncoder().encode([
"deviceId": deviceId, "title": encTitle, "subtitle": encSubtitle,
"body": encBody, "plain": "false", "encryptedKey": encryptedKey.base64EncodedString()
])
try await URLSession.shared.data(for: request)
}
import java.security.KeyFactory
import java.security.spec.X509EncodedKeySpec
import java.util.Base64
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.spec.GCMParameterSpec
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONObject
const val DEVICE_ID = "YOUR_DEVICE_ID"
const val API_BASE = "https://api.sendbag.cc"
fun encryptField(plaintext: String, aesKey: javax.crypto.SecretKey): String {
val nonce = ByteArray(12).apply { java.security.SecureRandom().nextBytes(this) }
val cipher = Cipher.getInstance("AES/GCM/NoPadding").apply {
init(Cipher.ENCRYPT_MODE, aesKey, GCMParameterSpec(128, nonce))
}
val ciphertext = cipher.doFinal(plaintext.toByteArray())
// Format: nonce || ciphertext (includes tag)
return Base64.getEncoder().encodeToString(nonce + ciphertext)
}
fun sendEncryptedNotification(title: String, body: String, subtitle: String = "") {
val client = OkHttpClient()
// 1. Fetch public key
val keyResp = client.newCall(
Request.Builder().url("$API_BASE/api/notifications/users/$DEVICE_ID/public-key").build()
).execute()
val publicKeyB64 = JSONObject(keyResp.body!!.string()).getString("publicKey")
val publicKeyDer = Base64.getDecoder().decode(publicKeyB64)
val publicKey = KeyFactory.getInstance("RSA")
.generatePublic(X509EncodedKeySpec(publicKeyDer))
// 2. Generate AES key
val aesKey = KeyGenerator.getInstance("AES").apply { init(256) }.generateKey()
// 3. Encrypt fields with AES-GCM
val encTitle = encryptField(title, aesKey)
val encSubtitle = encryptField(subtitle, aesKey)
val encBody = encryptField(body, aesKey)
// 4. Encrypt AES key with RSA-OAEP-SHA256
val rsaCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding").apply {
init(Cipher.ENCRYPT_MODE, publicKey)
}
val encryptedKey = Base64.getEncoder().encodeToString(rsaCipher.doFinal(aesKey.encoded))
// 5. Send notification
val json = JSONObject(mapOf(
"deviceId" to DEVICE_ID, "title" to encTitle, "subtitle" to encSubtitle,
"body" to encBody, "plain" to false, "encryptedKey" to encryptedKey
)).toString()
client.newCall(Request.Builder()
.url("$API_BASE/api/notifications")
.post(json.toRequestBody("application/json".toMediaType()))
.build()
).execute()
}