0

クライアントサーバーTokenServiceの3つのサービスで構成されるアプリケーションがあります。サーバー上のデータにアクセスするには、クライアントはTokenServiceSecurityTokenからオブジェクトを取得する必要があります。パーティ間の通信は、共有キーを使用して暗号化されます(クライアントTokenServiceはキー「A」を共有し、 TokenServiceサーバーは異なるキー「B」を共有します)。クライアントがTokenServiceにリクエストを送信すると、通信は「A」で暗号化されます。TokenServiceが戻ったときSecurityTokenオブジェクトの場合、このオブジェクトは次のようにBとAで暗号化されます((SecurityToken)B)A)この二重に暗号化されたオブジェクトは最初にクライアントに戻り、クライアントはそれをAで復号化し、別のオブジェクトに入れ、いくつかの追加情報(要求付きの文字列)を添付してサーバーに送信し、そこでSecurityTokenBで復号 化されます。

SecurityTokenサーバー側でオブジェクトを復号化するまでは、すべて正常に機能します。例外が発生します:

 javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:749)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:675)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at mds.hm5.sharedclasses.Decryptor.decryptData(Decryptor.java:40)
at mds.hm5.tokenservice.Main2.main(Main2.java:28)

私はこのエラーを次のように(当事者間のリモート通信なしで)再現することができました:

public static void main(String[] args) {

    SecurityToken s = new SecurityToken(false, "2");

    try {
        byte[] bytes = Encryptor.getBytesFromObject(s);
        bytes = Encryptor.encryptData(bytes, "secretkey1");
        bytes = Encryptor.encryptData(bytes, "secretkey2");
        bytes = Base64.encodeBase64(bytes);

        System.out.println(bytes);

        bytes = Base64.decodeBase64(bytes);
        bytes = Decryptor.decryptData(bytes, "secretkey2");
        bytes = Decryptor.decryptData(bytes, "secretkey1");
        SecurityToken s2 = (SecurityToken) Decryptor.getObjectFromBytes(bytes);

        System.out.println(s2.getRole());

    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

ここで何が間違っているのかわかりません。そのように2層の暗号化を作成することは不可能ですか?私は何かが足りないのですか?

追加情報:

これが私のEncryptorクラスです:

public class Encryptor {

public static byte[] encryptData(byte[] credentials, String key){

    Cipher c;
    SecretKeySpec k;
    byte[] byteCredentials = null;
    byte[] encryptedCredentials = null;
    byte[] byteSharedKey = null;

    try {

        byteCredentials = getBytesFromObject(credentials);
        byteSharedKey = getByteKey(key);

        c = Cipher.getInstance("AES");
        k = new SecretKeySpec(byteSharedKey, "AES");
        c.init(Cipher.ENCRYPT_MODE, k);
        encryptedCredentials = c.doFinal(byteCredentials);

    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    }

    return encryptedCredentials;

}

public static byte[] getBytesFromObject(Object credentials) throws IOException{

    //Hmmm.... now I'm thinking I should make generic type for both: Token and ITU_Credentials object, that would have this getBytes and getObject methods.
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutput out = null;
    byte[] newBytes = null;

    try {

      out = new ObjectOutputStream(bos);   
      out.writeObject(credentials);
      newBytes = bos.toByteArray();

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
      out.close();
      bos.close();
    }
    return newBytes;
}

private static byte[] getByteKey(String key) throws UnsupportedEncodingException, NoSuchAlgorithmException{

    //Converting key to SHA-1 and trimming to mach maximum lenght of key

    byte[] bkey = key.getBytes("UTF-8");
    MessageDigest sha = MessageDigest.getInstance("SHA-1");
    bkey = sha.digest(bkey);
    bkey = Arrays.copyOf(bkey, 16);

    return bkey;
}

そして、これが私のDecryptorクラスです:

public class Decryptor {


public static byte[] decryptData(byte[] encryptedCredentials, String key){

    Cipher c;
    SecretKeySpec k;
    byte[] byteSharedKey = null;
    byte[] byteObject = null;


    try {

        byteSharedKey = getByteKey(key);

        c = Cipher.getInstance("AES");
        k = new SecretKeySpec(byteSharedKey, "AES");
        c.init(Cipher.DECRYPT_MODE, k);
        byteObject = c.doFinal(encryptedCredentials);



    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    }

    return byteObject;

}

public static Object getObjectFromBytes(byte[] credentials) throws IOException, ClassNotFoundException{

    ByteArrayInputStream bis = new ByteArrayInputStream(credentials);
    ObjectInput in = null;
    ITU_Credentials credentialsObj = null;

    try {

        in = new ObjectInputStream(bis);
        credentialsObj = (ITU_Credentials)in.readObject(); 

    } finally {
      bis.close();
      in.close();
    }
    return credentialsObj;
}


private static byte[] getByteKey(String key) throws UnsupportedEncodingException, NoSuchAlgorithmException{

    //Converting key to SHA-1 and trimming to mach maximum lenght of key

    byte[] bkey = key.getBytes("UTF-8");
    MessageDigest sha = MessageDigest.getInstance("SHA-1");
    bkey = sha.digest(bkey);
    bkey = Arrays.copyOf(bkey, 16);

    return bkey;
}

public static void main(String[] args) {
    new Encryptor();
}

}

編集:

アドバイスに従って、例外を適切にスローするために、クラス内のすべてe.printStackTrace();をに置き換えました。throw new RuntimeException(e);Decriptor

public class Decryptor {


public static byte[] decryptData(byte[] encryptedCredentials, String key){

    Cipher c;
    SecretKeySpec k;
    byte[] byteSharedKey = null;
    byte[] byteObject = null;


    try {

        byteSharedKey = getByteKey(key);

        c = Cipher.getInstance("AES");
        k = new SecretKeySpec(byteSharedKey, "AES");
        c.init(Cipher.DECRYPT_MODE, k);
        byteObject = c.doFinal(encryptedCredentials);



    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
        throw new RuntimeException(e);
    } catch (InvalidKeyException e) {
        throw new RuntimeException(e);
    } catch (IOException e) {
        throw new RuntimeException(e);
    } catch (IllegalBlockSizeException e) {
        throw new RuntimeException(e);
    } catch (BadPaddingException e) {
        throw new RuntimeException(e);
    }

    return byteObject;

}

public static Object getObjectFromBytes(byte[] credentials) throws IOException, ClassNotFoundException{

    ByteArrayInputStream bis = new ByteArrayInputStream(credentials);
    ObjectInput in = null;
    ITU_Credentials credentialsObj = null;

    try {

        in = new ObjectInputStream(bis);
        credentialsObj = (ITU_Credentials)in.readObject(); 

    } finally {
      bis.close();
      in.close();
    }
    return credentialsObj;
}


private static byte[] getByteKey(String key) throws UnsupportedEncodingException, NoSuchAlgorithmException{

    //Converting key to SHA-1 and trimming to mach maximum lenght of key

    byte[] bkey = key.getBytes("UTF-8");
    MessageDigest sha = MessageDigest.getInstance("SHA-1");
    bkey = sha.digest(bkey);
    bkey = Arrays.copyOf(bkey, 16);

    return bkey;
}

public static void main(String[] args) {
    new Encryptor();
}

}

これで、例外は次のようになります。

Exception in thread "main" java.lang.RuntimeException: javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at mds.hm5.sharedclasses.Decryptor.decryptData(Decryptor.java:51)
at mds.hm5.tokenservice.Main2.main(Main2.java:28)
Caused by: javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:749)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:675)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at mds.hm5.sharedclasses.Decryptor.decryptData(Decryptor.java:40)
... 1 more
4

1 に答える 1

1

あなたの問題の根本は次のとおりだと思います。

byte[] bytes = Encryptor.getBytesFromObject(s);
bytes = Encryptor.encryptData(bytes, "secretkey1");

これは次のようになります:

//etc.//
byte[] encryptedCredentials = null;
byte[] byteSharedKey = null;

try {
    byteCredentials = getBytesFromObject(credentials);
    //Whoops!  credentials is already a byte array.
//etc.//
catch (and eat) exception.....
return encryptedCredentials;

そして、例外を食べて null を返すだけなので、ホームがコメントで反対するようにアドバイスしているように、復号化ステップに到達するまで動き続けます。そこでキャッチする 8 種類の Exception のいずれでもない IllegalBlockSizeException )、そして何か役に立つものを提供します。

それがとにかく起こっていると思います。

于 2012-11-20T17:47:38.387 に答える