Java中的URL加密
时间:2020-03-06 14:37:42 来源:igfitidea点击:
在Java中使用参数加密URL的最佳方法是什么?
解决方案
我们确定我们不是要对URL进行编码吗?
可以通过java.net.URLEncoder.encode进行编码。
Java安全api(http://java.sun.com/javase/technologies/security/)+网址编码
唯一的方法是使用SSL / TLS(https)。如果我们使用普通的旧HTTP,则绝对会以明文形式发送URL。
这取决于威胁模型。例如,如果要保护Java应用程序发送给服务器的参数免受有权访问通信通道的攻击者的攻击,则应考虑通过TLS / SSL(即情况下为HTTPS)和喜欢。如果要保护参数免受攻击者的侵害,而攻击者可以访问运行Java客户端应用程序的计算机,那么我们将面临更大的麻烦。
如果我们真的不能使用SSL,建议我们使用预共享密钥方法并添加随机iv。
我们可以使用任何体面的对称加密方法,例如ex。使用我们正在带外通信(电子邮件,电话等)的预共享密钥进行AES。
然后,我们将生成一个随机的初始化向量,并使用此iv和密钥对字符串进行加密。最后,将密文和iv连接起来,并将其作为参数发送。 iv可以毫无风险地进行明确沟通。
不幸的是,几乎注意到Java是很简单的:-),对于这个简单而又平常的任务,我无法找到准备好的库,最终我写了这个(这是源代码):
import java.net.URLDecoder; import java.net.URLEncoder; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEParameterSpec; /** * An easy to use class to encrypt and decrypt a string. Just call the simplest * constructor and the needed methods. * */ public class StringEncryptor { private Cipher encryptCipher; private Cipher decryptCipher; private sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder(); private sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder(); final private String charset = "UTF-8"; final private String defaultEncryptionPassword = "PAOSIDUFHQWER98234QWE378AHASDF93HASDF9238HAJSDF923"; final private byte[] defaultSalt = { (byte) 0xa3, (byte) 0x21, (byte) 0x24, (byte) 0x2c, (byte) 0xf2, (byte) 0xd2, (byte) 0x3e, (byte) 0x19 }; /** * The simplest constructor which will use a default password and salt to * encode the string. * * @throws SecurityException */ public StringEncryptor() throws SecurityException { setupEncryptor(defaultEncryptionPassword, defaultSalt); } /** * Dynamic constructor to give own key and salt to it which going to be used * to encrypt and then decrypt the given string. * * @param encryptionPassword * @param salt */ public StringEncryptor(String encryptionPassword, byte[] salt) { setupEncryptor(encryptionPassword, salt); } public void init(char[] pass, byte[] salt, int iterations) throws SecurityException { try { PBEParameterSpec ps = new javax.crypto.spec.PBEParameterSpec(salt, 20); SecretKeyFactory kf = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); SecretKey k = kf.generateSecret(new javax.crypto.spec.PBEKeySpec(pass)); encryptCipher = Cipher.getInstance("PBEWithMD5AndDES/CBC/PKCS5Padding"); encryptCipher.init(Cipher.ENCRYPT_MODE, k, ps); decryptCipher = Cipher.getInstance("PBEWithMD5AndDES/CBC/PKCS5Padding"); decryptCipher.init(Cipher.DECRYPT_MODE, k, ps); } catch (Exception e) { throw new SecurityException("Could not initialize CryptoLibrary: " + e.getMessage()); } } /** * * method to decrypt a string. * * @param str * Description of the Parameter * * @return String the encrypted string. * * @exception SecurityException * Description of the Exception */ public synchronized String encrypt(String str) throws SecurityException { try { byte[] utf8 = str.getBytes(charset); byte[] enc = encryptCipher.doFinal(utf8); return URLEncoder.encode(encoder.encode(enc),charset); } catch (Exception e) { throw new SecurityException("Could not encrypt: " + e.getMessage()); } } /** * * method to encrypting a string. * * @param str * Description of the Parameter * * @return String the encrypted string. * * @exception SecurityException * Description of the Exception */ public synchronized String decrypt(String str) throws SecurityException { try { byte[] dec = decoder.decodeBuffer(URLDecoder.decode(str,charset)); byte[] utf8 = decryptCipher.doFinal(dec); return new String(utf8, charset); } catch (Exception e) { throw new SecurityException("Could not decrypt: " + e.getMessage()); } } private void setupEncryptor(String defaultEncryptionPassword, byte[] salt) { java.security.Security.addProvider(new com.sun.crypto.provider.SunJCE()); char[] pass = defaultEncryptionPassword.toCharArray(); int iterations = 3; init(pass, salt, iterations); }
}
加密HTTP通信的标准方法是使用SSL。但是,即使通过HTTPS,URL和其中的任何参数(即GET请求)也将以明文形式发送。我们将需要使用SSL并执行POST请求以正确加密数据。
如注释中所指出的,无论我们使用哪种HTTP方法,只要我们使用SSL连接,参数都将被加密。