Симметричное шифрование (AES) в Apache ThriftPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Симметричное шифрование (AES) в Apache Thrift

Сообщение Anonymous »

У меня есть два приложения, которые взаимодействуют с использованием Thrift. Они разделяют тот же секретный ключ, и мне нужно зашифровать их сообщения. Имеет смысл использовать симметричный алгоритм (например, AES), но я не нашел никакой библиотеки для этого. Поэтому я провел исследование и посмотрел следующие параметры: < /p>

Используйте встроенную поддержку SSL < /h2>

Я могу использовать встроенную поддержку SSL, установить безопасное соединение и использовать свой секретный ключ как токен аутентификации. Требуется установить сертификаты в дополнение к секретному ключу, которая у них уже есть, но мне не нужно что -либо реализовать, кроме проверки этого секретного ключа, полученного от клиента, такой же, как и секретный ключ, хранящийся локально. Tsocket и переопределить write () и read () Методы и данные en-/decrypt в них. Будет увеличить трафик на маленьких записях. Например, если TbinaryProtocol записывает 4-биты Integer, потребуется один блок (16 байтов) в зашифрованном состоянии.
[*] расширить tsocket и wroup inputStream и outputStream с помощью cipherinputStream и cipheroutput . CipheroutputStream не будет сразу шифровать небольшие байтовые массивы, обновляя шифр с ними. После того, как у нас будет достаточно данных, они будут зашифрованы и записаны в базовый выход outputstream . Так что он будет ждать, пока вы не добавите 4 4-байтовых INT и тогда шифруете их. Это позволяет нам не тратить трафик, но также является причиной проблемы - если последнее значение не заполнит блок, оно никогда не будет зашифровано и записано в базовый поток. Он ожидает, что я напишу количество байтов, делившихся по размеру блока (16 байтов), но я не могу сделать это, используя tbinaryprotocol .
повторный применение tbinaryprotocol , кэширование всех записей вместо того, чтобы писать их в потоку и шифрование в WriteMessAgeend () . Реализовать расшифровку в readmessagebegin () . Я думаю, что шифрование должно быть выполнено на транспортном уровне, а не в протоколе. /> tencryptedframedtransport.java

package tutorial;

import org.apache.thrift.TByteArrayOutputStream;
import org.apache.thrift.transport.TMemoryInputTransport;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import org.apache.thrift.transport.TTransportFactory;

import javax.crypto.Cipher;
import java.security.Key;
/**
* TEncryptedFramedTransport is a buffered TTransport. It encrypts fully read message
* with the "AES/ECB/PKCS5Padding" symmetric algorithm and send it, preceeding with a 4-byte frame size.
*/
public class TEncryptedFramedTransport extends TTransport {
public static final String ALGORITHM = "AES/ECB/PKCS5Padding";

private Cipher encryptingCipher;
private Cipher decryptingCipher;

protected static final int DEFAULT_MAX_LENGTH = 0x7FFFFFFF;

private int maxLength_;

private TTransport transport_ = null;

private final TByteArrayOutputStream writeBuffer_ = new TByteArrayOutputStream(1024);
private TMemoryInputTransport readBuffer_ = new TMemoryInputTransport(new byte[0]);

public static class Factory extends TTransportFactory {
private int maxLength_;
private Key secretKey_;

public Factory(Key secretKey) {
this(secretKey, DEFAULT_MAX_LENGTH);
}

public Factory(Key secretKey, int maxLength) {
maxLength_ = maxLength;
secretKey_ = secretKey;
}

@Override
public TTransport getTransport(TTransport base) {
return new TEncryptedFramedTransport(base, secretKey_, maxLength_);
}
}

/**
* Constructor wraps around another tranpsort
*/
public TEncryptedFramedTransport(TTransport transport, Key secretKey, int maxLength) {
transport_ = transport;
maxLength_ = maxLength;

try {
encryptingCipher = Cipher.getInstance(ALGORITHM);
encryptingCipher.init(Cipher.ENCRYPT_MODE, secretKey);

decryptingCipher = Cipher.getInstance(ALGORITHM);
decryptingCipher.init(Cipher.DECRYPT_MODE, secretKey);
} catch (Exception e) {
throw new RuntimeException("Unable to initialize ciphers.");
}
}

public TEncryptedFramedTransport(TTransport transport, Key secretKey) {
this(transport, secretKey, DEFAULT_MAX_LENGTH);
}

public void open() throws TTransportException {
transport_.open();
}

public boolean isOpen() {
return transport_.isOpen();
}

public void close() {
transport_.close();
}

public int read(byte[] buf, int off, int len) throws TTransportException {
if (readBuffer_ != null) {
int got = readBuffer_.read(buf, off, len);
if (got > 0) {
return got;
}
}

// Read another frame of data
readFrame();

return readBuffer_.read(buf, off, len);
}

@Override
public byte[] getBuffer() {
return readBuffer_.getBuffer();
}

@Override
public int getBufferPosition() {
return readBuffer_.getBufferPosition();
}

@Override
public int getBytesRemainingInBuffer() {
return readBuffer_.getBytesRemainingInBuffer();
}

@Override
public void consumeBuffer(int len) {
readBuffer_.consumeBuffer(len);
}

private final byte[] i32buf = new byte[4];

private void readFrame() throws TTransportException {
transport_.readAll(i32buf, 0, 4);
int size = decodeFrameSize(i32buf);

if (size < 0) {
throw new TTransportException("Read a negative frame size (" + size + ")!");
}

if (size > maxLength_) {
throw new TTransportException("Frame size (" + size + ") larger than max length (" + maxLength_ + ")!");
}

byte[] buff = new byte[size];
transport_.readAll(buff, 0, size);

try {
buff = decryptingCipher.doFinal(buff);
} catch (Exception e) {
throw new TTransportException(0, e);
}

readBuffer_.reset(buff);
}

public void write(byte[] buf, int off, int len) throws TTransportException {
writeBuffer_.write(buf, off, len);
}

@Override
public void flush() throws TTransportException {
byte[] buf = writeBuffer_.get();
int len = writeBuffer_.len();
writeBuffer_.reset();

try {
buf = encryptingCipher.doFinal(buf, 0, len);
} catch (Exception e) {
throw new TTransportException(0, e);
}

encodeFrameSize(buf.length, i32buf);
transport_.write(i32buf, 0, 4);
transport_.write(buf);
transport_.flush();
}

public static void encodeFrameSize(final int frameSize, final byte[] buf) {
buf[0] = (byte) (0xff & (frameSize >> 24));
buf[1] = (byte) (0xff & (frameSize >> 16));
buf[2] = (byte) (0xff & (frameSize >> 8));
buf[3] = (byte) (0xff & (frameSize));
}

public static int decodeFrameSize(final byte[] buf) {
return
((buf[0] & 0xff)

multiplicationclient.java

package tutorial;

import co.runit.prototype.CryptoTool;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;

import java.security.Key;

public class MultiplicationClient {
public static void main(String[] args) {
Key key = CryptoTool.decodeKeyBase64("1OUXS3MczVFp3SdfX41U0A==");

try {
TSocket baseTransport = new TSocket("localhost", 9090);
TTransport transport = new TEncryptedFramedTransport(baseTransport, key);
transport.open();

TProtocol protocol = new TBinaryProtocol(transport);
MultiplicationService.Client client = new MultiplicationService.Client(protocol);

perform(client);

transport.close();
} catch (TException x) {
x.printStackTrace();
}
}

private static void perform(MultiplicationService.Client client) throws TException {
int product = client.multiply(3, 5);
System.out.println("3*5=" + product);
}
}
< /code>

Конечно, клавиши должны быть одинаковыми на клиенте и сервере. Чтобы сгенерировать и хранить его в BASE64: < /p>

public static String generateKey() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(128);
Key key = generator.generateKey();
return encodeKeyBase64(key);
}

public static String encodeKeyBase64(Key key) {
return Base64.getEncoder().encodeToString(key.getEncoded());
}

public static Key decodeKeyBase64(String encodedKey) {
byte[] keyBytes = Base64.getDecoder().decode(encodedKey);
return new SecretKeySpec(keyBytes, ALGORITHM);
}
< /code>

обновление 2 < /h2>

реализация Python сверху tframedtransport < /h2>

Strong> tencryptedTransport.py> >
from cStringIO import StringIO
from struct import pack, unpack
from Crypto.Cipher import AES

from thrift.transport.TTransport import TTransportBase, CReadableTransport

__author__ = 'Marboni'

BLOCK_SIZE = 16

pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: '' if not s else s[0:-ord(s[-1])]

class TEncryptedFramedTransportFactory:
def __init__(self, key):
self.__key = key

def getTransport(self, trans):
return TEncryptedFramedTransport(trans, self.__key)

class TEncryptedFramedTransport(TTransportBase, CReadableTransport):
def __init__(self, trans, key):
self.__trans = trans
self.__rbuf = StringIO()
self.__wbuf = StringIO()

self.__cipher = AES.new(key)

def isOpen(self):
return self.__trans.isOpen()

def open(self):
return self.__trans.open()

def close(self):
return self.__trans.close()

def read(self, sz):
ret = self.__rbuf.read(sz)
if len(ret) != 0:
return ret

self.readFrame()
return self.__rbuf.read(sz)

def readFrame(self):
buff = self.__trans.readAll(4)
sz, = unpack('!i', buff)
encrypted = StringIO(self.__trans.readAll(sz)).getvalue()

decrypted = unpad(self.__cipher.decrypt(encrypted))

self.__rbuf = StringIO(decrypted)

def write(self, buf):
self.__wbuf.write(buf)

def flush(self):
wout = self.__wbuf.getvalue()
self.__wbuf = StringIO()

encrypted = self.__cipher.encrypt(pad(wout))
encrypted_len = len(encrypted)
buf = pack("!i", encrypted_len) + encrypted
self.__trans.write(buf)
self.__trans.flush()

# Implement the CReadableTransport interface.
@property
def cstringio_buf(self):
return self.__rbuf

def cstringio_refill(self, prefix, reqlen):
while len(prefix) < reqlen:
self.readFrame()
prefix += self.__rbuf.getvalue()
self.__rbuf = StringIO(prefix)
return self.__rbuf
< /code>

multiplicationclient.py

import base64
from thrift import Thrift
from thrift.transport import TSocket
from thrift.protocol import TBinaryProtocol

from tutorial import MultiplicationService, TEncryptedTransport

key = base64.b64decode("1OUXS3MczVFp3SdfX41U0A==")

try:
transport = TSocket.TSocket('localhost', 9090)
transport = TEncryptedTransport.TEncryptedFramedTransport(transport, key)

protocol = TBinaryProtocol.TBinaryProtocol(transport)
client = MultiplicationService.Client(protocol)

transport.open()

product = client.multiply(4, 5, 'Echo!')
print '4*5=%d' % product

transport.close()
except Thrift.TException, tx:
print tx.message


Подробнее здесь: https://stackoverflow.com/questions/308 ... che-thrift
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Симметричное шифрование (AES) в Apache Thrift
    Anonymous » » в форуме JAVA
    0 Ответы
    15 Просмотры
    Последнее сообщение Anonymous
  • Симметричное шифрование с использованием Fernet в Python — вариант использования главного пароля
    Anonymous » » в форуме Python
    0 Ответы
    24 Просмотры
    Последнее сообщение Anonymous
  • Симметричное шифрование с использованием Fernet в Python — вариант использования главного пароля
    Anonymous » » в форуме Python
    0 Ответы
    24 Просмотры
    Последнее сообщение Anonymous
  • Cryptojs.aes.encrypt () и Java AES шифрование, давая разные результаты
    Гость » » в форуме JAVA
    0 Ответы
    22 Просмотры
    Последнее сообщение Гость
  • Cryptojs.aes.encrypt () и Java AES шифрование, давая разные результаты
    Гость » » в форуме Javascript
    0 Ответы
    33 Просмотры
    Последнее сообщение Гость

Вернуться в «Python»