MD5加密,判断文件是否被篡改,解码与编码,16进制与2进制的转换

加密算法:步骤

1 用每个byte去和11111111做与运算并且得到的是int类型的值: 

          byte & 11111111;

2、把int 类型转成 16进制并返回String类型;

3、不满八个二进制位就补全;

public static void main(String[] args) throws NoSuchAlgorithmException {
        //得到一个信息摘要器
        MessageDigest digest = MessageDigest.getInstance("md5");
        String password = "123456";//密码
        byte [] result = digest.digest(password.getBytes());//这里也可以传读取的一个文件的字节数组
        StringBuffer buffer  = new StringBuffer();
        //把每一个 字节 & 0xff
        for(byte b : result){
            int nuber =  b & 0xff;
            String str = Integer.toHexString(nuber);//转换为16进制的字符串
            if(str.length()==1){
                buffer.append("0");//如果该字符串只有一位数就在前面补0
            }
            buffer.append(str);
        }
        //这就是MD5加密得到的值,如果想更难破解可以拿这个值再加密
        System.out.println(buffer);
    }

与保存的加密密码判断是否一致时,将用户输入的密码加密再比较就是

网站在线验证算法是否正确  www.cmd5.com

还可以校验文件的md5 sha1签名.

上面代码中也可以读取一个文件,然后将读取出来的字符串转换成字节数组,然后通过 byte [] result = digest.digest("字节数组");方法......获取这个文件的MD5码,文件名修改了MD5码是不会变的,但是如果文件的内容变化了.得到的MD5码就不同了(加了空格都会不同)

这也是判断文件是否被别人篡改的标示

/**
     * 获取文件的MD5值,path为文件的全路径
     * 获取文件的特征信息
     */
    public String getFileMD5(String path){
        try {
            File file=new File(path);
            FileInputStream fis=new FileInputStream(file);
            byte[] byffer = new byte[1024];
            int len=-1;
            MessageDigest digest = MessageDigest.getInstance("md5");
            while((len=fis.read(byffer))!=-1){
                digest.update(byffer,0,len);
            }
            byte[] result=digest.digest();
            StringBuffer sb=new StringBuffer();
            for (byte b : result) {
                int number=b & 0xff;//加盐
                String str = Integer.toHexString(number);
                if(str.length() == 1){
                    sb.append("0");
                }
                sb.append(str);
            }
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } 
        return null;
    }

1.编码和解码
  1.编码的概念
    用一种统一的公认的规则来将数据进行统一的编排。(1对1)
    如ascall编码中
    A ---- 65
  编码的方式:
    1.BASE64(A-Z,a-z,0-9,+,/)

    2.URL编码

base64编码与解码

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Base64;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class Base64Activity extends AppCompatActivity {
    private EditText mEditText;
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_base64);
        initView();
    }

    private void initView() {
        mEditText = (EditText) findViewById(R.id.et_base64_input);
        mTextView = (TextView) findViewById(R.id.tv_base64_show);
    }

    public void onClick(View view) {
        if (view!=null){
            switch (view.getId()){
                case R.id.bt_base64_encode:
                    // 获取输入框的内容
                     String content = mEditText.getText().toString().trim();
                    // 判空
                    if (TextUtils.isEmpty(content)){
                        Toast.makeText(Base64Activity.this, "您还没有输入需要编码的内容", Toast.LENGTH_SHORT).show();
                        return;
                    }

                    // 编码
                    byte[] encode = Base64.encode(content.getBytes(), Base64.DEFAULT);
                    // 设置到控件上
                    mTextView.setText(new String(encode));
                    break;
                case R.id.bt_base64_decode:
                    // 获取TextView上已经编码的内容
                    String decodeString = mTextView.getText().toString().trim();

                    // 判空
                    if (TextUtils.isEmpty(decodeString)){
                        Toast.makeText(Base64Activity.this, "您还没有编码过", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    // 解码
                     byte[] decode = Base64.decode(decodeString.getBytes(), Base64.DEFAULT);
                    // 把结果再设置到TextView上。
                    mTextView.setText(new String(decode));


                    break;
                default:
                    break;

            }
        }
    }
}
View Code

Url编码与解码,好多网址就是使用这种编码

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

public class UrlActivity extends AppCompatActivity {
    private EditText mEditText;
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_url);
        initView();
        // UrlEncode URLDecode 一般使用在服务器和客户端 传递中文参数的时候,一般会把参数通过UrlEncode 防止客户端
        // 传递过来的中文参数出现乱码的情况
    }

    private void initView() {
        mEditText = (EditText) findViewById(R.id.et_url_input);
        mTextView = (TextView) findViewById(R.id.tv_url_show);
    }

    public void onClick(View view) {
        if (view!=null){
            switch (view.getId()){
                case R.id.bt_url_encode:
                    String content = mEditText.getText().toString().trim();
                    if (TextUtils.isEmpty(content)){
                        Toast.makeText(UrlActivity.this, "您还没有输入任何需要编码的内容", Toast.LENGTH_SHORT).show();
                         return;
                    }
                    try {
                        String encode = URLEncoder.encode(content, "UTF-8");
                        mTextView.setText(encode);
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    break;
                case R.id.bt_url_decode:
                    String decodeContent = mTextView.getText().toString().trim();
                    if (TextUtils.isEmpty(decodeContent)){
                        Toast.makeText(UrlActivity.this, "您还没有进行过编码", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    try {
                        String decode = URLDecoder.decode(decodeContent, "UTF-8");
                        mTextView.setText(decode);
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }

                    break;
                default:
                    break;
            }
        }
    }
}
View Code

2.加密和解密

  1.对称加密(DES-->3DES-->AES)
    概念:加密和解密用的是同一个密钥
    特点:强度较低,只要丢失加密或者解密用到的密钥,那么信息就会出现安全隐患
  2.非对称加密(RSA)
    概念:加密和解密用的不同的密钥
    特点:密码强度较高
  3.信息摘要(MD5,SHA)
    概念:用它来做验证数据的完整性的。

对称加密与解密:

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

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

public class DesActivity extends AppCompatActivity {
    private EditText mEditTextPassword;
    private EditText mEditTextContent;
    private TextView mTextViewResult;
    private TextView mTextViewDecode;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_des);
        initView();
        // DES 加密解密密码的长度必须是八位(8 个byte)
    }

    private void initView() {
        mEditTextContent = (EditText) findViewById(R.id.et_des_content);
        mEditTextPassword = (EditText) findViewById(R.id.et_des_password);
        mTextViewDecode = (TextView) findViewById(R.id.tv_des_decode);
        mTextViewResult = (TextView) findViewById(R.id.tv_des_result);
    }

    public void onClick(View view) {
        if (view!=null){
            switch (view.getId()){
                case R.id.bt_des_encode:
                    // 获取控件上的值
                    // DES 加密解密密码的长度必须是八位(8 个byte)
                     String password = mEditTextPassword.getText().toString().trim();
                     String content = mEditTextContent.getText().toString().trim();
                    //判空
                    if (TextUtils.isEmpty(password)||TextUtils.isEmpty(content)){
                        Toast.makeText(DesActivity.this, "请完善信息", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    // 加密
                    // 初始化加密引擎
                    try {
                        Cipher cipher = Cipher.getInstance("DES");
                        //初始化加密的key
                        SecretKeySpec spec = new SecretKeySpec(password.getBytes(),"DES");
                        // 初始化加密引擎
                        cipher.init(Cipher.ENCRYPT_MODE,spec);
                        // 加密
                         byte[] bytes = cipher.doFinal(content.getBytes());
                        // 经过base64处理
                        Log.d("TAG", "onClick:  bytes == "+new String(bytes));
                         byte[] encode = Base64.encode(bytes, Base64.DEFAULT);
                        // 设置给控件
                        mTextViewResult.setText(new String(encode));
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    } catch (NoSuchPaddingException e) {
                        e.printStackTrace();
                    } catch (InvalidKeyException e) {
                        e.printStackTrace();
                    } catch (BadPaddingException e) {
                        e.printStackTrace();
                    } catch (IllegalBlockSizeException e) {
                        e.printStackTrace();
                    }
                    //设置值到控件上

                    break;
                case R.id.bt_des_decode:
                     String result = mTextViewResult.getText().toString().trim();
                     String passwordes = mEditTextPassword.getText().toString().trim();
                    if (TextUtils.isEmpty(result)||TextUtils.isEmpty(passwordes)){
                        Toast.makeText(DesActivity.this, "请完善信息", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    try {
                        // 初始化加密引擎
                        Cipher cipher = Cipher.getInstance("DES");
                        // 初始化key
                        // DES 加密解密密码的长度必须是八位(8 个byte)
                        SecretKeySpec keySpec = new SecretKeySpec(passwordes.getBytes(),"DES");
                        cipher.init(Cipher.DECRYPT_MODE, keySpec);
                        // 因为在我们加密后 经过了Base64处理了(Encode) ,所以 加密必须经过base64处理回来(decode)
                        byte[] bytes = result.getBytes();
                        byte[] decode = Base64.decode(bytes, Base64.DEFAULT);
                         byte[] contentes = cipher.doFinal(decode);
                         mTextViewDecode.setText(new String(contentes));
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    } catch (NoSuchPaddingException e) {
                        e.printStackTrace();
                    } catch (InvalidKeyException e) {
                        e.printStackTrace();
                    } catch (BadPaddingException e) {
                        e.printStackTrace();
                    } catch (IllegalBlockSizeException e) {
                        e.printStackTrace();
                    }
                    break;
                default:
                    break;
            }
        }
    }
}
View Code
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Base64;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

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

public class AESActivity extends AppCompatActivity {
    private EditText mEditTextPassword;
    private EditText mEditTextContent;
    private TextView mTextViewDecode;
    private TextView mTextViewResult;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_aes);
        initView();
        // 密码长度必须是16byte 或者24 或者32 一个字符两个字节
    }

    private void initView() {
        mEditTextContent = (EditText) findViewById(R.id.et_aes_content);
        mEditTextPassword = (EditText) findViewById(R.id.et_aes_password);

        mTextViewResult = (TextView) findViewById(R.id.tv_aes_result);
        mTextViewDecode = (TextView) findViewById(R.id.tv_aes_decode);


    }
    public void onClick(View view) {
        try {
       if (view!=null){
           switch (view.getId()){
               case R.id.bt_aes_encode:
                   // 获取控件值
                    String content = mEditTextContent.getText().toString().trim();
                    // 密码长度必须是16byte 或者24 或者32
                    String password= mEditTextPassword.getText().toString().trim();
                   //判空
                   if (TextUtils.isEmpty(content)||TextUtils.isEmpty(password)){
                       Toast.makeText(AESActivity.this, "请完善信息", Toast.LENGTH_SHORT).show();
                       return;
                   }
                   // 加密
                       Cipher cipher = Cipher.getInstance("AES");
                       SecretKeySpec key = new SecretKeySpec(password.getBytes(),"AES");
                       cipher.init(Cipher.ENCRYPT_MODE, key);
                       byte[] bytes = cipher.doFinal(content.getBytes());
                       byte[] encode = Base64.encode(bytes, Base64.DEFAULT);
                       mTextViewResult.setText(new String(encode));


                   // 设置值到控件上
                   break;
               case R.id.bt_aes_decode:
                   // 获取控件值
                   final String result = mTextViewResult.getText().toString().trim();
                   // 密码长度必须是16byte 或者24 或者32
                   final String passwordes = mEditTextPassword.getText().toString().trim();
                   //判空
                   if (TextUtils.isEmpty(result)||TextUtils.isEmpty(passwordes)){
                       Toast.makeText(AESActivity.this, "请完善内容", Toast.LENGTH_SHORT).show();
                       return;
                   }
                   // 解密
                   Cipher cipherTwo = Cipher.getInstance("AES");
                   SecretKeySpec keySpec = new SecretKeySpec(passwordes.getBytes(),"AES");
                   cipherTwo.init(Cipher.DECRYPT_MODE, keySpec);
                   byte[] decode = Base64.decode(result.getBytes(), Base64.DEFAULT);
                   final byte[] decodeResult = cipherTwo.doFinal(decode);
                   mTextViewDecode.setText(new String(decodeResult));
                   // 设置值到控件上
                   break;
               default:
                   break;

           }

       }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }
    }
}
View Code

非对称:

import android.content.Context;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.security.InvalidKeyException;
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.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;

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

public class RSAActvitiy extends AppCompatActivity {
    private EditText mEditText;
    private TextView mTextViewResult;
    private TextView mTextViewDecode;
    private PrivateKey mPrivateKey;
    private PublicKey mPublicKey;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rsaactvitiy);
        initView();
        initData();
    }

    private void initData() {
        try {
            // 初始化RSA密码对
            KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
            // 设置密码对的长度,随机生成的密码对,每次生成都不会相同
            generator.initialize(1024);
            //生成密码对
            KeyPair keyPair = generator.generateKeyPair();
            //获取私钥
            mPrivateKey = keyPair.getPrivate();
            //获取公钥
            mPublicKey = keyPair.getPublic();

            // 把服务器的私钥存入共享参数
            SharedPreferences sp = getSharedPreferences("1605", Context.MODE_PRIVATE);
            SharedPreferences.Editor edit = sp.edit();
            // 获取私钥的byte数组
            final byte[] privateKeyEncoded = mPrivateKey.getEncoded();
            //因为我们要存起来,然后在读出来,所以得经过Base64处理
            byte[] encodePrivate = Base64.encode(privateKeyEncoded, Base64.DEFAULT);
            edit.putString("privateKey",new String(encodePrivate));
            edit.commit();


            // 把 私钥和公钥转化成String
             byte[] encoded = mPublicKey.getEncoded();
             byte[] encode = Base64.encode(encoded, Base64.DEFAULT);
            byte[] encodedp = mPrivateKey.getEncoded();
            byte[] encodep = Base64.encode(encodedp, Base64.DEFAULT);
            Log.d("TAG", "initData:  priateKey == "+new String(encode)+"    publicKey ==  "+new String(encodep));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    private void initView() {
        mEditText = (EditText) findViewById(R.id.et_rsa_content);
        mTextViewDecode = (TextView) findViewById(R.id.tv_rsa_decode);
        mTextViewResult = (TextView) findViewById(R.id.tv_rsa_result);
    }

    public void onClick(View view) {
        if (view!=null){
            switch (view.getId()) {
                case R.id.bt_rsa_encode:
                    // 获取需要加密的内容
                    String content = mEditText.getText().toString().trim();
                    //判空
                    if(TextUtils.isEmpty(content)){
                        Toast.makeText(RSAActvitiy.this, "请输入您要加密的内容", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    // 初始化加密
                    try {
                        Cipher cipher = Cipher.getInstance("RSA");
                        cipher.init(Cipher.ENCRYPT_MODE, mPublicKey);
                        byte[] bytes = cipher.doFinal(content.getBytes());
                        byte[] encode = Base64.encode(bytes, Base64.DEFAULT);
                        mTextViewResult.setText(new String(encode));
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    } catch (NoSuchPaddingException e) {
                        e.printStackTrace();
                    } catch (InvalidKeyException e) {
                        e.printStackTrace();
                    } catch (BadPaddingException e) {
                        e.printStackTrace();
                    } catch (IllegalBlockSizeException e) {
                        e.printStackTrace();
                    }

                    //设置数据
                    break;
                case R.id.bt_rsa_decode:
                    try {
                        String result = mTextViewResult.getText().toString().trim();
                        if (TextUtils.isEmpty(result)){
                            Toast.makeText(RSAActvitiy.this, "您还没有进行加密", Toast.LENGTH_SHORT).show();
                            return;
                        }
                        Cipher ciphers = Cipher.getInstance("RSA");
                        ciphers.init(Cipher.DECRYPT_MODE, mPrivateKey);
                        byte[] decode = Base64.decode(result.getBytes(), Base64.DEFAULT);
                        byte[] bytes = ciphers.doFinal(decode);
                        mTextViewDecode.setText(new String(bytes));
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    } catch (NoSuchPaddingException e) {
                        e.printStackTrace();
                    } catch (InvalidKeyException e) {
                        e.printStackTrace();
                    } catch (BadPaddingException e) {
                        e.printStackTrace();
                    } catch (IllegalBlockSizeException e) {
                        e.printStackTrace();
                    }


                    break;
                case R.id.bt_rsa_sp:
                    // 拿到sp里面私钥传话成的String
                    final SharedPreferences sp = getSharedPreferences("1605", Context.MODE_PRIVATE);
                     String privateKeyStr = sp.getString("privateKey", "");
                    if (TextUtils.isEmpty(privateKeyStr)){
                        Toast.makeText(RSAActvitiy.this, "您还没有存入私钥", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    // 把String 传话成私钥
                    byte[] priKeyBytes = Base64.decode(privateKeyStr, Base64.DEFAULT);
                    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(priKeyBytes);
                    try {
                        KeyFactory factory = KeyFactory.getInstance("RSA");
                        PrivateKey privateKey = factory.generatePrivate(keySpec);
                        // 解密公钥加密后的内容
                        Cipher cipher = Cipher.getInstance("RSA");
                        cipher.init(Cipher.DECRYPT_MODE, privateKey);
                        String encodeContent = mTextViewResult.getText().toString().trim();
                        if (TextUtils.isEmpty(encodeContent)){
                            Toast.makeText(RSAActvitiy.this, "您还没有进行加密,请不要解密", Toast.LENGTH_SHORT).show();
                            return;
                        }

                        byte[] bytes = cipher.doFinal(Base64.decode(encodeContent, Base64.DEFAULT));
                        mTextViewDecode.setText(new String(bytes));

                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    } catch (InvalidKeySpecException e) {
                        e.printStackTrace();
                    } catch (NoSuchPaddingException e) {
                        e.printStackTrace();
                    } catch (InvalidKeyException e) {
                        e.printStackTrace();
                    } catch (BadPaddingException e) {
                        e.printStackTrace();
                    } catch (IllegalBlockSizeException e) {
                        e.printStackTrace();
                    }
                    // 解密
                    break;
                default:
                    break;
            }
        }

    }
}
View Code

SHA:判断是否篡改

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Sha1Activity extends AppCompatActivity {
    private EditText mEditText;
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sha1);
        initView();
    }

    private void initView() {
        mEditText = (EditText) findViewById(R.id.et_sha1_input);
        mTextView = (TextView) findViewById(R.id.tv_sha1_result);
    }
    //7c4a8d09ca3762af61e59520943dc26494f8941b
    //e10adc3949ba59abbe56e057f20f883e
    public void onClick(View view) {
        if (view!=null){
            try {
                String content = mEditText.getText().toString().trim();
                if (TextUtils.isEmpty(content)){
                    Toast.makeText(Sha1Activity.this, "请您输入您要摘要的内容", Toast.LENGTH_SHORT).show();
                    return;
                }
                MessageDigest digest = MessageDigest.getInstance("SHA1");

                digest.update(content.getBytes());

                final byte[] resultBytes = digest.digest();
                StringBuffer buffer = new StringBuffer();
                for (int i = 0; i < resultBytes.length; i++) {
                    String index = Integer.toHexString(resultBytes[i] & 0xff);
                    if (index.length()==1){
                        buffer.append("0");
                    }
                    buffer.append(index);
                }
                Log.d("TAG", "onClick: " +buffer.toString());
                mTextView.setText(buffer.toString());

            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        }
    }
}
View Code

 

字节转16进制字符串与16进制字符串转字节数组:

/**
     * 将二进制转换成16进制
     *
     * @param buf
     * @return
     */
    public static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 将16进制转换为二进制
     *
     * @param hexStr
     * @return
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

解密规则:

1.数据都用AES加密与解密(动态的,每次客户端生成)

2.将AES的秘钥使用RSA加密,然后提交给服务器

3.RSA的公钥与私钥由服务器生成(写死的,我们保存到代码中就行)

AES工具类如下:

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * AES的加密与解密
 */
public class AESUtil {

    /**
     * AES加密字符串
     * 
     * @param content
     *            需要被加密的字符串
     * @param key
     *            秘钥
     * @return 密文
     */
    public static byte[] encrypt(String content, byte[] key) {
        try {

            Cipher cipher = Cipher.getInstance("AES");// 创建密码器

            byte[] byteContent = content.getBytes("utf-8");

            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));// 初始化为加密模式的密码器

            byte[] result = cipher.doFinal(byteContent);// 加密

            return result;

        }
        catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
        catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解密AES加密过的字符串
     * 
     * @param content
     *            AES加密过过的内容
     * @param key
     *            秘钥
     * @return 明文
     */
    public static byte[] decrypt(byte[] content, byte[] key) {
        try {

            Cipher cipher = Cipher.getInstance("AES");// 创建密码器
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"));// 初始化为解密模式的密码器
            byte[] result = cipher.doFinal(content);
            return result; // 明文

        }
        catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
        catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 生成一个AES密钥对象
     * 
     * @return
     */
    public static SecretKeySpec generateKey() {
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            kgen.init(128, new SecureRandom());
            SecretKey secretKey = kgen.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
            return key;
        }
        catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 生成一个AES密钥
     * @return
     */
    public static byte[] generateKey2byte() {
        return generateKey().getEncoded();
    }


}

RSA工具类:

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

/**
 * RSA工具类
 */
public class RSAUtil {

    /**
     * 定义加密方式
     */
    protected final static String KEY_RSA = "RSA";

    /**
     * 定义签名算法
     */
    protected final static String KEY_RSA_SIGNATURE = "MD5withRSA";


    /**
     * RSA的私钥
     */
    protected final static String PRIVATEKEY = "30820276020100300D06092A864886F70D0101010500048202603082025C0201000281810089EBFDC41DE5968A586DD7B91F808E163BCF1A0F427D206A3B80D9D761A09444120229747F59433488CAAA0A99D0F3AF9DE03720251E0BDFF68B28E1C106DD66B7B4C7B7EEE7D2AA2B686695F975621876B33EE4B4641CDDC0B14FBDA96C722D9397D2E8AD74A46AC98B82A8A41F6D9527B3D8DEFB2A60D5A642E4709CFFB2150203010001028181008113A11D27B5B45BA942B37F8761F298104554682F9B96F894D3940C244BFA36727C1F7BEDAB0660661CF562926DA1821BC8B90E966E3642D6238A912CEB55CBE972129393667ED2D97718DBEBA6256394E3700A40202C1568E292E50EB0EAC3E0B838F56AF6F6C118E22EF5B18DB4104A07630CC7F383283B821B0568F82641024100C87B0E203F316D0D73348AA4448F60E87FC9BAEABD23DD33E5E55223706B9267216B5381181A84911FC6EA6A90A6BED10881FE7C8491612B39138FBD33A2B0AD024100B01DDE551696F55AC56F17E4B2E0C64DB6F4B6DD93116AC199959B26999416B553B2212B256846665B7E864310DC70913122A7DAE674C1AD2FD3DEF0FC08EC0902402723F7370E7F5CD62266E0A67F882A9859D28DBEA49CAAE425FF26912AB2A5CBA2B7AC7EE8B0CCAEF4B04635F5F5C80D5186E7A371D25C512EFC85B49FAF24A5024035F8B14DFA2241069442BB5BC6C5C37FC575B124AE11445A182B14E4FB63BAA1CF0863C9C928EF8A26B7DB856A01642DDA94F843C92436C65045E9A8885463A10240762C26ED98A3B0F07A6E5E38E3C23A59C6BD1F3CFDF4DD4545CDF5FE5191DD90CAAD8922447E6F65CE33E2040C9A2638EC2C54B9D6DBBC16974653E89BC520C8";

    /**
     * RSA的公钥
     */
    public final static String PUBLICKEY = "30819F300D06092A864886F70D010101050003818D003081890281810089EBFDC41DE5968A586DD7B91F808E163BCF1A0F427D206A3B80D9D761A09444120229747F59433488CAAA0A99D0F3AF9DE03720251E0BDFF68B28E1C106DD66B7B4C7B7EEE7D2AA2B686695F975621876B33EE4B4641CDDC0B14FBDA96C722D9397D2E8AD74A46AC98B82A8A41F6D9527B3D8DEFB2A60D5A642E4709CFFB2150203010001";


    /**
     * 用私钥对信息生成数字签名
     * 
     * @param data
     *            加密数据
     * @param privateKey
     *            私钥
     * @return
     */
    public static String sign(byte[] data, String privateKey) {
        String str = "";
        try {
            // 解密16进制的二进制数的私钥
            byte[] bytes = EncryptUtil.parseHexStr2Byte(privateKey);
            // 构造PKCS8EncodedKeySpec对象
            PKCS8EncodedKeySpec pkcs = new PKCS8EncodedKeySpec(bytes);
            // 指定的加密算法
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            // 取私钥对象
            PrivateKey key = factory.generatePrivate(pkcs);
            // 用私钥对信息生成数字签名
            Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE);
            signature.initSign(key);
            signature.update(data);
            str = EncryptUtil.parseByte2HexStr(signature.sign());
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }

    /**
     * 校验数字签名
     * 
     * @param data
     *            加密数据
     * @param publicKey
     *            公钥
     * @param sign
     *            数字签名
     * @return 校验成功返回true,失败返回false
     */
    public static boolean verify(byte[] data, String publicKey, String sign) {
        boolean flag = false;
        try {
            // 解密16进制的二进制数的私钥
            byte[] bytes = EncryptUtil.parseHexStr2Byte(publicKey);
            // 构造X509EncodedKeySpec对象
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
            // 指定的加密算法
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            // 取公钥对象
            PublicKey key = factory.generatePublic(keySpec);
            // 用公钥验证数字签名
            Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE);
            signature.initVerify(key);
            signature.update(data);
            flag = signature.verify(EncryptUtil.parseHexStr2Byte(sign));
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 私钥解密
     * 
     * @param data
     *            加密数据
     * @param key
     *            私钥
     * @return
     */
    public static byte[] decryptByPrivateKey(byte[] data, String key) {
        byte[] result = null;
        try {
            // 对私钥解密
            byte[] bytes = EncryptUtil.parseHexStr2Byte(key);
            // 取得私钥
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PrivateKey privateKey = factory.generatePrivate(keySpec);
            // 对数据解密
            Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            result = cipher.doFinal(data);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 私钥加密
     *
     * @param data
     *            待加密数据
     * @param key
     *            私钥
     * @return
     */
    public static byte[] encryptByPrivateKey(byte[] data, String key) {
        byte[] result = null;
        try {
            byte[] bytes = EncryptUtil.parseHexStr2Byte(key);
            // 取得私钥
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PrivateKey privateKey = factory.generatePrivate(keySpec);
            // 对数据加密
            Cipher cipher = Cipher.getInstance(factory.getAlgorithm());//注意客户端(Linux)与服务端(Wendows)的区别
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            result = cipher.doFinal(data);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 公钥解密
     * 
     * @param data
     *            加密数据
     * @param key
     *            公钥
     * @return
     */
    public static byte[] decryptByPublicKey(byte[] data, String key) {
        byte[] result = null;
        try {
            // 对公钥解密
            byte[] bytes = EncryptUtil.parseHexStr2Byte(key);
            // 取得公钥
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PublicKey publicKey = factory.generatePublic(keySpec);
            // 对数据解密   由于服务器与安卓底层不同  使用factory.getAlgorithm()解密失败
            Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            result = cipher.doFinal(data);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 公钥加密
     * 
     * @param data
     *            待加密数据
     * @param key
     *            公钥
     * @return
     */
    public static byte[] encryptByPublicKey(byte[] data, String key) {
        byte[] result = null;
        try {
            byte[] bytes = EncryptUtil.parseHexStr2Byte(key);
            // 取得公钥
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PublicKey publicKey = factory.generatePublic(keySpec);
            // 对数据加密  注意点:
            Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            result = cipher.doFinal(data);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


}

解密工具类:

/**
 * 解密工具类
 */
public class EncryptUtil {

    /**
     * 解密  对二进制的解密
     * @param aeskey
     *            AES通过RSA加密后的秘钥
     * @param content
     *            AES加密的密文
     */
    public static byte[] aesAndRsaDecrypt(byte[] aeskey, byte[] content) {
        // 1.使用RSA私钥解密接收到的AES秘钥密文
        byte[] aeskey1 = RSAUtil.decryptByPrivateKey(aeskey, RSAUtil.PUBLICKEY);
        // 2.再使用解密到的AES秘钥对接收到的数据进行解密
        return AESUtil.decrypt(content, aeskey1);
    }

    /**
     * 解密  对字符串类型的
     * @param aeskey
     *            AES通过RSA加密后的秘钥
     * @param content
     *            AES加密的密文
     * @throws Exception
     */
    public static byte[] aesAndRsaDecrypt(String aeskey, String content){
        return aesAndRsaDecrypt(EncryptUtil.parseHexStr2Byte(aeskey), EncryptUtil.parseHexStr2Byte(content));
    }

    /**
     * 获取使用AES加密后的内容
     * @param content
     * @return
     */
    public static String getEncryptContext(byte[] content,byte[] aes_key){
        // 1.AES秘钥加密需要传输的数据
        byte[] byte_context = AESUtil.decrypt(content, aes_key);
        return EncryptUtil.parseByte2HexStr(byte_context);
    }


    /**
     * 将二进制转换成16进制
     *
     * @param buf
     * @return
     */
    public static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 将16进制转换为二进制
     *
     * @param hexStr
     * @return
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }


}

使用RSA在自己本地能解密与加密,自己加密后到服务器解密失败的原因 可参考:http://blog.csdn.net/libraryhu/article/details/50821791

使用如下:

//加密的处理,RSA加密AES钥匙,再用AES加密内容
        //生成AES秘钥
        byte[] aeskey = AESUtil.generateKey2byte();
        //RSA加密AES的秘钥
        byte[] aeskeyToRsa = RSAUtil.encryptByPublicKey(aeskey, RSAUtil.PUBLICKEY);
        OkHttpUtils
                .get()
                .url(login)
                .addParams("key", EncryptUtil.parseByte2HexStr(aeskeyToRsa))//将加了密的AES秘钥给服务器
                //用户名与密码的加密
                .addParams("username", AESUtil.encrypt2String(username, aeskey))//再用AES加密内容
                .addParams("password", AESUtil.encrypt2String(password, aeskey))
                .addParams("loginType", "E")
                .build()

android RSA和Java RSA加密不一致的坑

 

byte[]转String 与 String转byte[], 避免数据丢失的正确转换方式:

 

private final static byte[] aesKey = Base64.decode("SWp6DMurpjXYlR5oJf1F4q89OzHmE3Xo/iMqUfFY1H0=",Base64.DEFAULT);

new String(aesKey,"ISO-8859-1")

new String(aesKey,"ISO-8859-1").getBytes("ISO-8859-1")

Base64.encodeToString(new String(aesKey,"ISO-8859-1").getBytes("ISO-8859-1"),Base64.DEFAULT)

 

也就是需要通过ISO-8859-1 来转换

 

posted @ 2016-08-13 17:07  ts-android  阅读(2096)  评论(0编辑  收藏  举报