SecureCRT 密码破解(JAVA 版)

适用版本:

  SecureCRT 7.3.3 之后的版本 - Password V2 算法

参考文章:

  1. how-does-SecureCRT-encrypt-password
  2. 内网常用工具密码
  3. AES-256-CBC加密
  4. Java实现SHA256算法

 全部代码:


import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Random;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

public class SecureCRTPwdDecrypt {
	
	// 初始向量
	private static final byte[] IV = {
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
	};

	// 如果未设置配置密码,则密钥为SHA256的空字符串摘要
	private static final byte[] KEY = AES256.autoKey(AES256.getSHA256Str(""));

	// 如果设置配置密码,则密钥为
//	private static byte[] passphrase = {
//		(byte) 0xe3, (byte) 0xb0, (byte) 0xc4, 0x42, (byte) 0x98, (byte) 0xfc, 0x1c, 0x14, 
//	    (byte) 0x9a, (byte) 0xfb, (byte) 0xf4, (byte) 0xc8, (byte) 0x99, 0x6f, (byte) 0xb9, 0x24, 
//	    0x27, (byte) 0xae, 0x41, (byte) 0xe4, 0x64, (byte) 0x9b, (byte) 0x93, 0x4c, 
//	    (byte) 0xa4, (byte) 0x95, (byte) 0x99, 0x1b, 0x78, 0x52, (byte) 0xb8, 0x55
//	};

    public static void main(String[] args) throws Exception {
    	String plainText = "1234567";
    	String encHexStr = passwordV2EnDecrytion(plainText);
    	System.out.println(encHexStr.toLowerCase());

    	String passwd = passwordV2Decrytion(encHexStr);
    	System.out.println(passwd);
    }
    
	private static String passwordV2Decrytion(String encDataStr) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
		// 1. 16进制字符串转成 byte[]
    	byte[] encData = AES256.hexStringToBytes(encDataStr);
    	// 2. 解密
    	byte[] decData = AES256.AES_cbc_decrypt(encData, KEY, IV);
    	// 3. 取出前四个字节,转换成 int 类型,获取实际字节长度
    	int length = AES256.bytesToInt(decData);
    	// 4. 取出密码
    	byte[] passwdData = new byte[length];
    	System.arraycopy(decData, 4, passwdData, 0, length);
    	// 5. 转成字符串
    	String passwd = new String(passwdData, "UTF-8");
    	return passwd;
	}
	
	private static String passwordV2EnDecrytion(String plainText) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
		// 1. 转成字节数组
    	byte[] plainBytes = plainText.getBytes("UTF-8");
    	// 2. 获取字节数组长度
    	int length = plainBytes.length;
    	byte[] lengthBytes = AES256.intToBytes(length);
    	// 3. 把长度放到字节数组前
    	byte[] lengthPasswdBytes = new byte[length + 4];
    	System.arraycopy(lengthBytes, 0, lengthPasswdBytes, 0, 4);
    	System.arraycopy(plainBytes, 0, lengthPasswdBytes, 4, plainBytes.length);
    	// 4. 后面加上 原始明文的.digest()
    	byte[] plainTextDigest = AES256.getSHA256(plainBytes);
    	byte[] lengthPasswdDigestBytes = new byte[lengthPasswdBytes.length + plainTextDigest.length];
    	System.arraycopy(lengthPasswdBytes, 0, lengthPasswdDigestBytes, 0, lengthPasswdBytes.length);
    	System.arraycopy(plainTextDigest, 0, lengthPasswdDigestBytes, lengthPasswdBytes.length, plainTextDigest.length);
    	// 5. 后面加上 随机的,并且与前面的数组组成长度为16的倍数的字节数组
    	byte[] randomBytes = buildRandomBytes(16 - lengthPasswdDigestBytes.length % 16);
    	byte[] allBytes = new byte[lengthPasswdDigestBytes.length + randomBytes.length];
    	System.arraycopy(lengthPasswdDigestBytes, 0, allBytes, 0, lengthPasswdDigestBytes.length);
    	System.arraycopy(randomBytes, 0, allBytes, lengthPasswdDigestBytes.length, randomBytes.length);
    	// 6. 加密
    	byte[] encData = AES256.AES_cbc_encrypt(allBytes, KEY, IV);
    	// 7. 转成16进制字符串
    	String encHexStr = AES256.bytesToHex(encData);
    	return encHexStr;
	}
	
	private static byte[] buildRandomBytes(int length) {
	      Random rd = new Random();
	      byte[] arr = new byte[length];
	      rd.nextBytes(arr);
	      return arr;
	}
	
}

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AES256 {

    static {
        /*AES 加密默认128位的key,这里改成256位的(类在下面粘出来了)*/
        UnlimitedKeyStrengthJurisdictionPolicy.ensure();
    }

    /*加密算法*/
    private static final String ALGORITHM = "AES/CBC/NoPadding";

    /**
     *
     * @param srcData 要加密的数组(String 需要base64 编码)
     * @param key 公钥,32位byte数组
     * @param iv 私钥,16位byte数组
     * @return 加密后的byte数组
     * @throws Exception 找不到加密算法等
     */
    public static byte[] AES_cbc_encrypt(byte[] srcData, byte[] key, byte[] iv) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        Cipher.getMaxAllowedKeyLength(ALGORITHM);
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv));
        return cipher.doFinal(srcData);
    }

    /**
     *
     * @param encData 要解密的数组
     * @param key 公钥
     * @param iv 私钥
     * @return 解密后的byte数组
     * @throws Exception 找不到解密算法等
     */
    public static byte[] AES_cbc_decrypt(byte[] encData, byte[] key, byte[] iv) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        Cipher.getMaxAllowedKeyLength(ALGORITHM);
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv));
        return cipher.doFinal(encData);
    }
    
    //长度不够处理
    public static byte[] autoKey(byte[] key){
        byte[] bytes = new byte[32];
        for (int i =0;i<32;i++){
            bytes[i]=0;
        }
        if (key.length>=32){
            System.arraycopy(key,0,bytes,0,32);
        }else {
            System.arraycopy(key,0,bytes,0,key.length);
        }
        return bytes;
    }
    //256加密
    public static byte[] getSHA256Str(String str){
        byte[] encdeStr = null;
        try {
        	encdeStr = getSHA256(str.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return encdeStr;
    }
    //256加密
    public static byte[] getSHA256(byte[] bytes){
        MessageDigest messageDigest;
        byte[] encdeStr = null;
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            encdeStr = messageDigest.digest(bytes);
            //encdeStr = Hex.encodeHexString(hash);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return encdeStr;
    }

	public static byte[] hexStringToBytes(String hexString) {
		if (hexString == null || hexString.equals("")) {
			return null;
		}
		hexString = hexString.toUpperCase();
		int length = hexString.length() / 2;
		char[] hexChars = hexString.toCharArray();
		byte[] d = new byte[length];
		for (int i = 0; i < length; i++) {
			int pos = i * 2;
			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));

		}
		return d;
	}

	private static byte charToByte(char c) {
		return (byte) "0123456789ABCDEF".indexOf(c);
	}
	
    public static byte[] intToBytes(int a){
        byte[] ans=new byte[4];
        for(int i=0;i<4;i++)
            ans[i]=(byte)(a>>(i*8));
        return ans;
    }

    public static int bytesToInt(byte[] a){
        int ans=0;
        for(int i=0;i<4;i++){
            ans<<=8;
            ans|=(a[3-i]&0xff);
        }
        return ans;
    }

	public static String bytesToHex(byte[] bytes) {
		StringBuffer sb = new StringBuffer();
		if (bytes != null && bytes.length > 0) {
			for (int i = 0; i < bytes.length; i++) {
				String hex = byteToHex(bytes[i]);
				sb.append(hex);
			}
		}
		return sb.toString();
	}

	public static String byteToHex(byte b) {
		String hexString = Integer.toHexString(b & 0xFF);
		// 由于十六进制是由0~9、A~F来表示1~16,所以如果Byte转换成Hex后如果是<16,就会是一个字符(比如A=10),通常是使用两个字符来表示16进制位的,
		// 假如一个字符的话,遇到字符串11,这到底是1个字节,还是1和1两个字节,容易混淆,如果是补0,那么1和1补充后就是0101,11就表示纯粹的11
		if (hexString.length() < 2) {
			hexString = new StringBuilder(String.valueOf(0)).append(hexString).toString();
		}
		return hexString.toUpperCase();
	}
}

import javax.crypto.Cipher;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.NoSuchAlgorithmException;
import java.security.Permission;
import java.security.PermissionCollection;
import java.util.Map;

// https://stackoverflow.com/questions/1179672/how-to-avoid-installing-unlimited-strength-jce-policy-files-when-deploying-an
public class UnlimitedKeyStrengthJurisdictionPolicy {

    private static boolean isRestrictedCryptography() throws NoSuchAlgorithmException {
        return Cipher.getMaxAllowedKeyLength("AES/ECB/NoPadding") <= 128;
    }

    private static void removeCryptographyRestrictions() {
        try {
            if (!isRestrictedCryptography()) {
//                System.out.println("Cryptography restrictions removal not needed");
                return;
            }
            /*
             * Do the following, but with reflection to bypass access checks:
             *
             * JceSecurity.isRestricted = false;
             * JceSecurity.defaultPolicy.perms.clear();
             * JceSecurity.defaultPolicy.add(CryptoAllPermission.INSTANCE);
             */
            Class<?> jceSecurity = Class.forName("javax.crypto.JceSecurity");
            Class<?> cryptoPermissions = Class.forName("javax.crypto.CryptoPermissions");
            Class<?> cryptoAllPermission = Class.forName("javax.crypto.CryptoAllPermission");

            Field isRestrictedField = jceSecurity.getDeclaredField("isRestricted");
            isRestrictedField.setAccessible(true);
            Field modifiersField = Field.class.getDeclaredField("modifiers");
            modifiersField.setAccessible(true);
            modifiersField.setInt(isRestrictedField, isRestrictedField.getModifiers() & ~Modifier.FINAL);
            isRestrictedField.set(null, false);

            Field defaultPolicyField = jceSecurity.getDeclaredField("defaultPolicy");
            defaultPolicyField.setAccessible(true);
            PermissionCollection defaultPolicy = (PermissionCollection) defaultPolicyField.get(null);

            Field perms = cryptoPermissions.getDeclaredField("perms");
            perms.setAccessible(true);
            ((Map<?, ?>) perms.get(defaultPolicy)).clear();

            Field instance = cryptoAllPermission.getDeclaredField("INSTANCE");
            instance.setAccessible(true);
            defaultPolicy.add((Permission) instance.get(null));

            System.out.println("Successfully removed cryptography restrictions");
        } catch (Exception e) {
            System.out.println("Failed to remove cryptography restrictions" + e);
        }
    }

    static {
        removeCryptographyRestrictions();
    }

    public static void ensure() {
        // just force loading of this class
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值