You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python/JS开发者求助:GOST 28147-89算法加解密使用问题

GOST 28147-89 Encryption/Decryption for Large Texts (Python & JavaScript)

Hey there! Let's work through your GOST 28147-89 implementation issues for both Python and JavaScript, including handling large texts like lorem1000.


Python (Using pygost)

First, let's fix up your pygost setup. You've already imported parts of gost28147, but we need to add key decoding, block handling, padding, and actual encryption/decryption logic. Your provided key is Base64-encoded, so we'll start by decoding that.

Step-by-Step Implementation

  1. Decode the Base64 Key: Convert your key string into raw bytes.
  2. Use a Secure Mode: We'll use CBC mode (safer than ECB) with an initialization vector (IV).
  3. Handle Padding: GOST 28147 uses 64-bit (8-byte) blocks, so we need to pad text that doesn't fit perfectly into blocks.
  4. Encrypt/Decrypt Large Text: Split the text into blocks, process each, and combine results.

Full Code Example

import base64
from pygost.gost28147 import encrypt, decrypt, DEFAULT_SBOX, BLOCKSIZE

# Decode your Base64 key
key = base64.b64decode("afdfGRerehrehtwICJAAGByqFAwICHgEDQwAEQHuYflp31mEqb1YLSTOlzWJCUWDsDmNVZ9Lor7bkJfbrSnsFg7gcHGNuGoIhfds+Shgfhrtgergerfewwer7W2Wd3P+sPnrmtw=")

# PKCS#7 padding function (required for block alignment)
def pad(data):
    padding_len = BLOCKSIZE - len(data) % BLOCKSIZE
    return data + bytes([padding_len]) * padding_len

# PKCS#7 unpadding function
def unpad(data):
    padding_len = data[-1]
    return data[:-padding_len]

# Encrypt function (CBC mode)
def gost_encrypt(plaintext, key, iv):
    plaintext_bytes = plaintext.encode("utf-8")
    padded_data = pad(plaintext_bytes)
    ciphertext = b""
    prev_block = iv
    for i in range(0, len(padded_data), BLOCKSIZE):
        block = padded_data[i:i+BLOCKSIZE]
        # XOR block with previous ciphertext block (IV for first block)
        xor_block = bytes([a ^ b for a, b in zip(block, prev_block)])
        encrypted_block = encrypt(key, xor_block, sbox=DEFAULT_SBOX)
        ciphertext += encrypted_block
        prev_block = encrypted_block
    return base64.b64encode(ciphertext).decode("utf-8")

# Decrypt function (CBC mode)
def gost_decrypt(ciphertext_b64, key, iv):
    ciphertext = base64.b64decode(ciphertext_b64)
    plaintext = b""
    prev_block = iv
    for i in range(0, len(ciphertext), BLOCKSIZE):
        block = ciphertext[i:i+BLOCKSIZE]
        decrypted_block = decrypt(key, block, sbox=DEFAULT_SBOX)
        # XOR with previous block to get plaintext block
        plaintext_block = bytes([a ^ b for a, b in zip(decrypted_block, prev_block)])
        plaintext += plaintext_block
        prev_block = block
    return unpad(plaintext).decode("utf-8")

# Example usage with lorem1000
iv = b"abcdefgh"  # 8-byte IV (generate a random one for production!)
large_text = "Lorem ipsum dolor sit amet..."  # Replace with your lorem1000 text

# Encrypt
encrypted = gost_encrypt(large_text, key, iv)
print("Encrypted text:", encrypted)

# Decrypt
decrypted = gost_decrypt(encrypted, key, iv)
print("Decrypted text:", decrypted)

Notes:

  • IV: Always generate a cryptographically random IV for production use (never reuse an IV with the same key).
  • Mode: If you need ECB mode (not recommended for large texts), you can skip the XOR step with the previous block.

JavaScript (Using GostCipher)

Your error Uncaught Error: Invalid block length happens because the GostCipher constructor requires a valid S-box parameter. GOST 28147 uses standard S-boxes—we'll use the default one matching pygost's DEFAULT_SBOX.

Step-by-Step Implementation

  1. Define the Standard S-box: Use the default GOST 28147 S-box values.
  2. Correctly Instantiate GostCipher: Pass the S-box as a parameter.
  3. Decode the Base64 Key: Convert your key string into a Uint8Array.
  4. Handle Padding: Add/remove padding to align text with 8-byte blocks.
  5. Process Large Text: Split into blocks and encrypt/decrypt.

Full Code Example

// Standard GOST 28147-89 S-box (matches pygost's DEFAULT_SBOX)
const DEFAULT_SBOX = [
    [4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3],
    [14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9],
    [5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11],
    [7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3],
    [6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2],
    [4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14],
    [13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12],
    [1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12]
];

// PKCS#7 padding function
function pad(data) {
    const blockSize = 8;
    const paddingLen = blockSize - (data.length % blockSize);
    const padding = new Uint8Array(paddingLen).fill(paddingLen);
    return new Uint8Array([...data, ...padding]);
}

// PKCS#7 unpadding function
function unpad(data) {
    const paddingLen = data[data.length - 1];
    return data.slice(0, data.length - paddingLen);
}

// Base64 decode to Uint8Array
function base64Decode(str) {
    const binStr = atob(str);
    const arr = new Uint8Array(binStr.length);
    for (let i = 0; i < binStr.length; i++) {
        arr[i] = binStr.charCodeAt(i);
    }
    return arr;
}

// Base64 encode from Uint8Array
function base64Encode(arr) {
    const binStr = String.fromCharCode(...arr);
    return btoa(binStr);
}

// Example usage
const keyBase64 = "afdfGRerehrehtwICJAAGByqFAwICHgEDQwAEQHuYflp31mEqb1YLSTOlzWJCUWDsDmNVZ9Lor7bkJfbrSnsFg7gcHGNuGoIhfds+Shgfhrtgergerfewwer7W2Wd3P+sPnrmtw=";
const key = base64Decode(keyBase64);
const iv = new Uint8Array([97, 98, 99, 100, 101, 102, 103, 104]); // "abcdefgh" as bytes
const largeText = "Lorem ipsum dolor sit amet..."; // Replace with your lorem1000 text

// Initialize GostCipher with correct parameters
const gostCipher = new GostCipher('GOST 28147', 1989, 64, 'ES', DEFAULT_SBOX);

// Encrypt
const plaintextBytes = new TextEncoder().encode(largeText);
const paddedPlaintext = pad(plaintextBytes);
const ciphertextBytes = gostCipher.encrypt(paddedPlaintext, key, iv);
const encryptedBase64 = base64Encode(ciphertextBytes);
console.log("Encrypted text:", encryptedBase64);

// Decrypt
const ciphertextDecoded = base64Decode(encryptedBase64);
const decryptedPaddedBytes = gostCipher.decrypt(ciphertextDecoded, key, iv);
const decryptedBytes = unpad(decryptedPaddedBytes);
const decryptedText = new TextDecoder().decode(decryptedBytes);
console.log("Decrypted text:", decryptedText);

Notes:

  • S-box: Make sure you're using the correct S-box for your use case (some implementations use regional variants, but the one above is the standard default).
  • IV: Just like in Python, use a random IV for production and share it with the decryptor (it doesn't need to be secret).

内容的提问来源于stack exchange,提问作者Nikolay Gogol

火山引擎 最新活动