2017-11-06 11 views
0

私のチームがAPI資格情報の暗号化をどのように使用し、他のチーム/プロジェクトから暗号化されたメッセージを受け取るかを簡略化するために暗号化ライブラリを作成しています。API /ライブラリの並列継承階層を回避する方法

私はドメインを定義するには、これらのトップレベルインターフェースを開始しました:

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を使用しているため、SecretにはInitializationVectorが含まれています。

だから私はこれを持っている:

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が私はリスコフの置換原則に違反し、かつ並列階層コード-臭いを導入してると思います。 Visitorパターンはこのコードの匂いに対する一般的な解決策ですが、私の状況にどのように適用されるかはわかりません。

提案がありますか?それとも私はこれを熟考していますか?

私は要旨にこれらのクラスを追加しました:https://gist.github.com/mmeier/c493c28cbcd57a73d08419066cd23484

+1

Generics。 ''秘密 'の 'en/decrypter'ジェネリックを作ります。 Createと 'interface' - ' CbcSecret'は 'extends Secret'を追加し、IVを追加します。 –

+0

また、 'getBytes'を持つすべてのインタフェースは、いくつかの親を募集しているようです。そしてインターフェイスの 'public'メソッドは私を悲しくします。 –

+1

最後に、 'Decrypter'が' Message'を取り、 'Encrypter'が' String'を返すのは奇妙に思えます。私は彼らがお互いの逆であることを期待するでしょう。 –

答えて

1

あなたの復号化は、一般的な作ることができます。

interface Decryptor<S extends Secret>{ 
    public String decrypt(S secret, Key publicKey); 
} 

このように、Decryptorのすべての実装では、独自の秘密を定義できます。それであなたはあなたのキャスティングを取り除くことができます。

-1

暗号APIには通常「初期化」機能があり、その後に別の復号化/暗号化があります。 APIを開発している場合は、インスピレーションのために他のAPIを勉強することをお勧めします(Javaには既に使用できるCipher APIがあります)。一方、私はあなたの暗号を書くのではなく、代わりにbouncycasleのようなライブラリを使うことをお勧めします。

+0

これは質問に答えません。これはコメントに属します。 –

+0

あなたはそれについて正しいです。 – davidpetter

+0

私が使用している実装はBouncyCastleです。私はjava.securityとBouncyCastleの両方がチェックされた例外のロードを導入するので、私たち自身のAPIの背後に隠しています。だから、私はそれらのライブラリを「フードの下に」使っていますが、他の理由のなかでも、非常に面倒な例外がある単純化されたAPIを公開したいのです。 – gridDragon

関連する問題