精华内容
下载资源
问答
  • 这几天一直做安全登录,网上查了好多资料,不尽如意。具体实现思路如下:1。服务端生成公钥与私钥,保存。...这其中有一个关键是解决服务端的公钥,传入客户端,客户端用此公钥加密字符串后,后又能在服务...

    这几天一直做安全登录,网上查了好多资料,不尽如意。

    具体实现思路如下:

    1。服务端生成公钥与私钥,保存。

    2。客户端在请求到登录页面后,随机生成一字符串。

    3。后此随机字符串作为密钥加密密码,再用从服务端获取到的公钥加密生成的随机字符串。

    4。将此两段密文传入服务端,服务端用私钥解出随机字符串,再用此私钥解出加密的密文。

    这其中有一个关键是解决服务端的公钥,传入客户端,客户端用此公钥加密字符串后,后又能在服务端用私钥解出。

    此文即为实现此步而作。

    加密算法为RSA:

    1。服务端的RSA  java实现。

    Java代码 6788554fe9bcd82795ef9839d3f317b0.gif c491770d13cdcbfc9be5bb9b128dd65d.png

    1d4715fb3e5b109ea94009c98d36f8e8.gif

    /**

    *

    */

    packagecom.sunsoft.struts.util;

    importjava.io.ByteArrayOutputStream;

    importjava.io.FileInputStream;

    importjava.io.FileOutputStream;

    importjava.io.ObjectInputStream;

    importjava.io.ObjectOutputStream;

    importjava.math.BigInteger;

    importjava.security.KeyFactory;

    importjava.security.KeyPair;

    importjava.security.KeyPairGenerator;

    importjava.security.NoSuchAlgorithmException;

    importjava.security.PrivateKey;

    importjava.security.PublicKey;

    importjava.security.SecureRandom;

    importjava.security.interfaces.RSAPrivateKey;

    importjava.security.interfaces.RSAPublicKey;

    importjava.security.spec.InvalidKeySpecException;

    importjava.security.spec.RSAPrivateKeySpec;

    importjava.security.spec.RSAPublicKeySpec;

    importjavax.crypto.Cipher;

    /**

    * RSA 工具类。提供加密,解密,生成密钥对等方法。

    * 需要到http://www.bouncycastle.org下载bcprov-jdk14-123.jar。

    *

    */

    publicclassRSAUtil {

    /**

    * * 生成密钥对 *

    *

    * @return KeyPair *

    * @throws EncryptException

    */

    publicstaticKeyPair generateKeyPair()throwsException {

    try{

    KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",

    neworg.bouncycastle.jce.provider.BouncyCastleProvider());

    finalintKEY_SIZE =1024;// 没什么好说的了,这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低

    keyPairGen.initialize(KEY_SIZE,newSecureRandom());

    KeyPair keyPair = keyPairGen.generateKeyPair();

    saveKeyPair(keyPair);

    returnkeyPair;

    }catch(Exception e) {

    thrownewException(e.getMessage());

    }

    }

    publicstaticKeyPair getKeyPair()throwsException{

    FileInputStream fis =newFileInputStream("C:/RSAKey.txt");

    ObjectInputStream oos =newObjectInputStream(fis);

    KeyPair kp= (KeyPair) oos.readObject();

    oos.close();

    fis.close();

    returnkp;

    }

    publicstaticvoidsaveKeyPair(KeyPair kp)throwsException{

    FileOutputStream fos =newFileOutputStream("C:/RSAKey.txt");

    ObjectOutputStream oos =newObjectOutputStream(fos);

    //生成密钥

    oos.writeObject(kp);

    oos.close();

    fos.close();

    }

    /**

    * * 生成公钥 *

    *

    * @param modulus *

    * @param publicExponent *

    * @return RSAPublicKey *

    * @throws Exception

    */

    publicstaticRSAPublicKey generateRSAPublicKey(byte[] modulus,

    byte[] publicExponent)throwsException {

    KeyFactory keyFac =null;

    try{

    keyFac = KeyFactory.getInstance("RSA",

    neworg.bouncycastle.jce.provider.BouncyCastleProvider());

    }catch(NoSuchAlgorithmException ex) {

    thrownewException(ex.getMessage());

    }

    RSAPublicKeySpec pubKeySpec =newRSAPublicKeySpec(newBigInteger(

    modulus),newBigInteger(publicExponent));

    try{

    return(RSAPublicKey) keyFac.generatePublic(pubKeySpec);

    }catch(InvalidKeySpecException ex) {

    thrownewException(ex.getMessage());

    }

    }

    /**

    * * 生成私钥 *

    *

    * @param modulus *

    * @param privateExponent *

    * @return RSAPrivateKey *

    * @throws Exception

    */

    publicstaticRSAPrivateKey generateRSAPrivateKey(byte[] modulus,

    byte[] privateExponent)throwsException {

    KeyFactory keyFac =null;

    try{

    keyFac = KeyFactory.getInstance("RSA",

    neworg.bouncycastle.jce.provider.BouncyCastleProvider());

    }catch(NoSuchAlgorithmException ex) {

    thrownewException(ex.getMessage());

    }

    RSAPrivateKeySpec priKeySpec =newRSAPrivateKeySpec(newBigInteger(

    modulus),newBigInteger(privateExponent));

    try{

    return(RSAPrivateKey) keyFac.generatePrivate(priKeySpec);

    }catch(InvalidKeySpecException ex) {

    thrownewException(ex.getMessage());

    }

    }

    /**

    * * 加密 *

    *

    * @param key

    *            加密的密钥 *

    * @param data

    *            待加密的明文数据 *

    * @return 加密后的数据 *

    * @throws Exception

    */

    publicstaticbyte[] encrypt(PublicKey pk,byte[] data)throwsException {

    try{

    Cipher cipher = Cipher.getInstance("RSA",

    neworg.bouncycastle.jce.provider.BouncyCastleProvider());

    cipher.init(Cipher.ENCRYPT_MODE, pk);

    intblockSize = cipher.getBlockSize();// 获得加密块大小,如:加密前数据为128个byte,而key_size=1024

    // 加密块大小为127

    // byte,加密后为128个byte;因此共有2个加密块,第一个127

    // byte第二个为1个byte

    intoutputSize = cipher.getOutputSize(data.length);// 获得加密块加密后块大小

    intleavedSize = data.length % blockSize;

    intblocksSize = leavedSize !=0? data.length / blockSize +1

    : data.length / blockSize;

    byte[] raw =newbyte[outputSize * blocksSize];

    inti =0;

    while(data.length - i * blockSize >0) {

    if(data.length - i * blockSize > blockSize)

    cipher.doFinal(data, i * blockSize, blockSize, raw, i

    * outputSize);

    else

    cipher.doFinal(data, i * blockSize, data.length - i

    * blockSize, raw, i * outputSize);

    // 这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到

    // ByteArrayOutputStream中,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了

    // OutputSize所以只好用dofinal方法。

    i++;

    }

    returnraw;

    }catch(Exception e) {

    thrownewException(e.getMessage());

    }

    }

    /**

    * * 解密 *

    *

    * @param key

    *            解密的密钥 *

    * @param raw

    *            已经加密的数据 *

    * @return 解密后的明文 *

    * @throws Exception

    */

    publicstaticbyte[] decrypt(PrivateKey pk,byte[] raw)throwsException {

    try{

    Cipher cipher = Cipher.getInstance("RSA",

    neworg.bouncycastle.jce.provider.BouncyCastleProvider());

    cipher.init(cipher.DECRYPT_MODE, pk);

    intblockSize = cipher.getBlockSize();

    ByteArrayOutputStream bout =newByteArrayOutputStream(64);

    intj =0;

    while(raw.length - j * blockSize >0) {

    bout.write(cipher.doFinal(raw, j * blockSize, blockSize));

    j++;

    }

    returnbout.toByteArray();

    }catch(Exception e) {

    thrownewException(e.getMessage());

    }

    }

    /**

    * * *

    *

    * @param args *

    * @throws Exception

    */

    publicstaticvoidmain(String[] args)throwsException {

    RSAPublicKey rsap = (RSAPublicKey) RSAUtil.generateKeyPair().getPublic();

    String test ="hello world";

    byte[] en_test = encrypt(getKeyPair().getPublic(),test.getBytes());

    byte[] de_test = decrypt(getKeyPair().getPrivate(),en_test);

    System.out.println(newString(de_test));

    }

    }

    /**

    *

    */

    package com.sunsoft.struts.util;

    import java.io.ByteArrayOutputStream;

    import java.io.FileInputStream;

    import java.io.FileOutputStream;

    import java.io.ObjectInputStream;

    import java.io.ObjectOutputStream;

    import java.math.BigInteger;

    import java.security.KeyFactory;

    import java.security.KeyPair;

    import java.security.KeyPairGenerator;

    import java.security.NoSuchAlgorithmException;

    import java.security.PrivateKey;

    import java.security.PublicKey;

    import java.security.SecureRandom;

    import java.security.interfaces.RSAPrivateKey;

    import java.security.interfaces.RSAPublicKey;

    import java.security.spec.InvalidKeySpecException;

    import java.security.spec.RSAPrivateKeySpec;

    import java.security.spec.RSAPublicKeySpec;

    import javax.crypto.Cipher;

    /**

    * RSA 工具类。提供加密,解密,生成密钥对等方法。

    * 需要到http://www.bouncycastle.org下载bcprov-jdk14-123.jar。

    *

    */

    public class RSAUtil {

    /**

    * * 生成密钥对 *

    *

    * @return KeyPair *

    * @throws EncryptException

    */

    public static KeyPair generateKeyPair() throws Exception {

    try {

    KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",

    new org.bouncycastle.jce.provider.BouncyCastleProvider());

    final int KEY_SIZE = 1024;// 没什么好说的了,这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低

    keyPairGen.initialize(KEY_SIZE, new SecureRandom());

    KeyPair keyPair = keyPairGen.generateKeyPair();

    saveKeyPair(keyPair);

    return keyPair;

    } catch (Exception e) {

    throw new Exception(e.getMessage());

    }

    }

    public static KeyPair getKeyPair()throws Exception{

    FileInputStream fis = new FileInputStream("C:/RSAKey.txt");

    ObjectInputStream oos = new ObjectInputStream(fis);

    KeyPair kp= (KeyPair) oos.readObject();

    oos.close();

    fis.close();

    return kp;

    }

    public static void saveKeyPair(KeyPair kp)throws Exception{

    FileOutputStream fos = new FileOutputStream("C:/RSAKey.txt");

    ObjectOutputStream oos = new ObjectOutputStream(fos);

    //生成密钥

    oos.writeObject(kp);

    oos.close();

    fos.close();

    }

    /**

    * * 生成公钥 *

    *

    * @param modulus *

    * @param publicExponent *

    * @return RSAPublicKey *

    * @throws Exception

    */

    public static RSAPublicKey generateRSAPublicKey(byte[] modulus,

    byte[] publicExponent) throws Exception {

    KeyFactory keyFac = null;

    try {

    keyFac = KeyFactory.getInstance("RSA",

    new org.bouncycastle.jce.provider.BouncyCastleProvider());

    } catch (NoSuchAlgorithmException ex) {

    throw new Exception(ex.getMessage());

    }

    RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(

    modulus), new BigInteger(publicExponent));

    try {

    return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);

    } catch (InvalidKeySpecException ex) {

    throw new Exception(ex.getMessage());

    }

    }

    /**

    * * 生成私钥 *

    *

    * @param modulus *

    * @param privateExponent *

    * @return RSAPrivateKey *

    * @throws Exception

    */

    public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus,

    byte[] privateExponent) throws Exception {

    KeyFactory keyFac = null;

    try {

    keyFac = KeyFactory.getInstance("RSA",

    new org.bouncycastle.jce.provider.BouncyCastleProvider());

    } catch (NoSuchAlgorithmException ex) {

    throw new Exception(ex.getMessage());

    }

    RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(

    modulus), new BigInteger(privateExponent));

    try {

    return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);

    } catch (InvalidKeySpecException ex) {

    throw new Exception(ex.getMessage());

    }

    }

    /**

    * * 加密 *

    *

    * @param key

    * 加密的密钥 *

    * @param data

    * 待加密的明文数据 *

    * @return 加密后的数据 *

    * @throws Exception

    */

    public static byte[] encrypt(PublicKey pk, byte[] data) throws Exception {

    try {

    Cipher cipher = Cipher.getInstance("RSA",

    new org.bouncycastle.jce.provider.BouncyCastleProvider());

    cipher.init(Cipher.ENCRYPT_MODE, pk);

    int blockSize = cipher.getBlockSize();// 获得加密块大小,如:加密前数据为128个byte,而key_size=1024

    // 加密块大小为127

    // byte,加密后为128个byte;因此共有2个加密块,第一个127

    // byte第二个为1个byte

    int outputSize = cipher.getOutputSize(data.length);// 获得加密块加密后块大小

    int leavedSize = data.length % blockSize;

    int blocksSize = leavedSize != 0 ? data.length / blockSize + 1

    : data.length / blockSize;

    byte[] raw = new byte[outputSize * blocksSize];

    int i = 0;

    while (data.length - i * blockSize > 0) {

    if (data.length - i * blockSize > blockSize)

    cipher.doFinal(data, i * blockSize, blockSize, raw, i

    * outputSize);

    else

    cipher.doFinal(data, i * blockSize, data.length - i

    * blockSize, raw, i * outputSize);

    // 这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到

    // ByteArrayOutputStream中,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了

    // OutputSize所以只好用dofinal方法。

    i++;

    }

    return raw;

    } catch (Exception e) {

    throw new Exception(e.getMessage());

    }

    }

    /**

    * * 解密 *

    *

    * @param key

    * 解密的密钥 *

    * @param raw

    * 已经加密的数据 *

    * @return 解密后的明文 *

    * @throws Exception

    */

    public static byte[] decrypt(PrivateKey pk, byte[] raw) throws Exception {

    try {

    Cipher cipher = Cipher.getInstance("RSA",

    new org.bouncycastle.jce.provider.BouncyCastleProvider());

    cipher.init(cipher.DECRYPT_MODE, pk);

    int blockSize = cipher.getBlockSize();

    ByteArrayOutputStream bout = new ByteArrayOutputStream(64);

    int j = 0;

    while (raw.length - j * blockSize > 0) {

    bout.write(cipher.doFinal(raw, j * blockSize, blockSize));

    j++;

    }

    return bout.toByteArray();

    } catch (Exception e) {

    throw new Exception(e.getMessage());

    }

    }

    /**

    * * *

    *

    * @param args *

    * @throws Exception

    */

    public static void main(String[] args) throws Exception {

    RSAPublicKey rsap = (RSAPublicKey) RSAUtil.generateKeyPair().getPublic();

    String test = "hello world";

    byte[] en_test = encrypt(getKeyPair().getPublic(),test.getBytes());

    byte[] de_test = decrypt(getKeyPair().getPrivate(),en_test);

    System.out.println(new String(de_test));

    }

    }

    2.测试页面:

    IndexAction.java

    Java代码 6788554fe9bcd82795ef9839d3f317b0.gif c491770d13cdcbfc9be5bb9b128dd65d.png

    1d4715fb3e5b109ea94009c98d36f8e8.gif

    /*

    * Generated by MyEclipse Struts

    * Template path: templates/java/JavaClass.vtl

    */

    packagecom.sunsoft.struts.action;

    importjava.security.interfaces.RSAPrivateKey;

    importjava.security.interfaces.RSAPublicKey;

    importjavax.servlet.http.HttpServletRequest;

    importjavax.servlet.http.HttpServletResponse;

    importorg.apache.struts.action.Action;

    importorg.apache.struts.action.ActionForm;

    importorg.apache.struts.action.ActionForward;

    importorg.apache.struts.action.ActionMapping;

    importcom.sunsoft.struts.util.RSAUtil;

    /**

    * MyEclipse Struts

    * Creation date: 06-28-2008

    *

    * XDoclet definition:

    * @struts.action validate="true"

    */

    publicclassIndexActionextendsAction {

    /*

    * Generated Methods

    */

    /**

    * Method execute

    * @param mapping

    * @param form

    * @param request

    * @param response

    * @return ActionForward

    */

    publicActionForward execute(ActionMapping mapping, ActionForm form,

    HttpServletRequest request, HttpServletResponse response)throwsException {

    RSAPublicKey rsap = (RSAPublicKey) RSAUtil.getKeyPair().getPublic();

    String module = rsap.getModulus().toString(16);

    String empoent = rsap.getPublicExponent().toString(16);

    System.out.println("module");

    System.out.println(module);

    System.out.println("empoent");

    System.out.println(empoent);

    request.setAttribute("m", module);

    request.setAttribute("e", empoent);

    returnmapping.findForward("login");

    }

    }

    /*

    * Generated by MyEclipse Struts

    * Template path: templates/java/JavaClass.vtl

    */

    package com.sunsoft.struts.action;

    import java.security.interfaces.RSAPrivateKey;

    import java.security.interfaces.RSAPublicKey;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

    import org.apache.struts.action.Action;

    import org.apache.struts.action.ActionForm;

    import org.apache.struts.action.ActionForward;

    import org.apache.struts.action.ActionMapping;

    import com.sunsoft.struts.util.RSAUtil;

    /**

    * MyEclipse Struts

    * Creation date: 06-28-2008

    *

    * XDoclet definition:

    * @struts.action validate="true"

    */

    public class IndexAction extends Action {

    /*

    * Generated Methods

    */

    /**

    * Method execute

    * @param mapping

    * @param form

    * @param request

    * @param response

    * @return ActionForward

    */

    public ActionForward execute(ActionMapping mapping, ActionForm form,

    HttpServletRequest request, HttpServletResponse response)throws Exception {

    RSAPublicKey rsap = (RSAPublicKey) RSAUtil.getKeyPair().getPublic();

    String module = rsap.getModulus().toString(16);

    String empoent = rsap.getPublicExponent().toString(16);

    System.out.println("module");

    System.out.println(module);

    System.out.println("empoent");

    System.out.println(empoent);

    request.setAttribute("m", module);

    request.setAttribute("e", empoent);

    return mapping.findForward("login");

    }

    }

    通过此action进入登录页面,并传入公钥的 Modulus 与PublicExponent的hex编码形式。

    3。登录页面 login.jsp

    Html代码 6788554fe9bcd82795ef9839d3f317b0.gif c491770d13cdcbfc9be5bb9b128dd65d.png

    1d4715fb3e5b109ea94009c98d36f8e8.gif

    HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

    login

    function rsalogin()

    {

    bodyRSA();

    varresult=encryptedString(key, document.getElementById("pwd").value);

    //alert(result);

    loginForm.action="login.do?result="+result;

    loginForm.submit();

    }

    var key ;

    function bodyRSA()

    {

    setMaxDigits(130);

    key=newRSAKeyPair("10001","","8c1cd09a04ed01aafe70dc84c5f32ae23a16fe8fc8898aba6797c5a9c708720de4f08dbf086af429fc51c0636208f56de20a8ab5686affd9bdfb643ae1e90d5617155c4867eef06b0884ba8ecd187907c7069ae3eed4f0155eeca6573411864035ae803ad8fd91a0cc479f27e41b19c13465ab30f3cfbfd14de56f49cbd09481");

    }

    Login:Password:login

    function rsalogin()

    {

    bodyRSA();

    var result = encryptedString(key, document.getElementById("pwd").value);

    //alert(result);

    loginForm.action="login.do?result="+result;

    loginForm.submit();

    }

    var key ;

    function bodyRSA()

    {

    setMaxDigits(130);

    key = new RSAKeyPair("10001","","8c1cd09a04ed01aafe70dc84c5f32ae23a16fe8fc8898aba6797c5a9c708720de4f08dbf086af429fc51c0636208f56de20a8ab5686affd9bdfb643ae1e90d5617155c4867eef06b0884ba8ecd187907c7069ae3eed4f0155eeca6573411864035ae803ad8fd91a0cc479f27e41b19c13465ab30f3cfbfd14de56f49cbd09481");

    }

    Login:
    Password:

    3.点击登录后,调用LoginAction.java

    Java代码 6788554fe9bcd82795ef9839d3f317b0.gif c491770d13cdcbfc9be5bb9b128dd65d.png

    1d4715fb3e5b109ea94009c98d36f8e8.gif

    /*

    * Generated by MyEclipse Struts

    * Template path: templates/java/JavaClass.vtl

    */

    packagecom.sunsoft.struts.action;

    importjava.math.BigInteger;

    importjavax.servlet.http.HttpServletRequest;

    importjavax.servlet.http.HttpServletResponse;

    importorg.apache.struts.action.Action;

    importorg.apache.struts.action.ActionForm;

    importorg.apache.struts.action.ActionForward;

    importorg.apache.struts.action.ActionMapping;

    importcom.sunsoft.struts.util.RSAUtil;

    /**

    * MyEclipse Struts

    * Creation date: 06-28-2008

    *

    * XDoclet definition:

    * @struts.action path="/login" name="loginForm" input="/login.jsp" scope="request" validate="true"

    * @struts.action-forward name="error" path="/error.jsp"

    * @struts.action-forward name="success" path="/success.jsp"

    */

    publicclassLoginActionextendsAction {

    /*

    * Generated Methods

    */

    /**

    * Method execute

    * @param mapping

    * @param form

    * @param request

    * @param response

    * @return ActionForward

    */

    publicActionForward execute(ActionMapping mapping, ActionForm form,

    HttpServletRequest request, HttpServletResponse response)throwsException{

    //LoginForm loginForm = (LoginForm) form;

    String result = request.getParameter("result");

    System.out.println("原文加密后为:");

    System.out.println(result);

    byte[] en_result =newBigInteger(result,16).toByteArray();

    System.out.println("转成byte[]"+newString(en_result));

    byte[] de_result = RSAUtil.decrypt(RSAUtil.getKeyPair().getPrivate(),en_result);

    System.out.println("还原密文:");

    System.out.println(newString(de_result));

    StringBuffer sb =newStringBuffer();

    sb.append(newString(de_result));

    System.out.println(sb.reverse().toString());

    returnmapping.findForward("success");

    }

    }

    /*

    * Generated by MyEclipse Struts

    * Template path: templates/java/JavaClass.vtl

    */

    package com.sunsoft.struts.action;

    import java.math.BigInteger;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

    import org.apache.struts.action.Action;

    import org.apache.struts.action.ActionForm;

    import org.apache.struts.action.ActionForward;

    import org.apache.struts.action.ActionMapping;

    import com.sunsoft.struts.util.RSAUtil;

    /**

    * MyEclipse Struts

    * Creation date: 06-28-2008

    *

    * XDoclet definition:

    * @struts.action path="/login" name="loginForm" input="/login.jsp" scope="request" validate="true"

    * @struts.action-forward name="error" path="/error.jsp"

    * @struts.action-forward name="success" path="/success.jsp"

    */

    public class LoginAction extends Action {

    /*

    * Generated Methods

    */

    /**

    * Method execute

    * @param mapping

    * @param form

    * @param request

    * @param response

    * @return ActionForward

    */

    public ActionForward execute(ActionMapping mapping, ActionForm form,

    HttpServletRequest request, HttpServletResponse response) throws Exception{

    //LoginForm loginForm = (LoginForm) form;

    String result = request.getParameter("result");

    System.out.println("原文加密后为:");

    System.out.println(result);

    byte[] en_result = new BigInteger(result, 16).toByteArray();

    System.out.println("转成byte[]"+new String(en_result));

    byte[] de_result = RSAUtil.decrypt(RSAUtil.getKeyPair().getPrivate(),en_result);

    System.out.println("还原密文:");

    System.out.println(new String(de_result));

    StringBuffer sb = new StringBuffer();

    sb.append(new String(de_result));

    System.out.println(sb.reverse().toString());

    return mapping.findForward("success");

    }

    }

    因为发现解出的明文是倒序的,后面就用StringBuffer的reverse()来转换了一下。

    4。login.jsp所调用的js

    展开全文
  • javascript java rsa 加密 解密 数据加密 数据解密
  • login.jsp所调用的javascript,有: RSA.js BigInt.js Barrett.js 博文链接:https://sunxboy.iteye.com/blog/209156
  • /****/packagecom.sunsoft.struts.util;importjava.io.ByteArrayOutputStream;importjava.io.FileInputStream;importjava.io.FileOutputStream;importjava.io.ObjectInputStream;importjava.io.ObjectOutputSt...

    /**

    *

    */

    package com.sunsoft.struts.util;

    import java.io.ByteArrayOutputStream;

    import java.io.FileInputStream;

    import java.io.FileOutputStream;

    import java.io.ObjectInputStream;

    import java.io.ObjectOutputStream;

    import java.math.BigInteger;

    import java.security.KeyFactory;

    import java.security.KeyPair;

    import java.security.KeyPairGenerator;

    import java.security.NoSuchAlgorithmException;

    import java.security.PrivateKey;

    import java.security.PublicKey;

    import java.security.SecureRandom;

    import java.security.interfaces.RSAPrivateKey;

    import java.security.interfaces.RSAPublicKey;

    import java.security.spec.InvalidKeySpecException;

    import java.security.spec.RSAPrivateKeySpec;

    import java.security.spec.RSAPublicKeySpec;

    import javax.crypto.Cipher;

    /**

    * RSA 工具类。提供加密,解密,生成密钥对等方法。

    * 需要到http://www.bouncycastle.org下载bcprov-jdk14-123.jar。

    *

    */

    public class RSAUtil {

    /**

    * * 生成密钥对 *

    *

    * @return KeyPair *

    * @throws EncryptException

    */

    public static KeyPair generateKeyPair() throws Exception {

    try {

    KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",

    new org.bouncycastle.jce.provider.BouncyCastleProvider());

    final int KEY_SIZE = 1024;// 没什么好说的了,这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低

    keyPairGen.initialize(KEY_SIZE, new SecureRandom());

    KeyPair keyPair = keyPairGen.generateKeyPair();

    saveKeyPair(keyPair);

    return keyPair;

    } catch (Exception e) {

    throw new Exception(e.getMessage());

    }

    }

    public static KeyPair getKeyPair()throws Exception{

    FileInputStream fis = new FileInputStream("C:/RSAKey.txt");

    ObjectInputStream oos = new ObjectInputStream(fis);

    KeyPair kp= (KeyPair) oos.readObject();

    oos.close();

    fis.close();

    return kp;

    }

    public static void saveKeyPair(KeyPair kp)throws Exception{

    FileOutputStream fos = new FileOutputStream("C:/RSAKey.txt");

    ObjectOutputStream oos = new ObjectOutputStream(fos);

    //生成密钥

    oos.writeObject(kp);

    oos.close();

    fos.close();

    }

    /**

    * * 生成公钥 *

    *

    * @param modulus *

    * @param publicExponent *

    * @return RSAPublicKey *

    * @throws Exception

    */

    public static RSAPublicKey generateRSAPublicKey(byte[] modulus,

    byte[] publicExponent) throws Exception {

    KeyFactory keyFac = null;

    try {

    keyFac = KeyFactory.getInstance("RSA",

    new org.bouncycastle.jce.provider.BouncyCastleProvider());

    } catch (NoSuchAlgorithmException ex) {

    throw new Exception(ex.getMessage());

    }

    RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(

    modulus), new BigInteger(publicExponent));

    try {

    return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);

    } catch (InvalidKeySpecException ex) {

    throw new Exception(ex.getMessage());

    }

    }

    /**

    * * 生成私钥 *

    *

    * @param modulus *

    * @param privateExponent *

    * @return RSAPrivateKey *

    * @throws Exception

    */

    public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus,

    byte[] privateExponent) throws Exception {

    KeyFactory keyFac = null;

    try {

    keyFac = KeyFactory.getInstance("RSA",

    new org.bouncycastle.jce.provider.BouncyCastleProvider());

    } catch (NoSuchAlgorithmException ex) {

    throw new Exception(ex.getMessage());

    }

    RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(

    modulus), new BigInteger(privateExponent));

    try {

    return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);

    } catch (InvalidKeySpecException ex) {

    throw new Exception(ex.getMessage());

    }

    }

    /**

    * * 加密 *

    *

    * @param key

    *            加密的密钥 *

    * @param data

    *            待加密的明文数据 *

    * @return 加密后的数据 *

    * @throws Exception

    */

    public static byte[] encrypt(PublicKey pk, byte[] data) throws Exception {

    try {

    Cipher cipher = Cipher.getInstance("RSA",

    new org.bouncycastle.jce.provider.BouncyCastleProvider());

    cipher.init(Cipher.ENCRYPT_MODE, pk);

    int blockSize = cipher.getBlockSize();// 获得加密块大小,如:加密前数据为128个byte,而key_size=1024

    // 加密块大小为127

    // byte,加密后为128个byte;因此共有2个加密块,第一个127

    // byte第二个为1个byte

    int outputSize = cipher.getOutputSize(data.length);// 获得加密块加密后块大小

    int leavedSize = data.length % blockSize;

    int blocksSize = leavedSize != 0 ? data.length / blockSize + 1

    : data.length / blockSize;

    byte[] raw = new byte[outputSize * blocksSize];

    int i = 0;

    while (data.length - i * blockSize > 0) {

    if (data.length - i * blockSize > blockSize)

    cipher.doFinal(data, i * blockSize, blockSize, raw, i

    * outputSize);

    else

    cipher.doFinal(data, i * blockSize, data.length - i

    * blockSize, raw, i * outputSize);

    // 这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到

    // ByteArrayOutputStream中,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了

    // OutputSize所以只好用dofinal方法。

    i++;

    }

    return raw;

    } catch (Exception e) {

    throw new Exception(e.getMessage());

    }

    }

    /**

    * * 解密 *

    *

    * @param key

    *            解密的密钥 *

    * @param raw

    *            已经加密的数据 *

    * @return 解密后的明文 *

    * @throws Exception

    */

    public static byte[] decrypt(PrivateKey pk, byte[] raw) throws Exception {

    try {

    Cipher cipher = Cipher.getInstance("RSA",

    new org.bouncycastle.jce.provider.BouncyCastleProvider());

    cipher.init(cipher.DECRYPT_MODE, pk);

    int blockSize = cipher.getBlockSize();

    ByteArrayOutputStream bout = new ByteArrayOutputStream(64);

    int j = 0;

    while (raw.length - j * blockSize > 0) {

    bout.write(cipher.doFinal(raw, j * blockSize, blockSize));

    j++;

    }

    return bout.toByteArray();

    } catch (Exception e) {

    throw new Exception(e.getMessage());

    }

    }

    /**

    * * *

    *

    * @param args *

    * @throws Exception

    */

    public static void main(String[] args) throws Exception {

    RSAPublicKey rsap = (RSAPublicKey) RSAUtil.generateKeyPair().getPublic();

    String test = "hello world";

    byte[] en_test = encrypt(getKeyPair().getPublic(),test.getBytes());

    byte[] de_test = decrypt(getKeyPair().getPrivate(),en_test);

    System.out.println(new String(de_test));

    }

    }

    展开全文
  • 可以用js利用公钥对用户名和密码(加个随机数防止重放)进行加密,只有你的服务器拥有私钥,也就是只有你能解读用户名和密码的信息。 注意在submit前要用js将用户名和密码赋空之类的,要不随着加密有数据一起提交就...

    之所以引入这篇文章,是因为je里有人问到 https 加密用户名和密码的问题,如果仅仅是为了用户名和密码的加密,不一定要用https。
    可以用js利用公钥对用户名和密码(加个随机数防止重放)进行加密,只有你的服务器拥有私钥,也就是只有你能解读用户名和密码的信息。
    注意在submit前要用js将用户名和密码赋空之类的,要不随着加密有数据一起提交就没有意义了。
    以前QQ邮箱就是这么做的。
    原文:http://sunxboy.javaeye.com/blog/209156
    这几天一直做安全登录,网上查了好多资料,不尽如意。
    具体实现思路如下:
    1。服务端生成公钥与私钥,保存。
    2。客户端在请求到登录页面后,随机生成一字符串。
    3。后此随机字符串作为密钥加密密码,再用从服务端获取到的公钥加密生成的随机字符串。
    4。将此两段密文传入服务端,服务端用私钥解出随机字符串,再用此私钥解出加密的密文。
    这其中有一个关键是解决服务端的公钥,传入客户端,客户端用此公钥加密字符串后,后又能在服务端用私钥解出。
    此文即为实现此步而作。
    加密算法为RSA:
    1。服务端的RSA  java实现。
    Java代码
    /**

    */ 
    package com.sunsoft.struts.util; 

    import java.io.ByteArrayOutputStream; 
    import java.io.FileInputStream; 
    import java.io.FileOutputStream; 
    import java.io.ObjectInputStream; 
    import java.io.ObjectOutputStream; 
    import java.math.BigInteger; 
    import java.security.KeyFactory; 
    import java.security.KeyPair; 
    import java.security.KeyPairGenerator; 
    import java.security.NoSuchAlgorithmException; 
    import java.security.PrivateKey; 
    import java.security.PublicKey; 
    import java.security.SecureRandom; 
    import java.security.interfaces.RSAPrivateKey; 
    import java.security.interfaces.RSAPublicKey; 
    import java.security.spec.InvalidKeySpecException; 
    import java.security.spec.RSAPrivateKeySpec; 
    import java.security.spec.RSAPublicKeySpec; 

    import javax.crypto.Cipher; 

     

    /**
    * RSA 工具类。提供加密,解密,生成密钥对等方法。
    * 需要到http://www.bouncycastle.org下载bcprov-jdk14-123.jar。

    */ 
    public class RSAUtil { 
    /**
    * * 生成密钥对 *

    * @return KeyPair *
    * @throws EncryptException
    */ 
    public static KeyPair generateKeyPair() throws Exception { 
    try { 
    KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA", 
    new org.bouncycastle.jce.provider.BouncyCastleProvider()); 
    final int KEY_SIZE = 1024;// 没什么好说的了,这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低 
    keyPairGen.initialize(KEY_SIZE, new SecureRandom()); 
    KeyPair keyPair = keyPairGen.generateKeyPair(); 
    saveKeyPair(keyPair); 
    return keyPair; 
    } catch (Exception e) { 
    throw new Exception(e.getMessage()); 

    public static KeyPair getKeyPair()throws Exception{ 
    FileInputStream fis = new FileInputStream("C:/RSAKey.txt"); 
    ObjectInputStream oos = new ObjectInputStream(fis); 
    KeyPair kp= (KeyPair) oos.readObject(); 
    oos.close(); 
    fis.close(); 
    return kp; 

    public static void saveKeyPair(KeyPair kp)throws Exception{ 

    FileOutputStream fos = new FileOutputStream("C:/RSAKey.txt"); 
    ObjectOutputStream oos = new ObjectOutputStream(fos); 
    //生成密钥 
    oos.writeObject(kp); 
    oos.close(); 
    fos.close(); 

    /**
    * * 生成公钥 *

    * @param modulus *
    * @param publicExponent *
    * @return RSAPublicKey *
    * @throws Exception
    */ 
    public static RSAPublicKey generateRSAPublicKey(byte[] modulus, 
    byte[] publicExponent) throws Exception { 
    KeyFactory keyFac = null; 
    try { 
    keyFac = KeyFactory.getInstance("RSA", 
    new org.bouncycastle.jce.provider.BouncyCastleProvider()); 
    } catch (NoSuchAlgorithmException ex) { 
    throw new Exception(ex.getMessage()); 

    RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger( 
    modulus), new BigInteger(publicExponent)); 
    try { 
    return (RSAPublicKey) keyFac.generatePublic(pubKeySpec); 
    } catch (InvalidKeySpecException ex) { 
    throw new Exception(ex.getMessage()); 

    /**
    * * 生成私钥 *

    * @param modulus *
    * @param privateExponent *
    * @return RSAPrivateKey *
    * @throws Exception
    */ 
    public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus, 
    byte[] privateExponent) throws Exception { 
    KeyFactory keyFac = null; 
    try { 
    keyFac = KeyFactory.getInstance("RSA", 
    new org.bouncycastle.jce.provider.BouncyCastleProvider()); 
    } catch (NoSuchAlgorithmException ex) { 
    throw new Exception(ex.getMessage()); 

    RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger( 
    modulus), new BigInteger(privateExponent)); 
    try { 
    return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec); 
    } catch (InvalidKeySpecException ex) { 
    throw new Exception(ex.getMessage()); 

    /**
    * * 加密 *

    * @param key
    *            加密的密钥 *
    * @param data
    *            待加密的明文数据 *
    * @return 加密后的数据 *
    * @throws Exception
    */ 
    public static byte[] encrypt(PublicKey pk, byte[] data) throws Exception { 
    try { 
    Cipher cipher = Cipher.getInstance("RSA", 
    new org.bouncycastle.jce.provider.BouncyCastleProvider()); 
    cipher.init(Cipher.ENCRYPT_MODE, pk); 
    int blockSize = cipher.getBlockSize();// 获得加密块大小,如:加密前数据为128个byte,而key_size=1024 
    // 加密块大小为127 
    // byte,加密后为128个byte;因此共有2个加密块,第一个127 
    // byte第二个为1个byte 
    int outputSize = cipher.getOutputSize(data.length);// 获得加密块加密后块大小 
    int leavedSize = data.length % blockSize; 
    int blocksSize = leavedSize != 0 ? data.length / blockSize + 1 
    : data.length / blockSize; 
    byte[] raw = new byte[outputSize * blocksSize]; 
    int i = 0; 
    while (data.length - i * blockSize > 0) { 
    if (data.length - i * blockSize > blockSize) 
    cipher.doFinal(data, i * blockSize, blockSize, raw, i 
    * outputSize); 
    else 
    cipher.doFinal(data, i * blockSize, data.length - i 
    * blockSize, raw, i * outputSize); 
    // 这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到 
    // ByteArrayOutputStream中,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了 
    // OutputSize所以只好用dofinal方法。 

    i++; 

    return raw; 
    } catch (Exception e) { 
    throw new Exception(e.getMessage()); 

    /**
    * * 解密 *

    * @param key
    *            解密的密钥 *
    * @param raw
    *            已经加密的数据 *
    * @return 解密后的明文 *
    * @throws Exception
    */ 
    public static byte[] decrypt(PrivateKey pk, byte[] raw) throws Exception { 
    try { 
    Cipher cipher = Cipher.getInstance("RSA", 
    new org.bouncycastle.jce.provider.BouncyCastleProvider()); 
    cipher.init(cipher.DECRYPT_MODE, pk); 
    int blockSize = cipher.getBlockSize(); 
    ByteArrayOutputStream bout = new ByteArrayOutputStream(64); 
    int j = 0; 

    while (raw.length - j * blockSize > 0) { 
    bout.write(cipher.doFinal(raw, j * blockSize, blockSize)); 
    j++; 

    return bout.toByteArray(); 
    } catch (Exception e) { 
    throw new Exception(e.getMessage()); 

    /**
    * * *

    * @param args *
    * @throws Exception
    */ 
    public static void main(String[] args) throws Exception { 
    RSAPublicKey rsap = (RSAPublicKey) RSAUtil.generateKeyPair().getPublic(); 
    String test = "hello world"; 
    byte[] en_test = encrypt(getKeyPair().getPublic(),test.getBytes()); 
    byte[] de_test = decrypt(getKeyPair().getPrivate(),en_test); 
    System.out.println(new String(de_test)); 


    2.测试页面:
    IndexAction.java
    Java代码
    /*
    * Generated by MyEclipse Struts
    * Template path: templates/java/JavaClass.vtl
    */ 
    package com.sunsoft.struts.action; 

    import java.security.interfaces.RSAPrivateKey; 
    import java.security.interfaces.RSAPublicKey; 

    import javax.servlet.http.HttpServletRequest; 
    import javax.servlet.http.HttpServletResponse; 

    import org.apache.struts.action.Action; 
    import org.apache.struts.action.ActionForm; 
    import org.apache.struts.action.ActionForward; 
    import org.apache.struts.action.ActionMapping; 

    import com.sunsoft.struts.util.RSAUtil; 

    /** 
    * MyEclipse Struts
    * Creation date: 06-28-2008

    * XDoclet definition:
    * @struts.action validate="true"
    */ 
    public class IndexAction extends Action { 
    /*
    * Generated Methods
    */ 

    /** 
    * Method execute
    * @param mapping
    * @param form
    * @param request
    * @param response
    * @return ActionForward
    */ 
    public ActionForward execute(ActionMapping mapping, ActionForm form, 
    HttpServletRequest request, HttpServletResponse response)throws Exception { 

    RSAPublicKey rsap = (RSAPublicKey) RSAUtil.getKeyPair().getPublic(); 
    String module = rsap.getModulus().toString(16); 
    String empoent = rsap.getPublicExponent().toString(16); 
    System.out.println("module"); 
    System.out.println(module); 
    System.out.println("empoent"); 
    System.out.println(empoent); 
    request.setAttribute("m", module); 
    request.setAttribute("e", empoent); 
    return mapping.findForward("login"); 


    通过此action进入登录页面,并传入公钥的 Modulus 与PublicExponent的hex编码形式。
    3。登录页面 login.jsp
    Html代码
    <%@ page language="java" pageEncoding="GBK"%> 

    <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %> 
    <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %> 
    <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %> 
    <%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %> 

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
    <html:html lang="true"> 
    <head> 
    <html:base /> 

    <title>login</title> 

    <meta http-equiv="pragma" content="no-cache"> 
    <meta http-equiv="cache-control" content="no-cache"> 
    <meta http-equiv="expires" content="0">     
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 
    <meta http-equiv="description" content="This is my page"> 
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    --> 
    <script type="text/javascript" src="js/RSA.js"></script> 
    <script type="text/javascript" src="js/BigInt.js"></script> 
    <script type="text/javascript" src="js/Barrett.js"></script> 
    <script type="text/javascript"> 
    function rsalogin() 

    bodyRSA(); 
    var result = encryptedString(key, document.getElementById("pwd").value); 
    //alert(result); 
    loginForm.action="login.do?result="+result; 
    loginForm.submit(); 

    var key ; 
    function bodyRSA() 

    setMaxDigits(130); 
    key = new RSAKeyPair("10001","","8c1cd09a04ed01aafe70dc84c5f32ae23a16fe8fc8898aba6797c5a9c708720de4f08dbf086af429fc51c0636208f56de20a8ab5686affd9bdfb643ae1e90d5617155c4867eef06b0884ba8ecd187907c7069ae3eed4f0155eeca6573411864035ae803ad8fd91a0cc479f27e41b19c13465ab30f3cfbfd14de56f49cbd09481");  

    </script> 
    </head> 

    <body > 
    <html:form action="login" method="post" focus="username"> 
    <table border="0"> 
    <tr> 
    <td>Login:</td> 
    <td><html:text property="username" /></td> 
    </tr> 
    <tr> 
    <td>Password:</td> 
    <td><html:password property="password" styleId="pwd"/></td> 
    </tr> 
    <tr> 
    <td colspan="2" align="center"><input type="button" value="SUBMIT" οnclick="rsalogin();"/></td> 
    </tr> 
    </table> 
    </html:form> 
    </body> 
    </html:html> 
    3.点击登录后,调用LoginAction.java
    Java代码
    /*
    * Generated by MyEclipse Struts
    * Template path: templates/java/JavaClass.vtl
    */ 
    package com.sunsoft.struts.action; 

    import java.math.BigInteger; 

    import javax.servlet.http.HttpServletRequest; 
    import javax.servlet.http.HttpServletResponse; 

    import org.apache.struts.action.Action; 
    import org.apache.struts.action.ActionForm; 
    import org.apache.struts.action.ActionForward; 
    import org.apache.struts.action.ActionMapping; 

    import com.sunsoft.struts.util.RSAUtil; 

    /** 
    * MyEclipse Struts
    * Creation date: 06-28-2008

    * XDoclet definition:
    * @struts.action path="/login" name="loginForm" input="/login.jsp" scope="request" validate="true"
    * @struts.action-forward name="error" path="/error.jsp"
    * @struts.action-forward name="success" path="/success.jsp"
    */ 
    public class LoginAction extends Action { 
    /*
    * Generated Methods
    */ 

    /** 
    * Method execute
    * @param mapping
    * @param form
    * @param request
    * @param response
    * @return ActionForward
    */ 
    public ActionForward execute(ActionMapping mapping, ActionForm form, 
    HttpServletRequest request, HttpServletResponse response) throws Exception{ 
    //LoginForm loginForm = (LoginForm) form; 
    String result = request.getParameter("result"); 
    System.out.println("原文加密后为:"); 
    System.out.println(result); 
    byte[] en_result = new BigInteger(result, 16).toByteArray(); 
    System.out.println("转成byte[]"+new String(en_result)); 
    byte[] de_result = RSAUtil.decrypt(RSAUtil.getKeyPair().getPrivate(),en_result); 
    System.out.println("还原密文:"); 

    System.out.println(new String(de_result)); 
    StringBuffer sb = new StringBuffer(); 
    sb.append(new String(de_result)); 
    System.out.println(sb.reverse().toString()); 
    return mapping.findForward("success"); 


    因为发现解出的明文是倒序的,后面就用StringBuffer的reverse()来转换了一下。
    4。login.jsp所调用的js

    原文地址:http://blog.csdn.net/jjm194/article/details/6336856
    展开全文
  • RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。 RSA是被研究得最广泛的公钥算法,从提出到现在已近二十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。RSA的...
    RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。 RSA是被研究得最广泛的公钥算法,从提出到现在已近二十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。RSA的安全性依赖于大数的因子分解,但并没有从理论上证明破译RSA的难度与大数分解难度等价。即RSA的重大缺陷是无法从理论上把握它的保密性能如何,而且密码学界多数人士倾向于因子分解不是NPC问题。RSA的缺点主要有:A)产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次一密。B)分组长度太大,为保证安全性,n 至少也要 600 bits以上,使运算代价很高,尤其是速度较慢,较对称密码算法慢几个数量级;且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。目前,SET(Secure Electronic Transaction)协议中要求CA采用2048比特长的密钥,其他实体使用1024比特的密钥。
      这种算法1978年就出现了,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman。但RSA的安全性一直未能得到理论上的证明。
      RSA的安全性依赖于大数分解。公钥和私钥都是两个大素数( 大于 100个十进制位)的函数。据猜测,从一个密钥和密文推断出明文的难度等同于分解两个大素数的积。

    一.RSA用于安全登录:

    具体实现思路如下:

    1。服务端生成公钥与私钥,保存。

    2。客户端在请求到登录页面后,随机生成一字符串。

    3。后此随机字符串作为密钥加密密码,再用从服务端获取到的公钥加密生成的随机字符串。

    4。将此两段密文传入服务端,服务端用私钥解出随机字符串,再用此私钥解出加密的密文。

    这其中有一个关键是解决服务端的公钥,传入客户端,客户端用此公钥加密字符串后,后又能在服务端用私钥解出。

    二.RSA主要类
    import java.io.ByteArrayOutputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.math.BigInteger;
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.NoSuchAlgorithmException;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.SecureRandom;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.InvalidKeySpecException;
    import java.security.spec.RSAPrivateKeySpec;
    import java.security.spec.RSAPublicKeySpec;

    import javax.crypto.Cipher;

    import com.elibrary.app.util.ConstrtsProperty;
    import com.elibrary.core.ConfigurationManager;

    /**
    * RSA 工具类。提供加密,解密,生成密钥对等方法。
    * 需要到http://www.bouncycastle.org下载bcprov-jdk14-123.jar。
    *
    */
    public class RSAUtil {
    /**
    * * 生成密钥对 *
    *
    * @return KeyPair *
    * @throws EncryptException
    */
    public static KeyPair generateKeyPair() throws Exception {
    try {
    KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",
    new org.bouncycastle.jce.provider.BouncyCastleProvider());
    final int KEY_SIZE = 1024;// 没什么好说的了,这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低
    keyPairGen.initialize(KEY_SIZE, new SecureRandom());
    KeyPair keyPair = keyPairGen.generateKeyPair();
    saveKeyPair(keyPair);
    return keyPair;
    } catch (Exception e) {
    throw new Exception(e.getMessage());
    }
    }

    public static KeyPair getKeyPair() throws Exception {
    String file = "D:/Java/eLibrary/config/RSAKey";//ConfigurationManager.getProperty(ConstrtsProperty.RSAFILE);
    FileInputStream fis = new FileInputStream(file);
    ObjectInputStream oos = new ObjectInputStream(fis);
    KeyPair kp = (KeyPair) oos.readObject();
    oos.close();
    fis.close();
    return kp;
    }

    public static void saveKeyPair(KeyPair kp) throws Exception {
    String file = "D:/Java/eLibrary/config/RSAKey";//ConfigurationManager.getProperty(ConstrtsProperty.DIR);
    FileOutputStream fos = new FileOutputStream(file);
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    // 生成密钥
    oos.writeObject(kp);
    oos.close();
    fos.close();
    }

    /**
    * * 生成公钥 *
    *
    * @param modulus
    * *
    * @param publicExponent
    * *
    * @return RSAPublicKey *
    * @throws Exception
    */
    public static RSAPublicKey generateRSAPublicKey(byte[] modulus,
    byte[] publicExponent) throws Exception {
    KeyFactory keyFac = null;
    try {
    keyFac = KeyFactory.getInstance("RSA",
    new org.bouncycastle.jce.provider.BouncyCastleProvider());
    } catch (NoSuchAlgorithmException ex) {
    throw new Exception(ex.getMessage());
    }

    RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(
    modulus), new BigInteger(publicExponent));
    try {
    return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);
    } catch (InvalidKeySpecException ex) {
    throw new Exception(ex.getMessage());
    }
    }

    /**
    * * 生成私钥 *
    *
    * @param modulus
    * *
    * @param privateExponent
    * *
    * @return RSAPrivateKey *
    * @throws Exception
    */
    public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus,
    byte[] privateExponent) throws Exception {
    KeyFactory keyFac = null;
    try {
    keyFac = KeyFactory.getInstance("RSA",
    new org.bouncycastle.jce.provider.BouncyCastleProvider());
    } catch (NoSuchAlgorithmException ex) {
    throw new Exception(ex.getMessage());
    }

    RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(
    modulus), new BigInteger(privateExponent));
    try {
    return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);
    } catch (InvalidKeySpecException ex) {
    throw new Exception(ex.getMessage());
    }
    }

    /**
    * * 加密 *
    *
    * @param key
    * 加密的密钥 *
    * @param data
    * 待加密的明文数据 *
    * @return 加密后的数据 *
    * @throws Exception
    */
    public static byte[] encrypt(PublicKey pk, byte[] data) throws Exception {
    try {
    Cipher cipher = Cipher.getInstance("RSA",
    new org.bouncycastle.jce.provider.BouncyCastleProvider());
    cipher.init(Cipher.ENCRYPT_MODE, pk);
    int blockSize = cipher.getBlockSize();// 获得加密块大小,如:加密前数据为128个byte,而key_size=1024
    // 加密块大小为127
    // byte,加密后为128个byte;因此共有2个加密块,第一个127
    // byte第二个为1个byte
    int outputSize = cipher.getOutputSize(data.length);// 获得加密块加密后块大小
    int leavedSize = data.length % blockSize;
    int blocksSize = leavedSize != 0 ? data.length / blockSize + 1
    : data.length / blockSize;
    byte[] raw = new byte[outputSize * blocksSize];
    int i = 0;
    while (data.length - i * blockSize > 0) {
    if (data.length - i * blockSize > blockSize)
    cipher.doFinal(data, i * blockSize, blockSize, raw, i
    * outputSize);
    else
    cipher.doFinal(data, i * blockSize, data.length - i
    * blockSize, raw, i * outputSize);
    // 这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到
    // ByteArrayOutputStream中,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了
    // OutputSize所以只好用dofinal方法。

    i++;
    }
    return raw;
    } catch (Exception e) {
    throw new Exception(e.getMessage());
    }
    }

    /**
    * * 解密 *
    *
    * @param key
    * 解密的密钥 *
    * @param raw
    * 已经加密的数据 *
    * @return 解密后的明文 *
    * @throws Exception
    */
    public static byte[] decrypt(PrivateKey pk, byte[] raw) throws Exception {
    try {
    Cipher cipher = Cipher.getInstance("RSA",
    new org.bouncycastle.jce.provider.BouncyCastleProvider());
    cipher.init(cipher.DECRYPT_MODE, pk);
    int blockSize = cipher.getBlockSize();
    ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
    int j = 0;

    while (raw.length - j * blockSize > 0) {
    bout.write(cipher.doFinal(raw, j * blockSize, blockSize));
    j++;
    }
    return bout.toByteArray();
    } catch (Exception e) {
    throw new Exception(e.getMessage());
    }
    }

    /**
    * * *
    *
    * @param args
    * *
    * @throws Exception
    */
    public static void main(String[] args) throws Exception {
    /*RSAPublicKey rsap = (RSAPublicKey) RSAUtil.generateKeyPair()
    .getPublic();
    rsap.getModulus();
    rsap.getPublicExponent();
    String test = "hello world";
    byte[] en_test = encrypt(getKeyPair().getPublic(), test.getBytes());
    byte[] de_test = decrypt(getKeyPair().getPrivate(), en_test);
    System.out.println(new String(de_test));*/

    /*RSAPublicKey pubk = RSAUtil.generateRSAPublicKey("108368048788890560576572359774440094528241439236977435842254047613639902146619552188260903793435066711695213909830538008019609061114995118579433741950108897670960853465900185040198867356782389765444400474968011359678815704914512251924472572119499063342297571073597918012349131762728165202050464377633235643721".getBytes(), "10001".getBytes());
    RSAPrivateKey prik = RSAUtil.generateRSAPrivateKey("108368048788890560576572359774440094528241439236977435842254047613639902146619552188260903793435066711695213909830538008019609061114995118579433741950108897670960853465900185040198867356782389765444400474968011359678815704914512251924472572119499063342297571073597918012349131762728165202050464377633235643721".getBytes(), "247dfc60927b0343ddce035402291f3fa2eb155188a99da7b92a2a7f3e92d9ac2c98e9949adb376ed4e1d2594f874bc28c34b965bde555a9fc08cda3a01730f5b1e7c6aed9022ecd3d8bdda36dbb0b8a50a1d06660eafdd497883d95c683f44be484fdd1782c6c0094ed3a7584e260e663311ed90d4aa0a16b6a4360fcd7cee1".getBytes());
    byte[] en_test = RSAUtil.encrypt(pubk, "abc".getBytes());
    byte[] de_test = RSAUtil.decrypt(prik, en_test);
    System.out.println(new String(de_test));*/

    /*RSAPublicKey rsap = (RSAPublicKey) RSAUtil.generateKeyPair().getPublic();
    System.out.println(rsap.toString());
    System.out.println(rsap.toString());
    System.out.println(rsap.getModulus());
    System.out.println(rsap.getPublicExponent());*/
    }
    }


    二、页面端代码

    <script type="text/javascript" src="js/RSA.js"></script>
    <script type="text/javascript" src="js/BigInt.js"></script>
    <script type="text/javascript" src="js/Barrett.js"></script>

    <script type="text/javascript">
    /* <![CDATA[ */
    var key ;
    function loginformsubmit() {
    bodyRSA();
    var result = encryptedString(key, document.getElementById("tlogin_password").value);
    document.getElementById("login_password").value = result;
    return true;
    }

    function bodyRSA()
    {
    setMaxDigits(130);
    var PublicExponent = "10001";
    var modulus = "9a523bbbfa1fb4b0d6beea7e4ef9484d1aa2bbfbc42091ad9a716c25274dccc20b04b112bb2e959088fa0ded359ccee455c1238b0100f792d11537adfbe0d746ec13a8bb9c9321f8e408910c8afabf7ba89de6c5d500e39fec69a85bd072e5e5ad18d0642d599737ec2532af5ef9f08f63ecaac1941ac3abe1dcbcc49f6dad49";
    key = new RSAKeyPair("10001","","9a523bbbfa1fb4b0d6beea7e4ef9484d1aa2bbfbc42091ad9a716c25274dccc20b04b112bb2e959088fa0ded359ccee455c1238b0100f792d11537adfbe0d746ec13a8bb9c9321f8e408910c8afabf7ba89de6c5d500e39fec69a85bd072e5e5ad18d0642d599737ec2532af5ef9f08f63ecaac1941ac3abe1dcbcc49f6dad49");
    //页面端只需要更改PublicExponent和modulus 的值即可。
    }
    /* ]]> */
    </script>


    三、后台进行解密

    String login_password = request.getParameter("login_password");
    try {
    byte[] en_result;
    byte[] de_result;
    StringBuffer sb;
    en_result = new BigInteger(login_password, 16).toByteArray();
    //System.out.println("RSAUtil.getKeyPair().getPrivate(): " + RSAUtil.getKeyPair().getPrivate());
    de_result = RSAUtil.decrypt(RSAUtil.getKeyPair().getPrivate(), en_result);
    sb = new StringBuffer().append(new String(de_result));
    login_password = sb.reverse().toString();
    } catch (Exception e) {
    //e.printStackTrace();
    log.error("rsa rsa Encryption failed", e);
    }


    四、附上js脚本
    1.Barrett.js
    2.RSA.js
    3.BigInt.js
    展开全文
  • <p>Can I RSA-encrypt in J2ME or J2SE, and decrypt in PHP?</p> <p>I assume RSA is a specification, and has nothing to do with the languages. </div>
  • 现在,很多登陆表单的密码的都采用RSA加密,例如京东中的登陆使用公钥对密码进行加密java使用RSA加密方式实现数据加密解密,需要首先产生私钥和公钥测试代码public static void main(String args[]){try {RSADemo ...
  • 那么我今天就给大家介绍一下如何利用Java编程来实现RSA加密算法。一、RSA加密算法描述RSA加密算法是1978年提出的。经过多年的分析和研究,在众多的公开密钥加密算法中,RSA加密算法最受推崇,它也被推荐为公开密钥...
  • 一个多星期以来,我一直在使用this来实现一个RSA安全的与python服务器的通信。在然而,我一辈子都搞不清所有罐子的进口。在我已经包括了所有的罐子在蹦蹦城堡网站上找到,仍然没有骰子!在我听说他们到处搬家。如果...
  • byte) (b1 & 0x03);byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >... ...
  • 什么是RSA加密算法 RSA是一种典型的非对称性加密算法,具体介绍可参考阮一峰的日志 RSA...对内容进行RSA加密和解密校验的类 import java.security.KeyFactory; import java.security.PrivateKey; import java...
  • 而本人是使用非对称密钥来对数据进行加密的,客户端用公钥加密,服务器用私钥解 密。因此本人就用非对称密钥RSA算法来实施。而本人在最开始的时候,在android平台上与服务端初始化Cipher的时候都是使用一下这种方式...
  • 这是我在此站点上提出的第一个...从本质上来说,我的问题是我希望能够任命某人担任审核员:一个 源 字节阵列(明文进行加密)RSA公钥文件一个“ 目标 ”字节数组,这是我在给定明文和公钥的情况下对自己的密码数据进行...
  • 这里,讲一下RSA算法加解密在C#和Java之间交互的问题,这两天纠结了很久,也...服务器端给客户端提供公钥,已进行数据加密,客户端加密后提数据提交给服务器,服务器用私钥对数据解密,进行验证。这里遇到的主要问题...
  • 转载 http://blog.csdn.net/bbld_/article/details/38777491RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困 难,因此...
  • C#利用xml公钥进行加密Java利用私钥进行解密Java总是无法解密成功在网上找了各种开源的实现xml 转 pem啊pksc1 转 PKSC8 啊不是报超长的错,就是Decryption errorC# 端的代码是不许更改的,只能改java去兼容密钥是...
  • 1. 出错描述:服务RSA解密抛出javax.crypto.BadPaddingException: Decryption error2.出错原因:Android系统使用的...即Android端用Cipher.getInstance("RSA")方法进行加密时,使用的provider是Bouncycastle Sec...
  • 现在,很多登陆表单的密码的都采用RSA加密,例如京东中的登陆使用公钥对密码进行加密java使用RSA加密方式实现数据加密解密,需要首先产生私钥和公钥测试代码public static void main(String args[]){try {RSADemo ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,305
精华内容 522
关键字:

java进行rsa加密

java 订阅