📄 decryptionmanager.java
字号:
* depends on the type of security mechanism being used: * USRENCPWD - The userid is used as the token. The USRID is zero-padded to * 8 bytes if less than 8 bytes or truncated to 8 bytes if greater than 8 bytes. * EUSRIDPWD - The middle 8 bytes of the server's connection key is used as * the token. Decryption needs to use exactly the same token as encryption. * * @param securityMechanism security mechanism * @param initVector userid or server(this side)'s connection key * @return byte[] the decryption token */ private byte[] calculateDecryptionToken (int securityMechanism, byte[] initVector) { byte[] token = new byte[8]; //USRENCPWD, the userid is used as token if (securityMechanism == 7) { if (initVector.length < 8) { //shorter than 8 bytes, zero padded to 8 bytes for (int i=0; i<initVector.length; i++) token[i] = initVector[i]; for (int i=initVector.length; i<8; i++) token[i] = 0; } else { //longer than 8 bytes, truncated to 8 bytes for (int i=0; i<8; i++) token[i] = initVector[i]; } } //EUSRIDPWD - The middle 8 bytes of the server's connection key is used as //the token. else if (securityMechanism == 9) { for (int i = 0; i < 8; i++) { token[i] = initVector[i + 12]; } } return token; } /** * This method generates a secret key using the application requester's * public key, and decrypts the usreid/password with the middle 8 bytes of * the generated secret key and a decryption token. Then it returns the * decrypted data in a byte array. * * @param cipherText The byte array form userid/password to decrypt. * @param securityMechanism security mechanism * @param initVector The byte array which is used to calculate the * decryption token for initializing the cipher * @param sourcePublicKey application requester (encrypter)'s public key. * @return the decrypted data (plain text) in a byte array. */ public byte[] decryptData (byte[] cipherText, int securityMechanism, byte[] initVector, byte[] sourcePublicKey) throws SQLException { byte[] plainText = null; byte[] token = calculateDecryptionToken (securityMechanism, initVector); try { //initiate a Diffie_Hellman KeyFactory object. KeyFactory keyFac = KeyFactory.getInstance ("DH", "IBMJCE"); //Use server's public key to initiate a DHPublicKeySpec and then use //this DHPublicKeySpec to initiate a publicKey object BigInteger publicKey = new BigInteger (1, sourcePublicKey); DHPublicKeySpec dhKeySpec = new DHPublicKeySpec (publicKey, modulus__, base__); PublicKey pubKey = keyFac.generatePublic (dhKeySpec); //Execute the first phase of DH keyagreement protocal. keyAgreement_.doPhase (pubKey, true); //generate the shared secret key. The application requestor's shared secret //key should be exactly the same as the application server's shared secret //key byte[] sharedSecret = keyAgreement_.generateSecret(); byte[] newKey = new byte[32]; //We adjust the length here. If the length of secret key is 33 and the first byte is 0, //we trim off the frist byte. If the length of secret key is less than 32, we will //pad 0 to the beginning of the byte array tho make the secret key 32 bytes. if (sharedSecret.length == 33 && sharedSecret[0] == 0) { for (int i=0; i<newKey.length; i++) newKey[i] = sharedSecret[i+1]; } if (sharedSecret.length < 32) { int i; for (i=0; i<(32 - sharedSecret.length); i++) newKey[i] = 0; for (int j=i; j<sharedSecret.length; j++) newKey[j] = sharedSecret[j-i]; } //The Data Encryption Standard (DES) is going to be used to encrypt userid //and password. DES is a block cipher; it encrypts data in 64-bit blocks. //DRDA encryption uses DES CBC mode as defined by the FIPS standard //DES CBC requires an encryption key and an 8 byte token to encrypt the data. //The middle 8 bytes of Diffie-Hellman shared private key is used as the //encryption key. The following code retrieves middle 8 bytes of the shared //private key. byte[] key = new byte[8]; //if secret key is not 32, we will use the adjust length secret key if (sharedSecret.length==32) { for (int i=0; i< 8;i++) key[i] = sharedSecret[i+12]; } else if (sharedSecret.length==33 || sharedSecret.length < 32) { for (int i=0; i< 8;i++) key[i] = newKey[i+12]; } else throw new SQLException ("sharedSecret key length error " + sharedSecret.length); // make parity bit right, even number of 1's byte temp; int changeParity; for (int i=0; i<8; i++) { temp = key[i]; changeParity = 1; for (int j=0; j<8; j++) { if (temp < 0) changeParity = 1 - changeParity; temp = (byte) (temp << 1); } if (changeParity == 1) { if ((key[i] & 1) != 0) key[i] &= 0xfe; else key[i] |= 1; } } //use this encryption key to initiate a SecretKeySpec object SecretKeySpec desKey = new SecretKeySpec (key, "DES"); //We use DES in CBC mode because this is the mode used in DRDA. The //encryption mode has to be consistent for encryption and decryption. //CBC mode requires an initialization vector(IV) parameter. In CBC mode //we need to initialize the Cipher object with an IV, which can be supplied // using the javax.crypto.spec.IvParameterSpec class. Cipher cipher= Cipher.getInstance ("DES/CBC/PKCS5Padding", "IBMJCE"); //generate a IVParameterSpec object and use it to initiate the //Cipher object. IvParameterSpec ivParam = new IvParameterSpec (token); //initiate the Cipher using encryption mode, encryption key and the //IV parameter. cipher.init (javax.crypto.Cipher.DECRYPT_MODE, desKey,ivParam); //Execute the final phase of encryption plainText = cipher.doFinal (cipherText); } catch (java.security.NoSuchProviderException e) { throw new SQLException ("java.security.NoSuchProviderException is caught " + "when encrypting data '" + e.getMessage() + "'"); } catch (java.security.NoSuchAlgorithmException e) { throw new SQLException ("java.security.NoSuchAlgorithmException is caught " + "when encrypting data '" + e.getMessage() + "'"); } catch (java.security.spec.InvalidKeySpecException e) { throw new SQLException ("java.security.InvalidKeySpecException is caught " + "when encrypting data"); } catch (java.security.InvalidKeyException e) { throw new SQLException ("java.security.InvalidKeyException is caught " + "when encrypting data '" + e.getMessage() + "'"); } catch (javax.crypto.NoSuchPaddingException e) { throw new SQLException ("javax.crypto.NoSuchPaddingException is caught " + "when encrypting data '" + e.getMessage() + "'"); } catch (javax.crypto.BadPaddingException e) { throw new SQLException ("javax.crypto.BadPaddingException is caught " + "when encrypting data '" + e.getMessage() + "'"); } catch (java.security.InvalidAlgorithmParameterException e) { throw new SQLException ("java.security.InvalidAlgorithmParameterException is caught " + "when encrypting data '" + e.getMessage() + "'"); } catch (javax.crypto.IllegalBlockSizeException e) { throw new SQLException ("javax.crypto.IllegalBlockSizeException is caught " + "when encrypting data '" + e.getMessage() + "'"); } return plainText; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -