【问题标题】:Able to decrypt the message using different key能够使用不同的密钥解密消息
【发布时间】:2018-04-17 09:35:33
【问题描述】:

我创建了以下单例类来加密和解密字符串消息。

public class EncryptionHelper {
  private Cipher ecipher;
  private Cipher dcipher;
  private SecretKey key;
  private byte iv[] = { 8, 7, 6, 5, 4, 3, 2, 1 };

  private static EncryptionHelper instance;

  public static EncryptionHelper getInstance( String defKey ) {
    synchronized( EncryptionHelper.class ) {
      if ( null == instance ) {
        try {
          instance = new EncryptionHelper( defKey );
        } catch( Exception e ) {
                  }
      }
    }
    return instance;
  }

  private EncryptionHelper( String defKey )
    throws Exception {
    DESedeKeySpec keyspec = new DESedeKeySpec( defKey.getBytes() );
    SecretKeyFactory keyfactory = SecretKeyFactory.getInstance( "TripleDES" );
    key = keyfactory.generateSecret( keyspec );
    ecipher = Cipher.getInstance( "TripleDES/CBC/PKCS5Padding" );
    dcipher = Cipher.getInstance( "TripleDES/CBC/PKCS5Padding" );
    ecipher.init( Cipher.ENCRYPT_MODE, key, new IvParameterSpec( iv ) );
    dcipher.init( Cipher.DECRYPT_MODE, key, new IvParameterSpec( iv ) );
  }

  public String encrypt( String str ) {
    try {
      byte[] utf8 = str.getBytes( "UTF-8" );
      byte[] enc = ecipher.doFinal( utf8 );
      String val = Base64.getEncoder().encodeToString( enc );
      return val;
    } catch( UnsupportedEncodingException | IllegalBlockSizeException | BadPaddingException e ) {
    }
    return str;
  }

  public String decrypt( String str ) {
    try {
      byte[] dec = Base64.getDecoder().decode( str );
      byte[] utf8 = dcipher.doFinal( dec );
      return new String( utf8, "UTF8" );
    } catch( IllegalBlockSizeException | BadPaddingException | IOException e ) {
    }
    return str;
  }  
}

当我尝试使用这个类的加密和解密方法时,使用两个不同的程序使用不同的密钥,如下所示。

public static void main( String[] args ) {
  EncryptionHelper encryptionHelper = EncryptionHelper.getInstance( "000000000000ffffffffffff" );
  System.out.println( encryptionHelper.encrypt( "ABCDEFGH" ) );
}

输出是 ::: n+0SEJQDXwfvpdMIdetNow==

public static void main( String[] args ) {
  // Use different key to decrypt
  EncryptionHelper encryptionHelper = EncryptionHelper.getInstance( "111111111111ffffffffffff" );
  // Use output of previous call as input to decrypt
  System.out.println( encryptionHelper.decrypt( "n+0SEJQDXwfvpdMIdetNow==" ) );
}

输出是 ::: ABCDEFGH

如您所见,我在使用加密和解密方法时使用了不同的密钥,但程序仍然能够使用错误的密钥解密确切的值。

你们能帮我知道,为什么会这样,为什么我可以使用错误的密钥解密?

【问题讨论】:

  • 请注意 String.getBytes() 不会从十六进制转换...

标签: encryption cryptography java-security tripledes


【解决方案1】:

为什么我可以使用错误的密钥解密?

...因为您使用的不是第二个密钥,而是第一次调用getInstance时使用的密钥

如果您没有看到,请自己回答以下问题...在您对getInstance 的第二次调用中,当instance 已经有一个值并且不是NULL 时,defKey 如何影响实例? (提示:它没有)

【讨论】:

  • 我相信你没有仔细检查,两个客户端程序是两个不同的独立程序,并且有自己的 main() 方法。
  • 在这种情况下,请将包含 defKey 参数的字符串添加到您的助手中,如果您使用另一个字符串调用 get 实例,则会引发异常...
  • 不可能使用这种变通方法,因为这样键将在代码中变得恒定,并且为开发人员所知。我希望多个客户端使用他们自己的密钥来加密/解密消息。问题很容易理解,为什么可以使用不同的密钥进行解密。算法或代码有什么问题吗?
  • 我并不是要对密钥进行硬编码...我的猜测是您使用另一个密钥调用一次...如果您存储并比较参数,您可以检测到
猜你喜欢
  • 2011-12-06
  • 2019-01-14
  • 2022-01-28
  • 2017-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-07
相关资源
最近更新 更多