.NET TripleDESCryptoServiceProvider equivalent in Java

后端 未结 4 672
温柔的废话
温柔的废话 2020-12-25 09:26

Please, just don\'t ask me why. I just have this code in .NET that encrypt/decrypt strings of data. I need now to make \'exactly\' the same funcionality in java. I have trie

相关标签:
4条回答
  • 2020-12-25 09:37

    Have you made sure the .NET code uses the same padding as the Java code? I see no padding specified in the .NET code, that's why I ask.

    Do you happen to have the source for the Java code, it will help find mistakes.

    0 讨论(0)
  • 2020-12-25 09:43

    You got a few problems,

    1. Your key must be 24 bytes if you want generate the same key materials on both .NET and Java.
    2. The IV must be block size, which is 8 bytes for Triple DES.
    3. In Java, you need to specify the default mode and padding, which is "DESede/CBC/NoPadding".

    Once you make these changes, you should be able to decrypt it on Java side.

    0 讨论(0)
  • 2020-12-25 09:45

    Try the following. For actual usage, I would get a base64 library like commons codec or use the codec that comes with BouncyCastle

    import java.io.IOException;
    import java.security.GeneralSecurityException;
    import java.security.NoSuchAlgorithmException;
    
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.IvParameterSpec;
    
    public class Encryption {
    
        private static SecretKey sharedkey;
        private static byte [] sharedvector;
    
        static {
            int keySize = 168;
            int ivSize = 8;
            try {
                KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
                keyGenerator.init(keySize);
                sharedkey = keyGenerator.generateKey();
    
                sharedvector = new byte [ivSize];
                byte [] data = sharedkey.getEncoded();
    
                int half = ivSize / 2;
                System.arraycopy(data, data.length-half, sharedvector, 0, half);
                System.arraycopy(sharedvector, 0, sharedvector, half, half);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String [] args) throws Exception {
            System.out.println(Decrypt(Encrypt("Hello World")));
    
        }
    
        public static String Encrypt(String val) throws GeneralSecurityException {
            Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, sharedkey, new IvParameterSpec(sharedvector));
    
            return new sun.misc.BASE64Encoder().encode(cipher.doFinal(val.getBytes()));
        }
    
        public static String Decrypt(String val) throws GeneralSecurityException, IOException {
            Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, sharedkey, new IvParameterSpec(sharedvector));
    
            return new String(cipher.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(val)));
        }
    
    }
    
    0 讨论(0)
  • 2020-12-25 09:56

    Code follows, but first a few notes.

    1. A different initialization vector must be chosen for every message. Hard-coding the initialization vector does not make sense. The IV should be sent along with the cipher text to the message recipient (it's not secret).
    2. I used my own utility class for base-64 encoding. You can use sun.misc.BASE64Encoder and sun.misc.BASE64Decoder instead, use a third-party library like BouncyCastle, or write your own.
    3. You are using 2-key triple DES, where the first key and the third key is the same. I modified sharedkey to reflect this, since the Java DESede cipher always requires a 192-bit key; it's up to the key generator to handle the keying option.
    4. A CBC IV is only 64 bits. I've used only the first 64 bits of sharedvector.

    This class should inter-operate with the C# version.

    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    
    public class Encryption
    {
    
      private static byte[] sharedkey = {
        0x01, 0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11, 
        0x12, 0x11, 0x0D, 0x0B, 0x07, 0x02, 0x04, 0x08, 
        0x01, 0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11
      };
    
      private static byte[] sharedvector = {
        0x01, 0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11
      };
    
      public static void main(String... argv)
        throws Exception
      {
        String plaintext = "userNameHere:passwordHere";
        String ciphertext = encrypt(plaintext);
        System.out.println(ciphertext);
        System.out.println(decrypt(ciphertext));
      }
    
      public static String encrypt(String plaintext)
        throws Exception
      {
        Cipher c = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sharedkey, "DESede"), new IvParameterSpec(sharedvector));
        byte[] encrypted = c.doFinal(plaintext.getBytes("UTF-8"));
        return Base64.encode(encrypted);
      }
    
      public static String decrypt(String ciphertext)
        throws Exception
      {
        Cipher c = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        c.init(Cipher.DECRYPT_MODE, new SecretKeySpec(sharedkey, "DESede"), new IvParameterSpec(sharedvector));
        byte[] decrypted = c.doFinal(Base64.decode(ciphertext));
        return new String(decrypted, "UTF-8");
      }
    
    }
    

    Output:

    zQPZgQHpjxR+41Bc6+2Bvqo7+pQAxBBVN+0V1tRXcOc=

    userNameHere:passwordHere

    0 讨论(0)
提交回复
热议问题