โŒ

Normal view

There are new articles available, click to refresh the page.
Before yesterdayMain stream

How to encrypt and decrypt a token between flutter app and node js server

Im trying to hide a map token i have , i dont want to store to store it locally in the client so im trying to encrypt it with AES ECB and send it back to the user in order to decrypt it and use it.

Im using crypto-js in node server and encrypt package in flutter app , here is the code :

Node Server :

const express = require('express');
const router = express.Router();
const crypto = require("crypto-js");

const Map_Token_Controller = {
    async map_token(req, res) {
          try {
                    const token = "ASDFGHJKLASDFGHJ";
                    const secretKey = "ASDFGHJKLASDFGHJ";
                    const iv = "ASDFGHJKLASDFGHJ";
                    const ciphertext = crypto.AES.encrypt(token, secretKey, { mode: crypto.mode.ECB, padding: crypto.pad.Pkcs7 }).toString();
                    res.status(200).json(ciphertext);
            } catch (error) {
                    res.status(500).json({ error: error.message });
            }
    },
};


module.exports = Map_Token_Controller;

Flutter app :

//here i call the functions 
  Future<void> fetch_token() async {
    try {
      String token = await mapToken();
      String token2 = await decryptMessage(token);
      // print(token.runtimeType);
    } catch (error) {
      print('Error occurred: $error');
    }
  }
//API call
Future<String> mapToken() async {
  try {
    final response = await http.get(
      Uri.parse('${dotenv.env['baseUrl']}/map_token'),
      headers: requestHeaders,
    );
    if (response.statusCode == 200) {
      final data = response.body;
      print('Encrypted token: $data');
      return data;
    } else {
      throw Exception('Failed to fetch encrypted data');
    }
  } catch (error) {
    throw Exception('Error occurred: $error');
  }
}

//here i made the decrypt 
Future<String> decryptMessage(String token) async {
  try {
    //Key
    //var iv = encrypt.IV.fromUtf8('ASDFGHJKLASDFGHJ');
    var key = encrypt.Key.fromUtf8('ASDFGHJKLASDFGHJ');
    final encrypter = encrypt.Encrypter(
        encrypt.AES(key, mode: encrypt.AESMode.ecb, padding: 'PKCS7'));
    //Decode
    final decryptedToken = encrypter.decrypt(
      encrypt.Encrypted.fromUtf8(token),
    );
    print(decryptedToken);
    return decryptedToken;
  } catch (error) {
    throw Exception('Error occurred: $error');
  }
}

I have tried to encoded and send it as base64 i have tried everything i dont know what else im doing wrong , i set padding also to null i have tried with iv and mode CBC also,still nothing .

My errors depend if i set paddings or vi some of them are :

1)Error occurred: Exception: Error occurred: Invalid argument(s): Input buffer too short

2)Error occurred: Exception: Error occurred: Invalid argument(s): Input data length must be a multiple of cipher's block size

Also the result of encryption depend on some websites i used it must be like this : 6Waok3bTsS5XhI35WWsMz/+S7VmcsP+e+QtDugbp1ec=

and i get completly diffrent result with much more characters why ?

Encrypting process makes flutter app frozen until its done

I am making a flutter app and inside it the user can watch or download videos After downloading a video I want to encrypt it and then store it because I don't want the user to be able to share it. The encrypting process is being performed correctly however when it starts the app freezes for like 10 seconds before its finished and the app unfreezes I tried multiple encrypting methods but had the same result I read somewhere here that using "compute" methode and changing the function type to "FutureOr" can solve the problem. However, I cant seem to use it correctly. Any help would be appreciated.

  Future<void> downloadVideo(String url) async {
    var appDocDir = await getExternalStorageDirectory();
    String appDocPath = appDocDir!.path;
    String filePath = '$appDocPath/Videos/${url.split('/').last}';

    try {
      var request = await HttpClient().getUrl(Uri.parse(url));
      var response = await request.close();
      List<int> bytes = [];
      int downloaded = 0;
      int total = response.contentLength!;
      response.listen(
        (List<int> newBytes) {
          bytes.addAll(newBytes);
          downloaded += newBytes.length;
          downloadProgress.value = downloaded / total;
          print("Download progress: ${downloadProgress.value}");
        },
        onDone: () async {
          // Generate encryption key and IV
          final key = encrypt.Key.fromSecureRandom(32);
          final iv = encrypt.IV.fromSecureRandom(16);

          // Encrypt the video bytes
          final encrypter =
              encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc));
          final encryptedBytes = encrypter.encryptBytes(bytes, iv: iv).bytes;

          // Store the key and IV securely
          final storage = FlutterSecureStorage();
          await storage.write(key: 'key_$filePath', value: key.base64);
          await storage.write(key: 'iv_$filePath', value: iv.base64);

          // Save the encrypted video
          File file = File(filePath);
          await file.writeAsBytes(encryptedBytes);
          print("Download completed: $filePath");
        },
        onError: (e) {
          print("Error downloading video: $e");
        },
        cancelOnError: true,
      );
    } catch (e) {
      print("Error downloading video: $e");
    }
  }

Azure Virtual Network Encryption

What is Azure Virtual Network Encryption? Azure Virtual Network encryption provides a layer of security that encrypts virtual network traffic, specifically between Azure Virtual Machines that communicate securely within a subnet or across different subnets.

Node.js AES decryption code converted to Golang throws key size error

I have a nodesJS code which is used for decrypting and works fine. I was trying to convert the same in to Golang it always throws "panic: crypto/aes: invalid key size 7" error, which works perfectly when executed in NodeJs

NodeJs code :

const AesEncryption = require('aes-encryption')
var Buffer = require('buffer/').Buffer;
var CryptoJS = require("crypto-js");
const test = ""
const decodedCiphertext = Buffer.from(test, 'base64').toString('utf-8');
const decryptedData = CryptoJS.AES.decrypt(decodedCiphertext, 'D4jo0Ky')
const decryptedText = decryptedData.toString(CryptoJS.enc.Utf8);
console.log(decryptedText);

The will print the decrypted text correctly, but when convert these to go and run, its failing

GoLang code :

func main() {
encodedTest := "" // Replace with your test string
decodedCiphertext, _ := base64.StdEncoding.DecodeString(encodedTest)

key := []byte("s0k00py") // Replace with your AES key

block, err := aes.NewCipher(key)
if err != nil {
    panic(err.Error())
}

if len(decodedCiphertext) < aes.BlockSize {
    panic("Ciphertext block size is too short")
}

iv := decodedCiphertext[:aes.BlockSize]
decodedCiphertext = decodedCiphertext[aes.BlockSize:]

stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(decodedCiphertext, decodedCiphertext)

decryptedText := string(decodedCiphertext)
fmt.Println(decryptedText)
}

These one errors out with "panic: crypto/aes: invalid key size 7" , i tried to increase the key size to 16 byte using sha256.Sum256([]byte(inputString)), which prints garbage value in response.

Any help is much appreciated, thank you!

"Encrypt/Decrypt" is not defined while exporting nodule to an HTML file from a JS file

I am creating a program that emulates the Vigenere cipher algorithm in JavaScript. I am also creating an HTML page that would allow a user to type in a plain text phrase and encrypt/decrypt the message. When I type my plaintext message and enter in a key value, I get an error message 'encrypt is not defined.' I do not believe that my .js file is importing my functions correctly, or if the file is importing the functions, then I am not seeing my error. Could I get some insights into why I am not reaching my desired output?

function encrypt(plaintext, key) {
    if (!plaintext || !key || typeof plaintext !== 'string' || typeof key !== 'string' || key.match(/[^a-zA-Z]/)) {
        throw new Error('Invalid input: plaintext and key must be non-empty strings containing only alphabetic characters.');
    }

    var ciphertext = "";
    var keyIndex = 0;

    for (var i = 0; i < plaintext.length; i++) {
        var char = plaintext[i];

        if(/[a-zA-Z]/.test(char)) {
            var isUpperCase = char === char.toUpperCase();
            var plainCharCode = char.toUpperCase().charCodeAt(0) - 65;
            var keyCharCode = key[keyIndex % key.length].toUpperCase().charCodeAt(0) - 65;
            var encryptedCharCode = (plainCharCode + keyCharCode) % 26 + 65;

            ciphertext += isUpperCase ? String.fromCharCode(encryptedCharCode) : String.fromCharCode(encryptedCharCode).toLowerCase();
            keyIndex++;
        } else {
            ciphertext += char;
        }
    }

    return ciphertext;
}

function decrypt(ciphertext, key) {
    if (!ciphertext || !key || typeof ciphertext !== 'string' || typeof key !== 'string' || key.match(/[^a-zA-Z]/)) {
        throw new Error('Invalid input: ciphertext and key must be non-empty strings containing only alphabetic characters.');
    }

    var plaintext = "";
    var keyIndex = 0;

    for (var i = 0; i < ciphertext.length; i++) {
        var char = ciphertext[i];

        if (/[a-zA-Z]/.test(char)) {
            var isUpperCase = char === char.toUpperCase();
            var cipherCharCode = char.toUpperCase().charCodeAt(0) - 65;
            var keyCharCode = key[keyIndex % key.length].toUpperCase().charCodeAt(0) - 65;
            var decryptedCharCode = (cipherCharCode - keyCharCode + 26) % 26 + 65;

            plaintext += isUpperCase ? String.fromCharCode(decryptedCharCode) : String.fromCharCode(decryptedCharCode).toLowerCase();
            keyIndex++;
        } else {
            plaintext += char;
        }
    }

    return plaintext;
}

export { encrypt, decrypt };
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Assignment 4 - JavaScript</title>
  <script src="vigenere.js"></script>
  <style>
    .container {
      width: 50%;
      margin: auto;
    }
    .result {
      margin-top: 20px;
    }
    .error {
      color: red;
    }
  </style>
</head>
<body>
  <div class="container">
    <h2>Vigenere Cipher</h2>
    <form id="cipherForm">
      <div>
        <label for="plaintext">Plaintext:</label><br>
        <textarea id="plaintext" name="plaintext" rows="4" cols="50"></textarea>
      </div>
      <div>
        <label for="key">Key:</label><br>
        <input type="text" id="key" name="key">
      </div>
      <div>
        <button type="button" onclick="encryptText()">Encrypt</button>
        <button type="button" onclick="decryptText()">Decrypt</button>
      </div>
      <div class="result">
        <label for="ciphertext">Ciphertext:</label><br>
        <textarea id="ciphertext" name="ciphertext" rows="4" cols="50" readonly></textarea>
      </div>
      <div class="error" id="errorMessage"></div>
    </form>
  </div>

  <script>
    function encryptText() {
      var plaintext = document.getElementById("plaintext").value;
      var key = document.getElementById("key").value;
      try {
        var ciphertext = encrypt(plaintext, key);
        document.getElementById("ciphertext").value = ciphertext;
        document.getElementById("errorMessage").textContent = ""; // Clear any previous error messages
      } catch (error) {
        document.getElementById("errorMessage").textContent = error.message;
      }
    }

    function decryptText() {
      var ciphertext = document.getElementById("ciphertext").value;
      var key = document.getElementById("key").value;
      try {
        var plaintext = decrypt(ciphertext, key);
        document.getElementById("plaintext").value = plaintext;
        document.getElementById("errorMessage").textContent = ""; // Clear any previous error messages
      } catch (error) {
        document.getElementById("errorMessage").textContent = error.message;
      }
    }
  </script>
</body>
</html>

"binascii.Error: Incorrect padding" on python

I'm working on a chat client that supports E2EE (End-to-End Encryption). The process involves receiving the recipient's public key from the server and sending an encrypted message, which should normally arrive at the recipient's client and be decrypted. However, I'm encountering a strange error on the client side.

Here's the Client code :

import socket
import json
import threading
import sys
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
import os
import base64

KEY_FILE = "client_key.pem"

def generate_keys():
    if not os.path.exists(KEY_FILE):
        private_key = rsa.generate_private_key(
            public_exponent=65537,
            key_size=2048,
            backend=default_backend()
        )
        with open(KEY_FILE, "wb") as key_file:
            key_file.write(private_key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption()
            ))

def load_private_key():
    with open(KEY_FILE, "rb") as key_file:
        return serialization.load_pem_private_key(
            key_file.read(),
            password=None,
            backend=default_backend()
        )

def encrypt_message(public_key_pem, message):
    public_key = serialization.load_pem_public_key(
        public_key_pem.encode(),
        backend=default_backend()
    )
    encrypted = public_key.encrypt(
        message.encode(),
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    return base64.b64encode(encrypted).decode('utf-8')

def decrypt_message(private_key, encrypted_message):
    decrypted = private_key.decrypt(
        base64.b64decode(encrypted_message),
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    return decrypted.decode()

def receive_messages(client_socket, private_key):
    while True:
        try:
            message_data = json.loads(client_socket.recv(1024).decode('utf-8'))
            encrypted_message = message_data.get("message")
            if encrypted_message is not None:
                decrypted_message = decrypt_message(private_key, encrypted_message)
                print(f"\nMessage from {message_data['from']}: {decrypted_message}\nWrite your message: ", end='')
            else:
                print("\nReceived an invalid message.")
            sys.stdout.flush()
        except ConnectionResetError:
            break
        except json.JSONDecodeError:
            print("\nReceived an invalid JSON format.")
            break

def request_public_key(client, target_user):
    client.send(json.dumps({"action": "get_public_key", "target_user": target_user}).encode('utf-8'))
    response = json.loads(client.recv(1024).decode('utf-8'))
    if response["status"] == "success":
        return response["public_key"]
    else:
        print(f"Error: {response.get('message', 'Unknown error')}")
        return None

def start_client():
    generate_keys()
    private_key = load_private_key()
    public_key = private_key.public_key()

    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect(('localhost', 12345))

    action = input("Do you want to login or register? (login/register): ")
    user_id = input("Enter your ID: ")
    password = input("Enter your password: ")

    pem_public_key = public_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo
    ).decode()

    request = {"id": user_id, "password": password, "action": action, "public_key": pem_public_key}
    client.send(json.dumps(request).encode('utf-8'))

    response = json.loads(client.recv(1024).decode('utf-8'))
    if response["status"] in ["success", "registration_success"]:
        print(f"{action.capitalize()} successful!")
        if action == "login":
            target_user = input("Enter the ID of the user you want to message: ")
            target_public_key = request_public_key(client, target_user)

            if target_public_key:
                threading.Thread(target=receive_messages, args=(client, private_key), daemon=True).start()

                while True:
                    message = input("Write your message: ")
                    if message == "/exit":
                        break
                    encrypted_message = encrypt_message(target_public_key, message)
                    client.send(json.dumps({"action":"send_message", "target": target_user, "message": encrypted_message}).encode('utf-8'))
            else:
                print(f"Could not retrieve public key for {target_user}.")
    else:
        print(f"{action.capitalize()} failed: {response['status']}")

start_client()

Here's the error message:

Traceback (most recent call last):
  File "/opt/homebrew/Cellar/[email protected]/3.11.6_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/threading.py", line 1045, in _bootstrap_inner
    self.run()
  File "/opt/homebrew/Cellar/[email protected]/3.11.6_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/threading.py", line 982, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/zerocoke/Desktop/coding/python/E2EE-chat/u2/E2E_client.py", line 69, in receive_messages
    decrypted_message = decrypt_message(private_key, encrypted_message)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/zerocoke/Desktop/coding/python/E2EE-chat/u2/E2E_client.py", line 54, in decrypt_message
    base64.b64decode(encrypted_message),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/[email protected]/3.11.6_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/base64.py", line 88, in b64decode
    return binascii.a2b_base64(s, strict_mode=validate)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
binascii.Error: Incorrect padding

I'm not sure what is causing this issue. The error occurs during the decryption phase. It seems to be related to the base64 decoding process. Any insights or solutions to resolve this error would be greatly appreciated.

I tried changing 'validate' to false, but the result was the same. I can't figure out what the problem is.

Decrypting AES Encrypted Data with no IV

The AES Encrypted data I'm trying to decrypt is :

40b6b8e3d1f7b7128ecc16eae4702ff707e619c027744b8c55717e265516356dcbc3029ee1748978c8b13100f5c57352bb1e641a9104f037df0d65765d97e1997200d0fc41437c054bd6551b0b65ee0d53ac344f02ed6eaea3c4d24b0b667270c4c11593e4877c4dfd78ded0b8f35d6ceafec6d80ddec24f1653bf74d0b441f98e07529100845f4bff00bf96efa5307913a3fe5c87636ff1039a153a2ecb7ddf34500210292421715e4e063bf185afc22b21693260b638a4a395c1a87c3cc047e9acc5f59a1ca3144064cb6617f07bb6b357c4fe7c6ccbf9afee97efabf19397f7251702a6258a7aa42b704b238d27260930ec02f9451601360341018d4e2c34eb52cade8cb9b46738c369a6324f2e9603961bf81fb14a34f1db1e6f0b550024fd82eb0cfe556578f7b4e8d110b4bb2071f221d9bb024016afb1e7b09751ace8332a739570ef159b865da5a4a599052c7a31bcdbe7c728fc78fdec634baa68fec24bc26cd306bb32b42d9e78b69eed8ff011e86730436027ec3a60fca7bdc363192a10c46353ba45dc1bd476c2d004746a506e4539fac1b456a4aa36063ada89f682e3cb20076130d4c7041e2fa8bf1867f4c257f453332a39efc2a4463b8da5a1509e9016623d047226e2e6fb90b53b11c28e24938a41e0c88441b687e372de74939f10f16b4c892ab99f390b827efa70bed165619e8be33c29211c1f0bc8122e0addde18bff2afa2b54409c33f36bb480552bb5d9d293eb1cc10b8cd1029fc08464b31c7ffe85a3bd0334782b2561e21d8df4208ea0390ab5d3ea5913bbdd822ca1d9e3d291e8953c3e7742d414616e3e49058a6fb984059f14346de6d13a138b710ad03c9a85f353142e1b9f731ea8f0b7df601d949339a7b917362177e03f89610f757c1564b6a8a4450ccbc8f0e7a1f1b33e6c5817724e2a8e0187e00a8b28cc0ad9a789ae38bba0104919806813cfbbdba5afe880fc074e7f57e9518c9a5293dee4dc69c402a652a660eb40f2c19ea5cdfc947a78205fc792423c40e20565c98f8b0e86a5c4928c018ffa269d99398a92d8259d4a29f98841caa1f7f38afd7973c98572411b7136b4b46c0071814e951c712acebff3dc65dd3d51be7714c6e2b687cf1d5d3bd6af32e53b90ebd7c5d189fd7e08790b20f1c9483ea296b4997c90396736c8d3f4f49f39e948bc083b1a17977a6996d53f0b2ea5b8afa591b13487903762d8ea90f334d0e3c6ae6c9fe6be1a0e820ff9185fc10d469c7945d2f67f24e87fe0efa81e3eab7e35df5a17f4fd29a1a0803d77f0d381f8ef169c75a59133ab9b527bff464d999c5cf2ee3e26588c19577ff8b118e507886c575d7bf34a8d55f79772a2aa64987ebc43dfa3b6790d20fa54a4c2344c9647d987f9da268573a1f7ecad3df5013eff514d3142a63b6636cfeb0f3731a2770c053f77fa839bff6cdc4a8d1da5ccc6457f23c6d1db958086b029170c54c4f2d8658589dad998860f8bcaa06a59345f754943fb78384253c077e91959ef6c7f0e1862ea4e67dad3fd5de4ccf99c215837619c9173ee9645c59100fc718ee8b95782af73d1f952898cedb653c9090f5941f5f440968a0dcf26fa3a5b73715f7f379b7d793a22559bb00107b5f346175f4aaf27e2eac1a6a35b21ab246fb68b1d48eb949aa71932cab58eaaffcd29965d9dd6e068f13d23cbde334ccb0aa0a0724a7dba6162b4487066605ae3148575cdc13523f06713aa2642e121ccea6c28c750428bc170e7486b6c255f50064dac1080d591b26289138705837188abb240a2c34e1a4293dd8f294c31d763d83ec0833cea4633e23a863cd3a700af99e1dd7781d8cb2088857ab9620af005aa267e75422e65a55a377b9af96008adab10ae73c7c1020e2d2d4406e54eb2f4270013537138c19c3b6795f8785eb66ef3b0dcdce56ed17a1022d0362a6c9e9be6c3b23667a51ae1fa8b8988602f56860cb90b00f38b82f3c1e1d101449c430ff77d9e38f30ed2704e8620419b28ced8d7933f0447c0e4e86a0678072c7dc3bf43adabd18bc5226bd7e1ec55bf1b779f227e54517252d919eee1ec6494fe3088235f8ac46b77888b6ebbf633da74371f0b9e014df6d4d993da3df5cf278205a43e468f48dca0faf1cc864ef8024aece48f36ded739b56deefd3380e2c851020f2ad80b6cef180fb2a24bbdf070e4d170c1a7a0eb4fdab1309cb2a4d3952ec58efc0c23696aa173de2ae878cd9fc1d6907f5542acea57786207c43859aecf1ca5715d78b3d92198434d83694960c1c4d7d8a23ca01af35fd6a5c98c38c0367b40cbb17559cc753d636ba94fe8ba6fc2635d27767dcef5f9b667cd94f843ec022e8195e9234e0c43801480d6f1be263572a5444cef4ac4c9f80a41e76c0012727e195776fa4b56834f447a11ff05f4092beb6ad234054b7164299b2e1e670407a280812794f2d1fbf7ad6342225f5be2537e13f5902b54d5bdaf19fa4ff535d44e03a9be57d91135119de28966320f449e97cc6fb807a6ed5d9f4bcc22d546af71d253b3cf00d4dd56393d68b25aff86c0893502c200257f3418a7e1247629a3a9464b415ffd1d7d6862b4f00fcb2669e943b9e157862bf71f2d5156a40bc91e26dbe6482090a03a324220c79c1f9c3b7c7f932c6d6407cb8fce7b5a67221a2c93aedf78d7eb69ba88862e31e92b2d5c7e8eee17bffd108bc46b94997590d94248d5440648baefebc37564facaa01047ebeeab15f90eff18111e8fc890231d3ba3d1214b0b797f9cf688f06a2b9e006de65846a01fd4bbaa290091d0b41b11179f31063a947a1778ed0f80931d66281e42a43f8a57ce31983c71d11e1c8cffd9a55c6987b3ca1c2cafafa0d3e0d21668477de5d4bac263c2d3828c5c55888033efedceb68885cc3e87a2a437875e8852d1445b660abe43555465713b57f694fe412183a0a809ad57e1805a11cc68a7f07b77c2e58581de2eb97741a3e34682437584f129894abd914effcb01d694e71046e3efa453386f08a283743adcfdcbf07ebb96e5a43c3c930f20ae977e0493ed28016085f99d9c6e9164dc4ba1cba17a7cdf121c885fa8cea686a7c4160df73185fb9067079fcd865a40c39c43c690e1b2c39a51aa18fc4ef4b269edc01fc1654b96e065de53fccf9ca933aa3134bb627511068e1caf24454a47ed92dd56122ce25786e8a38f31a42d766c6bd241410e36172b4722c84065c1bf3261aa587d1d5374f4bf6a96791cddc74ab97f32533ea487710dabcd17ce6160380eef91918e70dac3268301461013a255e8aa593d005db3b893db20c5cca8feb5af813f07ec603dd02f3414ed2a4

The key is :

02f3ffa287f78ba68c60f24f79c6fb18ce32b4ebaadac11af5ace8c67a50ae9f

There is no IV provided, a friend advised me to assume the first "block" from the encrypted data is the IV.

I wrote this code to decrypt it in Python:

from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import binascii

def decrypt_aes(data, key, iv):
    cipher = AES.new(binascii.unhexlify(key), AES.MODE_CBC, binascii.unhexlify(iv))
    decrypted_data = unpad(cipher.decrypt(binascii.unhexlify(data)), AES.block_size)
    return decrypted_data.decode('utf-8')

# Input data, key, and IV
encrypted_data = '40b6b8e3d1f7b7128ecc16eae4702ff707e619c027744b8c55717e265516356dcbc3029ee1748978c8b13100f5c57352bb1e641a9104f037df0d65765d97e1997200d0fc41437c054bd6551b0b65ee0d53ac344f02ed6eaea3c4d24b0b667270c4c11593e4877c4dfd78ded0b8f35d6ceafec6d80ddec24f1653bf74d0b441f98e07529100845f4bff00bf96efa5307913a3fe5c87636ff1039a153a2ecb7ddf34500210292421715e4e063bf185afc22b21693260b638a4a395c1a87c3cc047e9acc5f59a1ca3144064cb6617f07bb6b357c4fe7c6ccbf9afee97efabf19397f7251702a6258a7aa42b704b238d27260930ec02f9451601360341018d4e2c34eb52cade8cb9b46738c369a6324f2e9603961bf81fb14a34f1db1e6f0b550024fd82eb0cfe556578f7b4e8d110b4bb2071f221d9bb024016afb1e7b09751ace8332a739570ef159b865da5a4a599052c7a31bcdbe7c728fc78fdec634baa68fec24bc26cd306bb32b42d9e78b69eed8ff011e86730436027ec3a60fca7bdc363192a10c46353ba45dc1bd476c2d004746a506e4539fac1b456a4aa36063ada89f682e3cb20076130d4c7041e2fa8bf1867f4c257f453332a39efc2a4463b8da5a1509e9016623d047226e2e6fb90b53b11c28e24938a41e0c88441b687e372de74939f10f16b4c892ab99f390b827efa70bed165619e8be33c29211c1f0bc8122e0addde18bff2afa2b54409c33f36bb480552bb5d9d293eb1cc10b8cd1029fc08464b31c7ffe85a3bd0334782b2561e21d8df4208ea0390ab5d3ea5913bbdd822ca1d9e3d291e8953c3e7742d414616e3e49058a6fb984059f14346de6d13a138b710ad03c9a85f353142e1b9f731ea8f0b7df601d949339a7b917362177e03f89610f757c1564b6a8a4450ccbc8f0e7a1f1b33e6c5817724e2a8e0187e00a8b28cc0ad9a789ae38bba0104919806813cfbbdba5afe880fc074e7f57e9518c9a5293dee4dc69c402a652a660eb40f2c19ea5cdfc947a78205fc792423c40e20565c98f8b0e86a5c4928c018ffa269d99398a92d8259d4a29f98841caa1f7f38afd7973c98572411b7136b4b46c0071814e951c712acebff3dc65dd3d51be7714c6e2b687cf1d5d3bd6af32e53b90ebd7c5d189fd7e08790b20f1c9483ea296b4997c90396736c8d3f4f49f39e948bc083b1a17977a6996d53f0b2ea5b8afa591b13487903762d8ea90f334d0e3c6ae6c9fe6be1a0e820ff9185fc10d469c7945d2f67f24e87fe0efa81e3eab7e35df5a17f4fd29a1a0803d77f0d381f8ef169c75a59133ab9b527bff464d999c5cf2ee3e26588c19577ff8b118e507886c575d7bf34a8d55f79772a2aa64987ebc43dfa3b6790d20fa54a4c2344c9647d987f9da268573a1f7ecad3df5013eff514d3142a63b6636cfeb0f3731a2770c053f77fa839bff6cdc4a8d1da5ccc6457f23c6d1db958086b029170c54c4f2d8658589dad998860f8bcaa06a59345f754943fb78384253c077e91959ef6c7f0e1862ea4e67dad3fd5de4ccf99c215837619c9173ee9645c59100fc718ee8b95782af73d1f952898cedb653c9090f5941f5f440968a0dcf26fa3a5b73715f7f379b7d793a22559bb00107b5f346175f4aaf27e2eac1a6a35b21ab246fb68b1d48eb949aa71932cab58eaaffcd29965d9dd6e068f13d23cbde334ccb0aa0a0724a7dba6162b4487066605ae3148575cdc13523f06713aa2642e121ccea6c28c750428bc170e7486b6c255f50064dac1080d591b26289138705837188abb240a2c34e1a4293dd8f294c31d763d83ec0833cea4633e23a863cd3a700af99e1dd7781d8cb2088857ab9620af005aa267e75422e65a55a377b9af96008adab10ae73c7c1020e2d2d4406e54eb2f4270013537138c19c3b6795f8785eb66ef3b0dcdce56ed17a1022d0362a6c9e9be6c3b23667a51ae1fa8b8988602f56860cb90b00f38b82f3c1e1d101449c430ff77d9e38f30ed2704e8620419b28ced8d7933f0447c0e4e86a0678072c7dc3bf43adabd18bc5226bd7e1ec55bf1b779f227e54517252d919eee1ec6494fe3088235f8ac46b77888b6ebbf633da74371f0b9e014df6d4d993da3df5cf278205a43e468f48dca0faf1cc864ef8024aece48f36ded739b56deefd3380e2c851020f2ad80b6cef180fb2a24bbdf070e4d170c1a7a0eb4fdab1309cb2a4d3952ec58efc0c23696aa173de2ae878cd9fc1d6907f5542acea57786207c43859aecf1ca5715d78b3d92198434d83694960c1c4d7d8a23ca01af35fd6a5c98c38c0367b40cbb17559cc753d636ba94fe8ba6fc2635d27767dcef5f9b667cd94f843ec022e8195e9234e0c43801480d6f1be263572a5444cef4ac4c9f80a41e76c0012727e195776fa4b56834f447a11ff05f4092beb6ad234054b7164299b2e1e670407a280812794f2d1fbf7ad6342225f5be2537e13f5902b54d5bdaf19fa4ff535d44e03a9be57d91135119de28966320f449e97cc6fb807a6ed5d9f4bcc22d546af71d253b3cf00d4dd56393d68b25aff86c0893502c200257f3418a7e1247629a3a9464b415ffd1d7d6862b4f00fcb2669e943b9e157862bf71f2d5156a40bc91e26dbe6482090a03a324220c79c1f9c3b7c7f932c6d6407cb8fce7b5a67221a2c93aedf78d7eb69ba88862e31e92b2d5c7e8eee17bffd108bc46b94997590d94248d5440648baefebc37564facaa01047ebeeab15f90eff18111e8fc890231d3ba3d1214b0b797f9cf688f06a2b9e006de65846a01fd4bbaa290091d0b41b11179f31063a947a1778ed0f80931d66281e42a43f8a57ce31983c71d11e1c8cffd9a55c6987b3ca1c2cafafa0d3e0d21668477de5d4bac263c2d3828c5c55888033efedceb68885cc3e87a2a437875e8852d1445b660abe43555465713b57f694fe412183a0a809ad57e1805a11cc68a7f07b77c2e58581de2eb97741a3e34682437584f129894abd914effcb01d694e71046e3efa453386f08a283743adcfdcbf07ebb96e5a43c3c930f20ae977e0493ed28016085f99d9c6e9164dc4ba1cba17a7cdf121c885fa8cea686a7c4160df73185fb9067079fcd865a40c39c43c690e1b2c39a51aa18fc4ef4b269edc01fc1654b96e065de53fccf9ca933aa3134bb627511068e1caf24454a47ed92dd56122ce25786e8a38f31a42d766c6bd241410e36172b4722c84065c1bf3261aa587d1d5374f4bf6a96791cddc74ab97f32533ea487710dabcd17ce6160380eef91918e70dac3268301461013a255e8aa593d005db3b893db20c5cca8feb5af813f07ec603dd02f3414ed2a4'
encryption_key = '02f3ffa287f78ba68c60f24f79c6fb18ce32b4ebaadac11af5ace8c67a50ae9f'
iv = '40b6b8e3d1f7b712'

# Decrypt the data
decrypted_data = decrypt_aes(encrypted_data, encryption_key, iv)

# Print the result
print("Decrypted Data:", decrypted_data)

Throws this error:

ValueError: Incorrect IV length (it must be 16 bytes long)

I'm making several assumptions here:

  • The decrypted data is assumed to be in UTF-8 encoding
  • binascii.unhexlify(data), I jusf learned about AES encryption laat night and I'm using this line as the "normal" thing to do. Does it apply to my case?
  • I'm not sure if the data or key is Hex or Base64. The key is 64 characters so I assume it's Hex.

Here's the file whose contents I'm trying to decrypt for reference: https://drive.google.com/file/d/1o79Bi9l4F_Dohef6Di3q_IKmzvKIx_2p/view?usp=sharing I'm trying to mod a game for personal use (activate mouse control, remove menu/dialogue restriction).

how to encrypt a text present in a string in unix using gpg

I have to encrypt a content inside a string buffer.

Currently Im encrypting the file. I write string buffer into a file and then encrypt using following command.

gpg --recipient "raj" --output "C:\a.txt.gpg" --yes --encrypt "C:\a.txt"

But due to security reason, we dont need to write into a file and the content should be passed directly to the gpg command.

Please help.

How do I encrypt plaintext with GnuPG?

I've been working a great deal with GnuPG lately and have come to depend on its ability to encrypt files, etc.

However, I am currently working on a couple of projects that involve communication (i.e. chat,email, etc) where I'd like to use existing keys to encrypt/decrypt text itself as opposed to a "container" such as a file or disk image.

I suppose I could encrypt the container, convert the stream to base64 (or something appropriate) then mark the text as such, but I would guess there is a more straightforward solution. I'm sure there is something simple I'm missing, but, well, I'm missing it.

Any ideas?

Decrypting NTAG424 encrypted data fails sporadically with WebCrypto

This is a follow-up question to a previous one, trying to get a working decryption of NDEF URLs from an NXP NTAG424 tag according to this documentation from NXP (4.4.2.1).

I've put together an initial WebCrypto code based on @Topaco 's excellent suggestions and the code now succesfuly decodes the picc and enc from the response and verifies the CMAC.

However, this only works for some payloads, while others still throw a bad decrypt error. Iv'e isolated the issue to the decryption of the enc static data payload using the derived keys from sv1, search for encDataFull in the reference code.

The complete implementation follows a reference in Python which is also the backend for the online validation service I refer to later on: https://github.com/nfc-developer/sdm-backend/blob/master/libsdm/sdm.py

The only difference is the use of AES-CBC vs. AES-ECBin encoding the encIVFull, since AES-ECB is not supported by WebCrypto.

Following this post, I understood that an AES-CBC with an IV of 0s would be equal to AES-ECB since only the first block in needed: const encIV = Buffer.from(encIVFull).subarray(0, 16)

Reference for ECB / CBC being the same for IV of zeros: CBC Example ECB Example

The updated decoding code:

async function decipherTag() {
    const keyBuffer = Uint8Array.from(Buffer.from(KEY, 'hex'))
    const piccBuffer = Uint8Array.from(Buffer.from(PICC, 'hex'))
    const encBuffer = Uint8Array.from(Buffer.from(ENC, 'hex'))
    const cmacArgBuffer = Buffer.from(`${ENC}&${CMAC_ARG}=`)

    /*
        Step 1 - decrypt PICC data (UID + tap counter)
    */

    // Import crypto key from key buffer
    const cryptoKey = await crypto.subtle.importKey(
        'raw',
        keyBuffer,
        {
            name: 'AES-CBC',
            length: 128,
        },
        true,
        ['encrypt', 'decrypt']
    )

    // Encrypt padding block to generate padding block
    const piccPaddingBlock = await crypto.subtle.encrypt({ name: 'AES-CBC', iv: piccBuffer }, cryptoKey, new Uint8Array())

    // create cipher buffer with padding block
    const piccPadded = concat(piccBuffer, new Uint8Array(piccPaddingBlock))

    // Decrypt
    const deciphered = await crypto.subtle.decrypt(
        {
            name: 'AES-CBC',
            iv: IV,
        },
        cryptoKey,
        piccPadded
    )

    // extract PICC data from deciphered buffer
    const picc = Buffer.from(deciphered)
    const tag = picc.slice(0, 1)
    const uid = picc.subarray(1, 8)
    const cnt = picc.subarray(8, 11)

    // subbuffer from 1 to 11 for later calculcations (drop tag data)
    const piccData = picc.subarray(1, 11)

    /*
        Step 2 - decrypt static data
    */

    const sv1Data = Buffer.alloc(16)
    SV1.copy(sv1Data, 0)
    piccData.copy(sv1Data, 6)

    const keyAesCmac = new AesCmac(keyBuffer)
    const dataKeyRaw = await keyAesCmac.calculate(sv1Data)
    const dataIV = Buffer.alloc(16)
    cnt.copy(dataIV, 0)

    const dataKey = await crypto.subtle.importKey(
        'raw',
        dataKeyRaw,
        {
            name: 'AES-CBC',
            length: 128,
        },
        true,
        ['encrypt', 'decrypt']
    )

    const encIVFull = await crypto.subtle.encrypt({ name: 'AES-CBC', iv: IV }, dataKey, dataIV)
    const encIV = Buffer.from(encIVFull).subarray(0, 16)
    const encPaddingBlock = await crypto.subtle.encrypt({ name: 'AES-CBC', iv: encIV }, dataKey, new Uint8Array())
    const encPadded = concat(encBuffer, new Uint8Array(encPaddingBlock))

    const encDataFull = await crypto.subtle.decrypt(
        {
            name: 'AES-CBC',
            iv: encIV,
        },
        dataKey,
        encPadded
    )

    const encData = Buffer.from(encDataFull).subarray(0, 16)

    /*
        Step 3 - validate CMAC
    */

    // construct SV2 buffer with PICC data
    const sv2Data = Buffer.alloc(16)
    SV2.copy(sv2Data, 0)
    piccData.copy(sv2Data, 6)

    // calculate SV2 CMAC
    // const keyAesCmac = new AesCmac(keyBuffer)
    const sv2 = await keyAesCmac.calculate(sv2Data)

    // calculate full CMAC of SV2 and encrypted data
    const sv2AesCmac = new AesCmac(sv2)
    const fullCmac = await sv2AesCmac.calculate(cmacArgBuffer)
    const fullCmacBuffer = Buffer.from(fullCmac)

    const cmac = Buffer.alloc(8)
    for (let i = 0; i < 8; i++) fullCmacBuffer.copy(cmac, i, i * 2 + 1, i * 2 + 2)

    return {
        dataTag: tag.toString('hex'),
        uid: uid.toString('hex').toUpperCase(),
        cnt: cnt.toString('hex'),
        cntInt: picc.readUIntLE(8, 3),
        cmacPass: Buffer.from(cmac).toString('hex').toUpperCase() === CMAC,
        data: encData.toString('hex'),
    }
}

With this function, some payloads work and some fail. This is despite the fact that they all pass verification on an online utility (provided as well)

Working payload (link to online validation):

// https://sdm.nfcdeveloper.com/tagtt?_____TRIAL_VERSION______NOT_FOR_PRODUCTION_____&picc_data=FDE4AFA99B5C820A2C1BB0F1C792D0EB&enc=94592FDE69FA06E8E3B6CA686A22842B&cmac=C48B89C17A233B2C
const KEY = '00000000000000000000000000000000'
const PICC = 'FDE4AFA99B5C820A2C1BB0F1C792D0EB'
const ENC = '94592FDE69FA06E8E3B6CA686A22842B'
const CMAC = 'C48B89C17A233B2C'
const CMAC_ARG = 'cmac'

returns

{"dataTag":"c7","uid":"04958CAA5C5E80","cnt":"010000","cntInt":1,"cmacPass":true,"data":"78787878787878787878787878787878"}

Failing payload (link to online validation):

// https://sdm.nfcdeveloper.com/tagtt?_____TRIAL_VERSION______NOT_FOR_PRODUCTION_____&picc_data=6107DD7607B179270EAFFCA2F0911940&enc=37C1E399E0948BEA54138F92DDD1E743&cmac=0406016621FC6AC6
const KEY = '00000000000000000000000000000000'
const PICC = '6107DD7607B179270EAFFCA2F0911940'
const ENC = '37C1E399E0948BEA54138F92DDD1E743'
const CMAC = '0406016621FC6AC6'
const CMAC_ARG = 'cmac'

Fails with bad decrypt

Another failing payload (link to online validation):

// https://sdm.nfcdeveloper.com/tagtt?_____TRIAL_VERSION______NOT_FOR_PRODUCTION_____&picc_data=FD91EC264309878BE6345CBE53BADF40&enc=CEE9A53E3E463EF1F459635736738962&cmac=ECC1E7F6C6C73BF6
const KEY = '00000000000000000000000000000000'
const PICC = 'FD91EC264309878BE6345CBE53BADF40'
const ENC = 'CEE9A53E3E463EF1F459635736738962'
const CMAC = 'ECC1E7F6C6C73BF6'
const CMAC_ARG = 'cmac'

Would appreciate any further insight on how to make the decryption code more robust.

Understanding and reversing encryption algorithm

I'm struggling with reversing (or understanding it at the very least) the following algorithm on Python (code is a bit long because of lookup tables):

crypto_byte_map_2 = [0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46]
crypto_byte_map_3 = [0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3]
crypto_byte_map_4 = [0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97]
crypto_byte_map_5 = [0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d]

def decrypt_block(block):
    intermediate_result = [0] * 4

    (firstByte, secondByte, thirdByte, fourthByte) = block[:4]

    intermediate_result[0x0] = (
            crypto_byte_map_2[fourthByte] ^ crypto_byte_map_3[secondByte] ^
            crypto_byte_map_5[firstByte] ^ crypto_byte_map_4[thirdByte])
    intermediate_result[0x1] = (
            crypto_byte_map_5[secondByte] ^ crypto_byte_map_2[firstByte] ^
            crypto_byte_map_3[thirdByte] ^ crypto_byte_map_4[fourthByte])
    intermediate_result[0x2] = (
            crypto_byte_map_2[secondByte] ^ crypto_byte_map_4[firstByte] ^
            crypto_byte_map_5[thirdByte] ^ crypto_byte_map_3[fourthByte])
    intermediate_result[0x3] = (
            crypto_byte_map_4[secondByte] ^ crypto_byte_map_3[firstByte] ^
            crypto_byte_map_2[thirdByte] ^ crypto_byte_map_5[fourthByte])

    return intermediate_result

This code is from crackme i've been solving. I reproduced the code from assembly, but I'm honestly zero in cryptography, so I feel lost here. I would appreciate any guidance.

So far I could come up only with following:

encrypted[0] ^ encrypted[1] ^ encrypted[2] ^ encrypted[3] == decrypted[0] ^ decrypted[1] ^ decrypted[2] ^ decrypted[3]

crypto_byte_map_2[i] ^ crypto_byte_map_3[i] ^ crypto_byte_map_4[i] ^ crypto_byte_map_5[i] == i

PDFBox extracting blanks from PDF encrypted with no password

I'm using PDFBox to extract text from forms and I have a PDF that is not encrypted with a password but PDFBox says is encrypted. I suspect some sort of Adobe "feature" since when I open it it says (SECURED), while other PDFs that I don't have issues with do not. isEncrypted() returns true so despite not having a password it appears to be secured somehow.

I suspect that it is not decrypting properly, as it is able to pull the form's text prompts but not the responses themselves. In the code below it pulls Address (Street Name and Number) and City from the sample PDF, but not the response in between them.

I am using PDFBox 2.0, but I have also tried 1.8.

I've tried every method of decrypting that I can find for PDFBox, including the deprecated ones (why not). I get the same result as not trying to decrypt at all, just the Address and City prompts.

With PDF's being the absolute nightmare that they are, this PDF was likely created in some non-standard way. Any help in identifying this and getting moving again is appreciated.

Sample PDF

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPageTree;
import org.apache.pdfbox.pdmodel.encryption.StandardDecryptionMaterial;
import org.apache.pdfbox.text.PDFTextStripperByArea;
import java.io.File;
import org.apache.pdfbox.pdmodel.PDPage;
import java.awt.Rectangle;
import java.util.List;


class Scratch {

    private static float pwidth;
    private static float pheight;

    private static int widthByPercent(double percent) {
        return (int)Math.round(percent * pwidth);
    }

    private static int heightByPercent(double percent) {
        return (int)Math.round(percent * pheight);
    }

    public static void main(String[] args) {
        try {
            //Create objects
            File inputStream = new File("ocr/TestDataFiles/i-9_08-07-09.pdf");

            PDDocument document = PDDocument.load(inputStream);

            // Try every decryption method I've found
            if(document.isEncrypted()) {

                // Method 1
                document.decrypt("");

                // Method 2
                document.openProtection(new StandardDecryptionMaterial(""));

                // Method 3
                document.setAllSecurityToBeRemoved(true);

                System.out.println("Removed encryption");
            }

            PDFTextStripperByArea stripper = new PDFTextStripperByArea();

            //Get the page with data on it
            PDPageTree allPages = document.getDocumentCatalog().getPages();
            PDPage page = allPages.get(3);

            pheight = page.getMediaBox().getHeight();
            pwidth = page.getMediaBox().getWidth();

            Rectangle LastName = new Rectangle(widthByPercent(0.02), heightByPercent(0.195), widthByPercent(0.27), heightByPercent(0.1));
            stripper.addRegion("LastName", LastName);
            stripper.setSortByPosition(true);
            stripper.extractRegions(page);
            List<String> regions = stripper.getRegions();

            System.out.println(stripper.getTextForRegion("LastName"));

        } catch (Exception e){
            System.out.println(e.getMessage());
        }
    }
}
โŒ
โŒ