Java实现SSH模式加密

Java实现SSH模式加密的实现原理思路分享给大家。

一、SSH加密原理

SSH是先通过非对称加密告诉服务端一个对称加密口令,然后进行验证用户名和密码的时候,使用双方已经知道的加密口令进行加密和解密,见下图:

解释:SSH中为什么要使用非对称加密,又使用对称加密,到底有什么用处?到底安全不安全?既然后来又使用了对称加密,开始的时候为什么还要用非对称加密?反过来,既然用非对称加密,为什么又要使用对称加密呢?

非对称加密,是为了将客户端产生的256位随机的口令传递到服务端,那么在传递的过程中,使用公钥进行了加密,这样,这个256位的加密口令就很难被网络上进行破解。
对称加密,因为频繁的使用非对称加密是非常浪费性能的,那么SSH就是用了256位长度的口令作为接下来传递用户名密码时的加密口令,其破解的难度,想必大家都知道了,每一位上都有0-9种变化。
这样安全吗,我觉得还是很不错的,具体使用起来也易于让人理解。
二、我的SSH加密原理

①、使用场景

我所开发的项目是大宗期货交易,主要服务于交易所,这也就产生一个需求就是,我们需要控制交易所使用我们软件的周期。也就是说我们的项目留有一个后门,用来控制项目的周期,假如交易所使用软件的周期到了,那么如果他不续费,而项目的代码部署在人家的服务器上,此时我们就很难控制了,但是有了这个后门,到期后会自动停止软件,这样就不担心交易所不给我们钱了。

②、使用方式

我们给交易的项目代码中包含一个后门,该后门通过webservice client发送一个请求到web service。
web service接收到请求后,回给client需要的信息。
在以上这个过程当中,就会产生一个SSH加密的请求方式,请允许我用一个拙劣的图表示一下。

三、我的SSH具体实现

既然要用到webservice,那么就需要建立web service服务,还有web service client。关于这方面,我暂时不想说太多,方式有很多,我在这就不误导大家了。我是通过eclipse搞定的,可参照webservice之间通信 。

接下来,我将介绍代码,但是考虑到篇幅问题,一些不必要的代码我就不贴出来了,关键在于讲解清楚这个原理。

①、service

ExchangeService.java

public byte[] request(String param, String resultType) {
  logger.info("请求参数:" + param);

  // 返回对象
  KeyResult keyResult = new KeyResult();

  try {
    // 先获取公钥
    if (resultType.equals(PUBLIC_KEY_RESULT_TYPE)) {

      Map<String, Object> keyMap = RSACoder.initKey();
      // 产生公钥和私钥
      privateKey = RSACoder.getPrivateKey(keyMap);

      keyResult.setKey(RSACoder.getPublicKey(keyMap));

      logger.info("公钥字符串:" + keyResult.getKey());
      logger.info("私钥字符串:" + privateKey);

    } else if (resultType.equals(ECHOSTR_RESULT_TYPE)) {

      // 设置客户端的口令信息
      byte[] paramByte = new BASE64Decoder().decodeBuffer(param);
      echoStr = new String(RSACoder.decryptByPrivateKey(paramByte, privateKey));

    } else {
      // 通过数据库获取交易所对应的权限信息.
      // 先将请求转换为byte数组,然后再进行解密,最后转换为字符串
      ExchangeInfo info = ExchangeInfo.dao.getInfoByName(new String(CryptUtil.decrypt(
          new BASE64Decoder().decodeBuffer(param), echoStr.getBytes())));

      String result = "";

      // 获取系统启用权限
      if (resultType.equals(PRIVILEGE_RESULT_TYPE)) {
        // 先判断使用权限

        // 在判断使用日期
        // 当前登录用登录时获取登录的当前日期和开始日期进行比较,然后计算还可以使用的日期
        long time = (new Date().getTime() / 1000) - string2DateInt(openday);
        // 换算成天数
        int day = (int) (time / (60 * 60 * 24));
        // 还可以使用的天数
        if (usedays - day > 0) {
          // 可以使用
          result = "1";
        } else {
          // 无法使用
          result = "0";
        }

      }

      keyResult.setResult(CryptUtil.encrypt(result.getBytes(), echoStr.getBytes()));
    }

    return JsonUtil.objectToByte(keyResult);
  } catch (Exception e) {
    logger.error("webservice出错了!!!!");
    logger.error(e.getMessage(), e);
  }

  return null;
}

再赘述一下:

第一个判断语句中的内容就是生成公钥和私钥,并且返回公钥。
第二个判断语句中的内容就是保存client发送的随机字符串,这一步非常关键,随机字符串首先通过公钥进行了加密,这大大加强了加密的深度。
第三个判断语句中的内容就是将client的权限通过随机字符串进行加密。
②、client

ExchangeUtil.java

public static boolean canRunForExchange(String resultType) {
  int i = 1;
  boolean result = false;

  while (true) {
    try {
      // webservice调用类
      ExchangeServiceProxy proxy = new ExchangeServiceProxy();
      BASE64Encoder encoder = new BASE64Encoder();

      // step1.获取service产生的公钥
      KeyResult keyResult = JsonUtil.byteToObject(proxy.request(null, PUBLIC_KEY_RESULT_TYPE),
          KeyResult.class);

      // step2.产生随机字符串,发送到webserivce
      String echoStr = StrUtil.getEchoStrByLength(10);
      byte[] echoByteParam = RSACoder.encryptByPublicKey(echoStr.getBytes(), keyResult.getKey());
      proxy.request(encoder.encode(echoByteParam), ECHOSTR_RESULT_TYPE);

      // step3.加密客户端请求信息,然后发送到webservice
      // 先加密为byte数组,然后转换成字符串
      byte[] results = proxy.request(
          encoder.encode(CryptUtil.encrypt(Constants.client_type.getBytes(), echoStr.getBytes())),
          resultType);
      keyResult = JsonUtil.byteToObject(results, KeyResult.class);

      // step4.通过口令解密服务端返回消息
      String response = new String(CryptUtil.decrypt(keyResult.getResult(), echoStr.getBytes()));
      if (response.equals("1")) {
        result = true;
      }
      break;
    } catch (Exception e) {
      logger.debug("第" + i + "次加载webservice失败");
      i++;
      logger.error(e.getMessage(), e);

      if (i >= 10) {
        break;
      }
    }
  }

  return result;
}

稍作解释:

通过循环主要为了防止网络断开时服务不停的发送请求,最多10次就够了。
主要有四步操作,注释中我想解释的还可以。
③、共享加密解密公共类

CryptUtil.java

package com.honzh.socket.util;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;

public class CryptUtil {
  /**
  * @Title: encrypt
  * @Description: 加密
  * @param data
  * @param key
  * @return
  * @throws Exception
  */
  public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
    key = get8(key);
    Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
    DESKeySpec desKeySpec = new DESKeySpec(key);
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
    SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
    IvParameterSpec iv = new IvParameterSpec(key);
    cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
    return cipher.doFinal(data);
  }

  /**
  * @Title: decrypt
  * @Description: 解密
  * @param data
  * @param key
  * @return
  * @throws Exception
  */
  public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
    key = get8(key);
    Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
    DESKeySpec desKeySpec = new DESKeySpec(key);
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
    SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
    IvParameterSpec iv = new IvParameterSpec(key);
    cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
    return cipher.doFinal(data);
  }

  private static byte[] get8(byte[] key) {
    byte[] key1 = new byte[8];
    for (int i = 0; i < 8; i++) {
      key1[i] = key[i];
    }
    return key1;
  }

  public static String toHexString(byte[] data) {
    String s = "";
    for (int i = 0; i < data.length; i++) {
      s += Integer.toHexString(data[i] & 0xFF)+"-";
    }
    return s;
  }

}

一般情况下,SHA和MD5两种加密就够我们使用了!
至于其他的辅助类我就不多介绍了,网上有很多资源,希望大家可以结合学习。

(0)

相关推荐

  • Java的web开发中SSH框架的协作处理应用笔记

    相信SSH没人不知道了吧,struts2+spring+hibernate,企业开发的"基础"架构,为什么基础标上引号,因为这个基础只是很多人自以为的而已,最基础的是servlet,很多培训机构很多基础都不教,直接上来就三大框架了,SSH不然就SSI,搞得很多人以为JAVAWEB开发就一定要框架,没框架就跟没了手一个样.三大框架没有什么坏处,实用,很多公司都在用,直接上手开发.但毕业以为真的好久没用三大框架了,spring倒是有用,特别是springMVC,感觉用起来比struts2爽

  • java-SSH2实现数据库和界面的分页

    分页应该是在我们开发web应用时经常要做的工作,能够比较简洁的实现数据库和视图层的分页十分重要. 在数据库层利用hibernate进行数据库的分页,将从数据库中查询出的数据封装为javabean:在视图层就可以方便的实现分页. 创建PageBean package com.fishing.common.bean; import java.util.List; @SuppressWarnings("unchecked") public class PageBean { private L

  • Java框架SSH结合Easyui控件实现省市县三级联动示例解析

    Easyui调用数据库实现省市县区三级联动的效果如果下 1.首先要设计数据库,如图所示.一个有4个字段code,note,pycode.code:行政区划代码,note:中文注释,pycode:拼音缩写. 其中code是由6个字段组成.如果是省级最后4位是0000,如果是地级市最后2位是00,其他是县区. 我已经把相关数据库代码上传到我的csdn资源中,需要的同学自行下载. 2.我用的是java.SSH框架结合Easyui控件 3.html代码如下 <tr> <td class=&quo

  • java通过ssh连接服务器执行shell命令详解及实例

    java通过ssh连接服务器执行shell命令详解 java通过ssh连接服务器执行shell命令:JSch 是SSH2的一个纯Java实现.它允许你连接到一个sshd 服务器,使用端口转发,X11转发,文件传输等等.你可以将它的功能集成到你自己的 程序中.同时该项目也提供一个J2ME版本用来在手机上直连SSHD服务器. SSH是Secure Shell的缩写,一种建立在应用层和传输层基础上的安全协议.SSH在连接和传送过程中会加密所有数据,可以用来在不同系统或者服务器之间进行安全连接.SSH提

  • SSH框架网上商城项目第25战之使用java email给用户发送邮件

    当用户购买完商品后,我们应该向用户发送一封邮件,告诉他订单已生成之类的信息,邮箱地址是从用户的基本信息中获取,好了,首先我们来看一下java中发送邮件的方法. 1. java中发送email的方法 在完善这个项目之前,先来回顾一下java中是如何发送邮件的,首先肯定需要发送邮件的jar包:mail.jar,导入到lib目录下,好了,下面我们先写一个普通的java程序来回顾一下java email的知识点: public class SendEmailDemo { public static vo

  • Java实现SSH模式加密

    Java实现SSH模式加密的实现原理思路分享给大家. 一.SSH加密原理 SSH是先通过非对称加密告诉服务端一个对称加密口令,然后进行验证用户名和密码的时候,使用双方已经知道的加密口令进行加密和解密,见下图: 解释:SSH中为什么要使用非对称加密,又使用对称加密,到底有什么用处?到底安全不安全?既然后来又使用了对称加密,开始的时候为什么还要用非对称加密?反过来,既然用非对称加密,为什么又要使用对称加密呢? 非对称加密,是为了将客户端产生的256位随机的口令传递到服务端,那么在传递的过程中,使用公

  • Java 如何实现AES加密

    做360广告的对接需要对密码进行AES加密,下面是点睛平台文档的描述: (AES模式为CBC,加密算法MCRYPT_RIJNDAEL_128)对MD5加密后的密码实现对称加密.秘钥是apiSecret 的前16位,向量是后16位,加密结果为64位数字和小写字母. 用Java实现AES需要依赖Java加密扩展(The Java Cryptography Extension,简称JCE)的支持--主要是在javax下面的一些包.根据描述需要使用的算法为"AES/CBC/NoPadding"

  • Java中的对称加密详解

    目录 常见的对称加密方法 代码案例 byte[] 和16进制字符串相互转换 DES 加密和解密 AES 加密和解密 加密模式 填充模式 使用加密模式和填充模式的案例 总结 采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密. 常见的对称加密方法 DES : Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政

  • Java实现的3des加密解密工具类示例

    本文实例讲述了Java实现的3des加密解密工具类.分享给大家供大家参考,具体如下: package com.gcloud.common; import org.apache.poi.poifs.property.Child; import org.bouncycastle.jce.provider.BouncyCastleProvider; import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; import javax

  • Java实现的DES加密解密工具类实例

    本文实例讲述了Java实现的DES加密解密工具类.分享给大家供大家参考,具体如下: 一个工具类,很常用,不做深入研究了,那来可直接用 DesUtil.java package lsy; import java.security.Key; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; imp

  • Java编程实现非对称加密的方法详解

    本文实例讲述了Java编程实现非对称加密的方法.分享给大家供大家参考,具体如下: 对称加密算法在加密和解密时使用的是同一个秘钥:而非对称加密算法需要两个密钥来进行加密和解密,这两个秘钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥). 是一种 高级的双保险加密方式,一般的实现加密方式有DH密钥交换算法,RSA基于因子分解算法,ElGamal离散对数算法及ECC椭圆曲线加密等. DH加密解密 /** * 非对称加密之:DH加密 * 非对称DH,是安全性基于

  • java 使用策略模式操作JDBC数据库

    java 使用策略模式操作JDBC数据库 1:构造一个操作数据库的工具类,可以获得连接和释放连接 public class DBUtil { private static Connection conn = null; static { //静态初始块 try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/tes

  • Java 四种基本加密算法分析

    Java 四种基本加密算法分析 简单的java加密算法有: BASE64 严格地说,属于编码格式,而非加密算法 MD5(Message Digest algorithm 5,信息摘要算法) SHA(Secure Hash Algorithm,安全散列算法) HMAC(Hash Message Authentication Code,散列消息鉴别码) 1. BASE64 Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045-RFC2049,上面有MIME的

  • Java责任链模式定义与用法分析

    本文实例讲述了Java责任链模式定义与用法.分享给大家供大家参考,具体如下: 使很多对象都有处理请求的机会,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止 责任链模式主要包括以下几个角色 1.处理者:处理者是一个接口,负责规定具体处理者处理用户请求的方法以及具体处理者设置后继处理对象的方法 2.具体处理者:具体处理者是实现处理接口的类的实例,具体处理者通过调用处理接口规定的方法处理用户的请求,既在接到用户的请求后,处理者将调用接

随机推荐