网站如何加密API响应?大型站点十六进制加密响应加解密方法问询
Hey there! Let's break down how those hex-encoded encrypted API responses you're spotting in Chrome's DevTools Network tab work—covering both how servers encrypt them and how clients decrypt the data.
First, a quick note: Hex encoding is just a way to convert binary ciphertext into a text-friendly format for HTTP transport (since HTTP is a text-based protocol). Before decryption, you always need to convert the hex string back to binary data.
1. AES (Advanced Encryption Standard) – The Most Widely Used
AES is symmetric encryption (same key for encryption and decryption) and perfect for large API responses. Common modes include CBC (Cipher Block Chaining) or GCM (Galois/Counter Mode, which adds authentication).
Server-Side Encryption (Python Example)
import os import binascii from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend def aes_encrypt(plaintext, key): # Generate a random 16-byte IV (required for CBC mode) iv = os.urandom(16) backend = default_backend() cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend) encryptor = cipher.encryptor() # Apply PKCS#7 padding to match AES's 16-byte block size padding_length = 16 - len(plaintext) % 16 padded_plaintext = plaintext + (chr(padding_length) * padding_length).encode('utf-8') # Encrypt and combine IV + ciphertext, then convert to hex ciphertext = encryptor.update(padded_plaintext) + encryptor.finalize() return binascii.hexlify(iv + ciphertext).decode('utf-8') # Usage secret_key = os.urandom(32) # 32 bytes = AES-256 plaintext = b"Confidential API Response Content" hex_encrypted_response = aes_encrypt(plaintext, secret_key) print(hex_encrypted_response)
Client-Side Decryption (JavaScript Example)
async function aesDecrypt(hexEncrypted, secretKeyBytes) { // Convert hex string to binary Uint8Array const encryptedData = new Uint8Array(hexEncrypted.match(/.{1,2}/g).map(byte => parseInt(byte, 16))); // Extract IV (first 16 bytes) and ciphertext const iv = encryptedData.slice(0, 16); const ciphertext = encryptedData.slice(16); // Import the secret key as a CryptoKey object const cryptoKey = await crypto.subtle.importKey( "raw", secretKeyBytes, { name: "AES-CBC" }, false, ["decrypt"] ); // Decrypt and remove PKCS#7 padding const decryptedBuffer = await crypto.subtle.decrypt( { name: "AES-CBC", iv: iv }, cryptoKey, ciphertext ); const padding = new Uint8Array(decryptedBuffer)[decryptedBuffer.byteLength - 1]; return new TextDecoder().decode(decryptedBuffer.slice(0, decryptedBuffer.byteLength - padding)); } // Usage example const secretKey = new Uint8Array(32); // Replace with actual shared key const hexResponse = "your-hex-encoded-response-from-network-tab"; aesDecrypt(hexResponse, secretKey).then(plaintext => { console.log("Decrypted API data:", plaintext); });
2. RSA – Asymmetric Encryption
RSA uses a public/private key pair (public key encrypts, private key decrypts). It’s typically used for small data (like encrypting an AES key) rather than full API responses, since it’s slower for large payloads.
Server-Side Encryption (Python Example)
import binascii from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives import serialization, hashes from cryptography.hazmat.backends import default_backend def rsa_encrypt(plaintext, public_key_pem): public_key = serialization.load_pem_public_key( public_key_pem.encode('utf-8'), backend=default_backend() ) ciphertext = public_key.encrypt( plaintext, padding.OAEP( mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None ) ) return binascii.hexlify(ciphertext).decode('utf-8') # Usage public_key_pem = """-----BEGIN PUBLIC KEY----- YOUR_CLIENT_PUBLIC_KEY_HERE -----END PUBLIC KEY-----""" small_plaintext = b"Encrypted AES Key" hex_encrypted = rsa_encrypt(small_plaintext, public_key_pem)
Client-Side Decryption (JavaScript Example)
async function rsaDecrypt(hexEncrypted, privateKeyPem) { const encryptedData = new Uint8Array(hexEncrypted.match(/.{1,2}/g).map(byte => parseInt(byte, 16))); // Import PKCS#8 formatted private key const privateKey = await crypto.subtle.importKey( "pkcs8", new TextEncoder().encode(privateKeyPem), { name: "RSA-OAEP", hash: "SHA-256" }, false, ["decrypt"] ); const decryptedBuffer = await crypto.subtle.decrypt( { name: "RSA-OAEP" }, privateKey, encryptedData ); return new TextDecoder().decode(decryptedBuffer); }
3. Custom Encryption Schemes
Some sites use custom algorithms (e.g., XOR with a rolling key, modified block ciphers) or obfuscated encryption logic. To reverse-engineer these:
- Use Chrome DevTools’ Sources tab to search for functions handling hex decoding or decryption (look for keywords like
hex,decrypt,CryptoJS) - Set breakpoints in code that processes the API response to track how the hex string is converted to binary and decrypted
- Check for obfuscated libraries that wrap standard encryption logic
Key Takeaways
- Hex → Binary First: Never try to decrypt a hex string directly—convert it to binary first.
- Key Security: For symmetric encryption, ensure the client and server exchange the secret key securely (e.g., via RSA-encrypted handshake or TLS).
- Padding Matters: Most encryption modes require padding (like PKCS#7) to align data with block sizes—always remove padding during decryption.
内容的提问来源于stack exchange,提问作者Amir Saleem

