- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有两个使用 Thrift 进行交互的应用程序。他们共享相同的 key ,我需要加密他们的消息。使用对称算法(例如 AES)是有意义的,但我还没有找到任何库来执行此操作。所以我做了一个研究,看到了以下选项:
我可以使用内置的 SSL 支持,建立安全连接并使用我的 key 作为身份验证 token 。除了证书已有的 key 外,它还需要安装证书,但除了检查从客户端收到的 key 是否与本地存储的 key 相同外,我不需要执行任何操作。
到目前为止,有以下选项:
TSocket
并覆盖 write()
和 read()
方法并在其中加密/解密数据。小型写入的流量将会增加。例如,如果 TBinaryProtocol
写入 4 字节整数,它将在加密状态下占用一个 block (16 字节)。TSocket
并用CipherInputStream
和CipherOutputStream
包装InputStream
和OutputStream
。 CipherOutputStream
不会立即加密小字节数组,用它们更新 Cipher
。在我们有足够的数据后,它们将被加密并写入底层的OutputStream
。所以它会等到你添加 4 个 4 字节的整数然后加密它们。它允许我们不浪费流量,但也是问题的原因 - 如果最后一个值不会填充 block ,它将永远不会被加密并写入底层流。它希望我写入可被其 block 大小(16 字节)整除的字节数,但我无法使用 TBinaryProtocol
执行此操作。TBinaryProtocol
,缓存所有写入而不是将它们写入流并在writeMessageEnd()
方法中加密。在 readMessageBegin()
中实现解密。我认为加密应该在传输层执行,而不是协议(protocol)层。请与我分享您的想法。
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) << 24) |
((buf[1] & 0xff) << 16) |
((buf[2] & 0xff) << 8) |
((buf[3] & 0xff));
}
}
MultiplicationServer.java
package tutorial;
import co.runit.prototype.CryptoTool;
import org.apache.thrift.server.TNonblockingServer;
import org.apache.thrift.server.TServer;
import org.apache.thrift.transport.TNonblockingServerSocket;
import org.apache.thrift.transport.TNonblockingServerTransport;
import java.security.Key;
public class MultiplicationServer {
public static MultiplicationHandler handler;
public static MultiplicationService.Processor processor;
public static void main(String[] args) {
try {
handler = new MultiplicationHandler();
processor = new MultiplicationService.Processor(handler);
Runnable simple = () -> startServer(processor);
new Thread(simple).start();
} catch (Exception x) {
x.printStackTrace();
}
}
public static void startServer(MultiplicationService.Processor processor) {
try {
Key key = CryptoTool.decodeKeyBase64("1OUXS3MczVFp3SdfX41U0A==");
TNonblockingServerTransport serverTransport = new TNonblockingServerSocket(9090);
TServer server = new TNonblockingServer(new TNonblockingServer.Args(serverTransport)
.transportFactory(new TEncryptedFramedTransport.Factory(key))
.processor(processor));
System.out.println("Starting the simple server...");
server.serve();
} catch (Exception e) {
e.printStackTrace();
}
}
}
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);
}
}
当然,客户端和服务端的 key 必须相同。生成并存储在 Base64 中:
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);
}
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
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
最佳答案
正如 JensG 所述,发送外部加密的二进制文件或提供分层密码传输是两个最佳选择。如果您需要模板,请查看 TFramedTransport。它是一种简单的分层传输,可以轻松用作创建 TCipherTransport 的起始 block 。
关于java - Apache Thrift 中的对称加密 (AES),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30861393/
这个问题已经有答案了: Reverse the ordering of words in a string (48 个回答) 已关闭 4 年前。 我想更改字符串中单词的位置。它需要对称变化。 示例 m
我的公司将为客户存储敏感数据,并将使用托管 .NET 加密算法类之一来加密数据。大部分工作已经完成,但我们还没有弄清楚如何/在哪里存储 key 。我已经做了一些简单的搜索和阅读,看起来硬件解决方案可能
我在 postgres 和对称 ds 的默认配置中使用对称 ds。 我总是收到以下错误。 2017-12-20 09:59:53,372 INFO [SymmetricLauncher] [Wrap
我正在使用 postgresql8.3 并在我的应用程序中包含 symmetris ds 1.5.1。但客户端到服务器的复制工作正常。但复制不是从服务器到客户端完成的。我是使用对称 ds 的新手。任何
我正在寻找一种与 JavaScript 和 Java 兼容的安全对称 key 加密算法。 我已经尝试实现一个,但我遇到了一些编码问题。 最佳答案 您不想使用 JavaScript 加密,especia
我读过 DDA .但我刚刚遇到symmetric DDA 这个术语。它是什么 ?它与 DDA 有何不同? 最佳答案 DDA(数字差分分析仪)算法用于找出任意给定两点之间的线性插值点(即直线)。现在,由
我已经使用 Spring Cloud Config Server 设置了一个简单的项目,我正在尝试简单地加密和解密一些值。我使用以下带有 Spring Boot 的 pom.xml 将项目创建为 Sp
我需要通过扩展 Symmetric DS 提供的接口(interface)来扩展它的功能。有谁知道开发流程应该是什么?在文档中,它只解释了将 JAR 文件(包含扩展接口(interface)的类)放在
我将在 中最多包含 50 个条目 map 。这样做的原因是我在初始握手后使用的协议(protocol)通过数字引用字符串名称 - 我假设服务器上必须存在与我的类似的 map 。 我想要的是一个可以搜
我在尝试编写这些函数时遇到困难。他们工作不正常,不知道我做错了什么。至于 Transitive,我什至无法开始,希望你能提供任何帮助,以及我在我的功能中做错了什么。谢谢。 示例输入: 0 1 2 3
什么是加密 SQL 数据库中某些敏感或个人身份数据的“最佳实践”(根据 PCI、HIPAA 或其他适用的合规性标准)? 这里有很多关于解决方案各个方面的问题,但我还没有看到任何在高层次上讨论该方法的问
我必须创建一个六边形,我真的希望它是完整的 HTML 和 CSS。它几乎完成了,除了它不是完全对称的。左 Angular 与右 Angular 不对齐。当前的CSS: .hexagon.outer {
我发现:“唯一需要 TURN 的情况是当其中一个对等点位于对称 NAT 后面,而另一个对等点位于对称 NAT 或端口限制 NAT 后面时。”那么,对称 NAT 后面的对等点如何连接后面的另一个点(例如
如何有效地按行的范数对矩阵进行排序(使用 numpy.ndarrays)? 我想对矩阵 A 进行排序: A = np.array( ( [ 10, 1, 6, 3 ],
我正在尝试使用 MBED TLS 加密函数来解开已使用我拥有的对称 key 使用 AES-128 key 包装进行加密的 key 。 我是加密新手,我的理解是 key 包装/解开与加密/解密不同。这是
所以基本上我的程序从用户选择的文本文件中加密/解密字符串。他可以选择五种算法之一。问题是当我用例如创建密文时。 AES然后将此密文保存到文本文件中,并想解密它以获取原始字符串,这是行不通的。有人可以指
我正在开展一个 OpenCL 项目以生成非常大的厄尔米特(对称)矩阵,并且我正在尝试确定生成工作 ID 的最佳方式。 厄密矩阵沿对角线对称,因此 M(i,j) = M*(j,i)。 在暴力方式下,fo
我想让底部圆圈对称,这意味着我希望第 5 个圆圈介于第 1 和第 2 个(但仍在下方)之间,第 7 个圆圈介于第 3 和第 4 个之间。 我在 v-for 循环中显示这个圆圈。我将它们全部放在一个容器
对于固定维数 (N=9) 的稠密线性系统(矩阵是对称的,半正定的)的快速求解,您会推荐哪种算法? 高斯消元法 LU分解 Cholesky 分解 等等? 类型是 32 位和 64 位 float 。 这
我有一个尺寸为行 x 列 x 深度的 3D 图像。对于图像中的每个体素,我计算了一个 3x3 实对称矩阵。它们存储在数组 D 中,因此具有形状 (rows, cols, deps, 6)。 D 为图像
我是一名优秀的程序员,十分优秀!