Java 如何避免API/库中的并行继承层次结构
我正在开发一个加密库,以简化我的团队如何对api凭据使用加密,以及如何从其他团队/项目接收加密消息 我从这些顶级接口开始定义域:Java 如何避免API/库中的并行继承层次结构,java,design-patterns,Java,Design Patterns,我正在开发一个加密库,以简化我的团队如何对api凭据使用加密,以及如何从其他团队/项目接收加密消息 我从这些顶级接口开始定义域: public interface Key { public byte[] getBytes(); } public interface Message { public byte[] getBytes(); } public interface Secret { public byte[] getBytes(); } public int
public interface Key {
public byte[] getBytes();
}
public interface Message {
public byte[] getBytes();
}
public interface Secret {
public byte[] getBytes();
}
public interface Decrypter {
public String decrypt(Secret secret, Key key);
}
public interface Encrypter {
public Secret encrypt(Message message, Key key);
}
这对于包装RSA加密非常有效:
public class KeyPair {
private final Key publicKey;
private final Key privateKey;
public Key getPublicKey() {
return publicKey;
}
public Key getPrivateKey() {
return privateKey;
}
}
public class RsaEncrypter implements Encrypter {
@Override
public Secret encrypt(Message message, Key publicKey) {
// Perform Encryption
}
}
public class RsaDecrypter implements Decrypter {
@Override
public String decrypt(Secret secret, Key privateKey) {
// Perform the decryption
}
}
但是现在我将它应用到我们的AES加密用例中,我遇到了一个问题。这个秘密包含一个初始化向量,因为我们在CBC模式下使用AES
所以我有这个:
public class AesSecret implements Secret {
private byte[] cipherText;
private byte[] initilizationVector;
@Override
public byte[] getBytes() {
return cipherText;
}
public byte[] getInitilizationVector() {
return initilizationVector;
}
}
public class AesDecrypter implements Decrypter {
@Override
public String decrypt(Secret secret, Key key) {
try {
return decrypt((AesSecret) secret, key);
} catch (ClassCastException e) {
throw new IllegalArgumentException("AesDecrypter only supports subclasses of AesSecret", e);
}
}
public String decrypt(AesSecret secret, Key key) {
// Do the AES Decryption
}
}
ClassCastException让我觉得我违反了Liskov替换原则,引入了并行层次代码。我已经读过Visitor模式是这种代码气味的常见解决方案,但我还没有弄清楚它如何适用于我的情况
有什么建议吗?还是我想得太多了
我已经在要点中添加了这些类:您可以将解密程序设置为通用的。大概是这样的:
interface Decryptor<S extends Secret>{
public String decrypt(S secret, Key publicKey);
}
这样,解密器的每个实现都可以定义自己的秘密。这样你就可以摆脱铸造。仿制药。使en/解密程序在机密中通用。Create和interface-CbcSecret,它扩展了Secret并添加了IV。此外,所有带有getBytes的接口似乎都在乞求某个父接口。接口上的公共方法让我很难过。最后,解密程序接收消息,加密程序返回字符串似乎很奇怪。我希望它们彼此相反。@aglassman只要使用可信的实现,就可以使用自己的API。关键是java.security有点棘手,需要正确处理;不熟悉它的人很可能会错误地使用它。用一个简单的API生成一个经过测试的正确用法将有助于防止这种情况。@aglassman:我实际上使用的是java.security。我们的存储库中有使用它的代码,但我花了几天时间对它的工作方式/原因进行逆向工程。因此,我将这些代码放入一个带有单元测试套件的共享库中,以便我们的其他项目可以使用简化的API。尽管如此,它仍然得到了可信库的支持。