澳门新浦京电子游戏RSA非对称加密简析-java,rsa非对称-java

同样是一道面试答错的问题,面试官问我非对称加密算法中有哪些经典的算法?
当时我愣了一下,因为我把非对称加密与单项散列加密的概念弄混淆了,所以更不用说什么非对称加密算法中有什么经典算法,结果当然也让面试官愣了一下,所以今天就花点时间说说PHP中的信息加密技术

RSA非对称加密简析-java,rsa非对称-java

iOS在安全方面所采用的的加密方式:MD5、BASE64、(AES)对称加密、非对称加密、DES(keychain中使用)

信息加密技术的分类

1 非对称加密算法

1.MD5

单项散列加密技术(不可逆的加密)

属于摘要算法,不是一种加密算法,作用是把任意长的输入字符串变化成固定长的输出串的一种函数

1.1 概述

  1976年,美国学者Dime和Henman为解决信息公开传送和密钥管理问题,提出一种新的密钥交换协议,允许在不安全的媒体上的通讯双方交换信息,安全地达成一致的密钥,这就是“公开密钥系统”。

  与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
 

使用场景:

MD5

string md5 ( string $str [, bool $raw_output = false ] ); //MD5加密,输入任意长度字符串返回一个唯一的32位字符

md5()为单向加密,没有逆向解密算法,但是还是可以对一些常见的字符串通过收集,枚举,碰撞等方法破解;所以为了让其破解起来更麻烦一些,所以我们一般加一点盐值(salt)并双重MD5;

md5(md5($password).'sdva');

sdva就是盐值,该盐值应该是随机的,比如md5常用在密码加密上,所以在注册的时候我会随机生成这个字符串,然后通过上面的方法来双重加密一下;

1.2 加密流程

  如下图所示,甲乙之间使用非对称加密的方式完成了重要信息的安全传输。
  澳门新浦京电子游戏 1
  非对称加密工作过程简要示意图
  1、乙方生成一对密钥(公钥和私钥)并将公钥向其它方公开。
  2、得到该公钥的甲方使用该密钥对机密信息进行加密后再发送给乙方。
  3、乙方再用自己保存的另一把专用密钥(私钥)对加密后的信息进行解密。乙方只能用其专用密钥(私钥)解密由对应的公钥加密后的信息。
  在传输过程中,即使攻击者截获了传输的密文,并得到了乙的公钥,也无法破解密文,因为只有乙的私钥才能解密密文。
  同样,如果乙要回复加密信息给甲,那么需要甲先公布甲的公钥给乙用于加密,甲自己保存甲的私钥用于解密。

(1)登陆、注册密码需要MD5加密下(防止直接看到明文)

Crypt

很少看到有人用这个函数,如果要用的话有可能是用在对称或非对称的算法里面,了解一下既可;

string crypt ( string $str [, string $salt ] ) //第一个为需要加密的字符串,第二个为盐值(就是加密干扰值,如果没有提供,则默认由PHP自动生成);返回散列后的字符串或一个少于 13 字符的字符串,后者为了区别盐值

<?php
$password='testtest.com';
echo crypt($password);
//输出:$1$DZ3.QX2.$CQZ8I.OfeepKYrWp0oG8L1
/*第二个$与第三个$之间的八个字符是由PHP生成的,每刷新一次就变一次
*/
echo "<hr>";

echo crypt($password,"testtest");
//输出:tesGeyALKYm3A
//当我们要加自定义的盐值时,如例子中的testtest作为第二个参数直接加入, 超出两位字符的会截取前两位
echo "<hr>";

echo  crypt($password,'$1$testtest$');
//输出:$1$testtest$DsiRAWGTHiVH3O0HSHGoL1
/*crypt加密函数有多种盐值加密支持,以上例子展示的是MD5散列作为盐值,该方式下
盐值以$1$$的形式加入,如例子中的testtest加在后两个$符之间,
超出八位字符的会截取前八位,总长为12位;crypt默认就是这种形式。
*/
echo "<hr>";
//crypt还有多种盐值加密支持,详见手册

2 RSA加密算法

(2)在http请求时候header需要(防止被篡改)

//MD5是不可逆的只有加密没有解密

NSTimeIntervaltimeInterval=[[NSDate date]澳门新浦京电子游戏
timeIntervalSince1970]*1000;

NSString*timeStamp=[NSString
 stringWithFormat:@”%.f”,floor(timeInterval)];

//  MD5加密 单纯的MD5加密不安全
需要加盐,加盐就是在要加密的内容后加一些常量,常量越长越安全

//盐值

NSString*safeKey=safekey;//安全码

NSString*signStr=[NSString
 stringWithFormat:@”timestamp=%@&safekey=%@”,timeStamp,safeKey];

NSString*auth=[[Utils  md5HexDigest:signStr ]  lowercaseString];

[manager.requestSerializersetValue:auth
 forHTTPHeaderField:@”crpdb_auth”];

[manager.requestSerializersetValue:timeStamp
 forHTTPHeaderField:@”timestamp”];

Sha1加密:

string sha1 ( string $str [, bool $raw_output = false ]); //跟md5很像,不同的是sha1()默认情况下返回40个字符的散列值,传入参数性质一样,第一个为加密的字符串,第二个为raw_output的布尔值,默认为false,如果设置为true,sha1()则会返回原始的20 位原始格式报文摘要
<?php
$my_intro="zhouxiaogang";
echo sha1($my_intro); // b6773e8c180c693d9f875bcf77c1202a243e8594
echo "<hr>";
//当然,可以将多种加密算法混合使用
echo md5(sha1($my_intro));
//输出:54818bd624d69ac9a139bf92251e381d
//这种方式的双重加密也可以提高数据的安全性

2.1 概述

  RSA是目前最有影响力和最常用的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。

  RSA公开密钥密码体制。所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。
  在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然解密密钥SK是由公开密钥PK决定的,但却不能根据PK计算出SK。
  正是基于这种理论,1978年出现了著名的RSA算法,它通常是先生成一对RSA
密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA对话密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要。
  RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。RSA是被研究得最广泛的公钥算法,从提出到现今的三十多年里,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。

原理简介:MD5算法原理

非对称加密

非对称加密算法需要两个密钥来进行加密和解密,这两个秘钥是公开密钥(public
key,简称公钥)和私有密钥(private key,简称私钥);

澳门新浦京电子游戏 2

如图所示,甲乙之间使用非对称加密的方式完成了重要信息的安全传输。

  1. 乙方生成一对密钥(公钥和私钥)并将公钥向其它方公开。
  2. 得到该公钥的甲方使用该密钥对机密信息进行加密后再发送给乙方。
  3. 乙方再用自己保存的另一把专用密钥(私钥)对加密后的信息进行解密。乙方只能用其专用密钥(私钥)解密由对应的公钥加密后的信息。

在传输过程中,即使攻击者截获了传输的密文,并得到了乙的公钥,也无法破解密文,因为只有乙的私钥才能解密密文
同样,如果乙要回复加密信息给甲,那么需要甲先公布甲的公钥给乙用于加密,甲自己保存甲的私钥用于解密。

在非对称加密中使用的主要算法有:RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)等。 其中我们最见的算法是RSA算法

以下是从网上摘抄的一段PHP通过openssl实现非对称加密的算法

<?php
/**
 * 使用openssl实现非对称加密
 * @since 2010-07-08
 */
class Rsa {
    /**
     * private key
     */
    private $_privKey;
    /**
     * public key
     */
    private $_pubKey;
    /**
     * the keys saving path
     */
    private $_keyPath;
    /**
     * the construtor,the param $path is the keys saving path
     */
    public function __construct($path) {
        if (empty($path) || !is_dir($path)) {
            throw new Exception('Must set the keys save path');
        }
        $this->_keyPath = $path;
    }
    /**
     * create the key pair,save the key to $this->_keyPath
     */
    public function createKey() {
        $r = openssl_pkey_new();
        openssl_pkey_export($r, $privKey);
        file_put_contents($this->_keyPath . DIRECTORY_SEPARATOR . 'priv.key', $privKey);
        $this->_privKey = openssl_pkey_get_public($privKey);
        $rp = openssl_pkey_get_details($r);
        $pubKey = $rp['key'];
        file_put_contents($this->_keyPath . DIRECTORY_SEPARATOR . 'pub.key', $pubKey);
        $this->_pubKey = openssl_pkey_get_public($pubKey);
    }
    /**
     * setup the private key
     */
    public function setupPrivKey() {
        if (is_resource($this->_privKey)) {
            return true;
        }
        $file = $this->_keyPath . DIRECTORY_SEPARATOR . 'priv.key';
        $prk = file_get_contents($file);
        $this->_privKey = openssl_pkey_get_private($prk);
        return true;
    }
    /**
     * setup the public key
     */
    public function setupPubKey() {
        if (is_resource($this->_pubKey)) {
            return true;
        }
        $file = $this->_keyPath . DIRECTORY_SEPARATOR . 'pub.key';
        $puk = file_get_contents($file);
        $this->_pubKey = openssl_pkey_get_public($puk);
        return true;
    }
    /**
     * encrypt with the private key
     */
    public function privEncrypt($data) {
        if (!is_string($data)) {
            return null;
        }
        $this->setupPrivKey();
        $r = openssl_private_encrypt($data, $encrypted, $this->_privKey);
        if ($r) {
            return base64_encode($encrypted);
        }
        return null;
    }
    /**
     * decrypt with the private key
     */
    public function privDecrypt($encrypted) {
        if (!is_string($encrypted)) {
            return null;
        }
        $this->setupPrivKey();
        $encrypted = base64_decode($encrypted);
        $r = openssl_private_decrypt($encrypted, $decrypted, $this->_privKey);
        if ($r) {
            return $decrypted;
        }
        return null;
    }
    /**
     * encrypt with public key
     */
    public function pubEncrypt($data) {
        if (!is_string($data)) {
            return null;
        }
        $this->setupPubKey();
        $r = openssl_public_encrypt($data, $encrypted, $this->_pubKey);
        if ($r) {
            return base64_encode($encrypted);
        }
        return null;
    }
    /**
     * decrypt with the public key
     */
    public function pubDecrypt($crypted) {
        if (!is_string($crypted)) {
            return null;
        }
        $this->setupPubKey();
        $crypted = base64_decode($crypted);
        $r = openssl_public_decrypt($crypted, $decrypted, $this->_pubKey);
        if ($r) {
            return $decrypted;
        }
        return null;
    }
    public function __destruct() {
        @fclose($this->_privKey);
        @fclose($this->_pubKey);
    }
}
//以下是一个简单的测试demo,如果不需要请删除
$rsa = new Rsa('ssl-key');
//私钥加密,公钥解密
echo 'source:我是老鳖<br />';
$pre = $rsa->privEncrypt('我是老鳖');
echo 'private encrypted:<br />' . $pre . '<br />';
$pud = $rsa->pubDecrypt($pre);
echo 'public decrypted:' . $pud . '<br />';
//公钥加密,私钥解密
echo 'source:干IT的<br />';
$pue = $rsa->pubEncrypt('干IT的');
echo 'public encrypt:<br />' . $pue . '<br />';
$prd = $rsa->privDecrypt($pue);
echo 'private decrypt:' . $prd;
?>

2.2  算法实现过程

2.BASE64(只支持加密英文)

base64编码是可逆的,它是一种编码格式不是加密方式。

#import “NSString+Base64.h”

@implementation NSString (Base64)

– (NSString *)base64EncodedString;

{

NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];

return [data base64EncodedStringWithOptions:0];

}

– (NSString *)base64DecodedString

{

NSData *data = [[NSData alloc]initWithBase64EncodedString:self
options:0];

return [[NSString alloc]initWithData:data
encoding:NSUTF8StringEncoding];

}

@end

NSString *codeString = @”Hello world”;

NSLog(@”原文–%@”,codeString);

NSString *base64Str = [codeString base64EncodedString];

NSLog(@”Base64编码–%@”,base64Str);

NSString *decodeStr = [base64Str base64DecodedString];

NSLog(@”Base64解码–%@”,decodeStr);

base64编解码过程

对称加密算法

对称加密(也叫私钥加密)指加密和解密使用相同密钥的加密算法。有时又叫传统密码算法,就是加密密钥能够从解密密钥中推算出来,同时解密密钥也可以从加密密钥中推算出来。而在大多数的对称算法中,加密密钥和解密密钥是相同的,所以也称这种加密算法为秘密密钥算法或单密钥算法。它要求发送方和接收方在安全通信之前,商定一个密钥。对称算法的安全性依赖于密钥,泄漏密钥就意味着任何人都可以对他们发送或接收的消息解密,所以密钥的保密性对通信性至关重要。

对称加密的常用算法有:
DES算法,3DES算法,TDEA算法,Blowfish算法,RC5算法,IDEA算法

在PHP中也有封装好的对称加密函数

        1. 随意选择两个大的质数p和q,p不等于q,计算N=pq。         2. 根据欧拉函数,不大于N且与N互质的整数個数為(p-1)(q-1)。         3. 选择一个整数e与(p-1)(q-1)互质,并且e小于(p-1)(q-1)。         4. 用以下这个公式计算d:d× e ≡ 1 (mod (p-1)(q-1))。         5. 将p和q的记录销毁。           以上内容中,(N,e)是公钥,(N,d)是私钥。

3.AES加密(对称加密)

原理:

AES 是一个新的可以用于保护电子数据的加密算法。明确地说,AES
是一个迭代的、对称密钥分组的密码,它可以使用128、192 和 256
位密钥,并且用 128
位(16字节)分组加密和解密数据。与公共密钥密码使用密钥对不同,对称密钥密码使用相同的密钥加密和解密数据。通过分组密码返回的加密数据
的位数与输入数据相同。迭代加密使用一个循环结构,在该循环中重复置换(permutations
)和替换(substitutions)输入数据。Figure 1 显示了 AES
用192位密钥对一个16位字节数据块进行加密和解密的情形。

Urlencode/Urldecode

string urlencode ( string $str ) 
/*
1. 一个参数,传入要加密的字符串(通常应用于对URL的加密)
2. urlencode为双向加密,可以用urldecode来加密(严格意义上来说,不算真正的加密,更像是一种编码方式)
3. 返回字符串,此字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,空格则编码为加号(+)。
*/

通过Urlencode函数解决链接中带有&字符引起的问题:

<?php
$pre_url_encode="zhougang.com?username=zhougang&password=zhou"; //在实际开发中,我们很多时候要构造这种URL,这是没有问题的
$url_decode    ="zhougang.com?username=zhou&gang&password=zhou";//但是这种情况下用$_GET()来接受是会出问题的;
/*
Array
(
  [username] => zhou
  [gang] => 
  [password] => zhou
)
 */

//如下解决问题:
$username="zhou&gang";
$url_decode="zhougang.com?username=".urlencode($username)."&password=zhou";
?>

常见的urlencode()的转换字符

?=> %3F
= => %3D
% => %25
& => %26
 => %5C

 2.3 算法缺点

  1)产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次一密。

  2)安全性,RSA的安全性依赖于大数的因子分解,但并没有从理论上证明破译RSA的难度与大数分解难度等价,而且密码学界多数人士倾向于因子分解不是NP问题。

  3)速度太慢,由于RSA 的分组长度太大,为保证安全性,n 至少也要 600
bits以上,使运算代价很高,尤其是速度较慢,较对称密码算法慢几个数量级;且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。

加密代码

NSString *password = @”password”;//一般来说用户名就是用户密码的Key

NSString *passwordKey = @”userName”;

NSString *encryptedData = [AESCrypt encrypt:password
password:passwordKey];//加密

NSString *messagepassword = [AESCrypt decrypt:encryptedData
password:passwordKey]; //解密

NSLog(@”加密结果 = %@”,encryptedData);

NSLog(@”解密结果 = %@”,messagepassword);

base64

string base64_decode ( string $encoded_data )
  1. base64_encode()接受一个参数,也就是要编码的数据(这里不说字符串,是因为很多时候base64用来编码图片)
  2. base64_encode()为双向加密,可用base64_decode()来解密

$data=file_get_contents($filename);
echo base64_encode($data);
/*然后你查看网页源码就会得到一大串base64的字符串,
再用base64_decode()还原就可以得到图片。这也可以作为移动端上传图片的处理方案之一(但是不建议这样做哈)
*/

严格的来说..这两个函数其实不算是加密,更像是一种格式的序列化

以下是我们PHP程序中常用到的对称加密算法

2.4 java代码实现加解密

  1 package xin.dreaming.rsa;
  2 
  3 import java.io.ByteArrayOutputStream;
  4 import java.io.UnsupportedEncodingException;
  5 import java.security.Key;
  6 import java.security.KeyFactory;
  7 import java.security.KeyPair;
  8 import java.security.KeyPairGenerator;
  9 import java.security.NoSuchAlgorithmException;
 10 import java.security.interfaces.RSAPrivateKey;
 11 import java.security.interfaces.RSAPublicKey;
 12 import java.security.spec.PKCS8EncodedKeySpec;
 13 import java.security.spec.X509EncodedKeySpec;
 14 import java.util.HashMap;
 15 import java.util.Map;
 16 
 17 import javax.crypto.Cipher;
 18 
 19 import org.bouncycastle.util.encoders.Base64;
 20 
 21 /**
 22  * Rsa工具类
 23  * 
 24  * @author DREAMING.XIN
 25  *
 26  */
 27 public abstract class RsaUtils {
 28     /**
 29      * 生成公钥私钥对,使用默认模长1024。
 30      * 
 31      * @return Object[] : 0:公钥( RSAPublicKey ),1:私钥( RSAPrivateKey )
 32      */
 33 
 34     private static final int DEFAULT_KEY_LEN = 2048;
 35 
 36     public static Map<String, String> genKeyPair() {
 37         return genKeyPair(DEFAULT_KEY_LEN);
 38 
 39     }
 40 
 41     /**
 42      * 指定模长生成公私钥对
 43      * 
 44      * @param modulus
 45      * @return
 46      */
 47     public static Map<String, String> genKeyPair(int modulus) {
 48         KeyPairGenerator keyPairGen;
 49         try {
 50             keyPairGen = KeyPairGenerator.getInstance("RSA");
 51             keyPairGen.initialize(modulus);
 52             KeyPair keyPair = keyPairGen.generateKeyPair();
 53 
 54             Map<String, String> keyMaps = new HashMap<String, String>();
 55             RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
 56             keyMaps.put("publicKey", new String(Base64.encode(publicKey.getEncoded())));
 57             RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
 58             keyMaps.put("privateKey", new String(Base64.encode(privateKey.getEncoded())));
 59 
 60             return keyMaps;
 61         } catch (NoSuchAlgorithmException e) {
 62             throw new RuntimeException(e);
 63         }
 64     }
 65 
 66     /**
 67      * 公钥加密
 68      * 
 69      * @param publicKeyBytes
 70      * @param data
 71      * @param modulus
 72      *            公钥模长,范围512-2048。
 73      * @return
 74      */
 75     public static byte[] encryptByPublicKey(byte[] publicKeyBytes, byte[] data, int modulus) {
 76         try {
 77             // RSA最大加密明文大小
 78             int maxEncryptBlock = modulus / 8 - 11;
 79 
 80             X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyBytes);
 81             KeyFactory keyFactory = KeyFactory.getInstance("RSA");
 82             Key publicK = keyFactory.generatePublic(x509KeySpec);
 83             Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
 84             cipher.init(Cipher.ENCRYPT_MODE, publicK);
 85             int inputLen = data.length;
 86             ByteArrayOutputStream out = new ByteArrayOutputStream();
 87             int offSet = 0;
 88             byte[] cache;
 89             int i = 0;
 90             while (inputLen - offSet > 0) {
 91                 if (inputLen - offSet > maxEncryptBlock) {
 92                     cache = cipher.doFinal(data, offSet, maxEncryptBlock);
 93                 } else {
 94                     cache = cipher.doFinal(data, offSet, inputLen - offSet);
 95                 }
 96                 out.write(cache, 0, cache.length);
 97                 i++;
 98                 offSet = i * maxEncryptBlock;
 99             }
100             byte[] encryptedData = out.toByteArray();
101             out.close();
102             return encryptedData;
103         } catch (Exception e) {
104             throw new RuntimeException(e);
105         }
106 
107     }
108 
109     /**
110      * 公钥加密,密钥模长使用默认长度1024。
111      * 
112      * @param publicKeyBytes
113      *            公钥RSAPublicKey getEncoded()
114      * @param data
115      *            要加密的字节数组
116      */
117     public static byte[] encryptByPublicKey(byte[] publicKeyBytes, byte[] data) {
118         return encryptByPublicKey(publicKeyBytes, data, DEFAULT_KEY_LEN);
119     }
120 
121     /**
122      * 公钥解密
123      * 
124      * @param publicKeyBytes
125      *            公钥RSAPublicKey getEncoded()
126      * @param encryptedData
127      *            被(私钥)加密过的字节数组
128      * @param modulus
129      *            模长,范围512-2048
130      * @return
131      */
132     public static byte[] decryptByPublicKey(byte[] publicKeyBytes, byte[] encryptedData, int modulus) {
133         // RSA最大解密密文大小
134         int maxDecryptBlock = modulus / 8;
135         try {
136             X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyBytes);
137             KeyFactory keyFactory = KeyFactory.getInstance("RSA");
138             Key publicK = keyFactory.generatePublic(x509KeySpec);
139             Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
140             cipher.init(Cipher.DECRYPT_MODE, publicK);
141             int inputLen = encryptedData.length;
142             ByteArrayOutputStream out = new ByteArrayOutputStream();
143             int offSet = 0;
144             byte[] cache;
145             int i = 0;
146             // 对数据分段解密
147             while (inputLen - offSet > 0) {
148                 if (inputLen - offSet > maxDecryptBlock) {
149                     cache = cipher.doFinal(encryptedData, offSet, maxDecryptBlock);
150                 } else {
151                     cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
152                 }
153                 out.write(cache, 0, cache.length);
154                 i++;
155                 offSet = i * maxDecryptBlock;
156             }
157             byte[] decryptedData = out.toByteArray();
158             out.close();
159             return decryptedData;
160         } catch (Exception e) {
161             throw new RuntimeException(e);
162         }
163     }
164 
165     /**
166      * 公钥解密,默认模长1024
167      * 
168      * @param publicKeyBytes
169      *            公钥RSAPublicKey getEncoded()
170      * @param encryptedData
171      *            被(私钥)加密过的字节数组
172      */
173     public static byte[] decryptByPublicKey(byte[] publicKeyBytes, byte[] encryptedData) {
174         return decryptByPublicKey(publicKeyBytes, encryptedData, DEFAULT_KEY_LEN);
175     }
176 
177     /**
178      * 私钥加密
179      * 
180      * @param privateKeyBytes
181      *            私钥RSAPrivateKey getEncoded()
182      * @param data
183      *            要加密的字节数组
184      * @param modulus
185      *            模长,范围512-2048。
186      */
187     public static byte[] encryptByPrivateKey(byte[] privateKeyBytes, byte[] data, int modulus) {
188         try {
189             // RSA最大加密明文大小
190             int maxEncryptBlock = modulus / 8 - 11;
191 
192             PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
193             KeyFactory keyFactory = KeyFactory.getInstance("RSA");
194             Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
195             Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
196             cipher.init(Cipher.ENCRYPT_MODE, privateK);
197             int inputLen = data.length;
198             ByteArrayOutputStream out = new ByteArrayOutputStream();
199             int offSet = 0;
200             byte[] cache;
201             int i = 0;
202             while (inputLen - offSet > 0) {
203                 if (inputLen - offSet > maxEncryptBlock) {
204                     cache = cipher.doFinal(data, offSet, maxEncryptBlock);
205                 } else {
206                     cache = cipher.doFinal(data, offSet, inputLen - offSet);
207                 }
208                 out.write(cache, 0, cache.length);
209                 i++;
210                 offSet = i * maxEncryptBlock;
211             }
212             byte[] encryptedData = out.toByteArray();
213             out.close();
214             return encryptedData;
215         } catch (Exception e) {
216             throw new RuntimeException(e);
217         }
218     }
219 
220     /**
221      * 私钥加密,默认模长1024。
222      * 
223      * @param privateKeyBytes
224      *            私钥RSAPrivateKey getEncoded()
225      * @param data
226      *            要加密的字节数组
227      */
228     public static byte[] encryptByPrivateKey(byte[] privateKeyBytes, byte[] data) {
229         return encryptByPrivateKey(privateKeyBytes, data, DEFAULT_KEY_LEN);
230     }
231 
232     /**
233      * 私钥解密
234      * 
235      * @param privateKeyBytes
236      *            私钥RSAPrivateKey getEncoded()
237      * @param encryptedData
238      *            被(公钥)加密过的字节数组
239      * @param modulus
240      *            模长,范围512-2048
241      */
242     public static byte[] decryptByPrivateKey(byte[] privateKeyBytes, byte[] encryptedData, int modulus) {
243         try {
244             // RSA最大解密密文大小
245             int maxDecryptBlock = modulus / 8;
246 
247             PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
248             KeyFactory keyFactory = KeyFactory.getInstance("RSA");
249             Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
250             Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
251             cipher.init(Cipher.DECRYPT_MODE, privateK);
252             int inputLen = encryptedData.length;
253             ByteArrayOutputStream out = new ByteArrayOutputStream();
254             int offSet = 0;
255             byte[] cache;
256             int i = 0;
257             while (inputLen - offSet > 0) {
258                 if (inputLen - offSet > maxDecryptBlock) {
259                     cache = cipher.doFinal(encryptedData, offSet, maxDecryptBlock);
260                 } else {
261                     cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
262                 }
263                 out.write(cache, 0, cache.length);
264                 i++;
265                 offSet = i * maxDecryptBlock;
266             }
267             byte[] decryptedData = out.toByteArray();
268             out.close();
269             return decryptedData;
270         } catch (Exception e) {
271             throw new RuntimeException(e);
272         }
273     }
274 
275     /**
276      * 私钥解密,默认模长1024。
277      * 
278      * @param privateKeyBytes
279      *            私钥RSAPrivateKey getEncoded()
280      * @param encryptedData
281      *            被(公钥)加密过的字节数组
282      */
283     public static byte[] decryptByPrivateKey(byte[] privateKeyBytes, byte[] encryptedData) {
284         return decryptByPrivateKey(privateKeyBytes, encryptedData, DEFAULT_KEY_LEN);
285     }
286 
287     public static void main(String[] args) throws UnsupportedEncodingException {
288         // 加密原串
289         String value = "DREAMING.XIN";
290         System.out.println("加密原串 : ");
291         System.out.println(value);
292         System.out.println("------------------------------------------------------------------------------------------");
293         // 生成公私钥对
294         Map<String, String> genKeyPair = genKeyPair();
295 
296         System.out.println("自行生成公私钥对: ");
297         System.out.println(genKeyPair);
298         System.out.println("------------------------------------------------------------------------------------------");
299         byte[] encryptByPublicKey = encryptByPublicKey(Base64.decode(genKeyPair.get("publicKey").getBytes("utf-8")),
300                 value.getBytes());
301 
302         // 3、Base64编码
303         byte[] encode = Base64.encode(encryptByPublicKey);
304 
305         System.out.println("最终加密结果: ");
306         String sign = new String(encode, "utf-8");
307         System.out.println(new String(encode, "utf-8"));
308         System.out.println("------------------------------------------------------------------------------------------");
309 
310         // 1、签名密文->Base64解码->RSA解密
311         byte[] signCipherArr = decryptByPrivateKey(Base64.decode(genKeyPair.get("privateKey").getBytes("utf-8")),
312                 Base64.decode(sign.getBytes("utf-8")));
313         System.out.println("解密结果: ");
314         System.out.println(new String (signCipherArr));
315         System.out.println("------------------------------------------------------------------------------------------");
316 
317     }
318 }

输出结果:

加密原串 : 
DREAMING.XIN
------------------------------------------------------------------------------------------
自行生成公私钥对: 
{publicKey=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkmRw1oug/LBmpkRsubsKoeEBQvGeRfUTMX8fTEuLJqKuWfHkB6HJ/08xf/BYhbL+GrUFk5DR/lbJdnD9SEx0ZDZHecrjj262T67izwf7d+rB3o7z5w/3Pk3p3Ye6Ns7SdGM6D8O6InUK4mQFSBKQhw25BqPzUQKb4DY/S+I2OAx1/qVB56Na+if5H9ttP8nhVVnQZXheTPh5Say0+ySFEBb1i2sxJQuwFLbtA9RkKNFSSB2+4sBrn5fRmemu6OGToR/WQ8KFa96+u9X2t41HPxa7dTF+g9btkEMWwbiXkPatjD9JaNXKKrueIQoDt/FKonUZQ0AafSs8r/xsrb4pfwIDAQAB, privateKey=MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCSZHDWi6D8sGamRGy5uwqh4QFC8Z5F9RMxfx9MS4smoq5Z8eQHocn/TzF/8FiFsv4atQWTkNH+Vsl2cP1ITHRkNkd5yuOPbrZPruLPB/t36sHejvPnD/c+Tendh7o2ztJ0YzoPw7oidQriZAVIEpCHDbkGo/NRApvgNj9L4jY4DHX+pUHno1r6J/kf220/yeFVWdBleF5M+HlJrLT7JIUQFvWLazElC7AUtu0D1GQo0VJIHb7iwGufl9GZ6a7o4ZOhH9ZDwoVr3r671fa3jUc/Frt1MX6D1u2QQxbBuJeQ9q2MP0lo1coqu54hCgO38UqidRlDQBp9Kzyv/Gytvil/AgMBAAECggEAWWoJ1bExIkYoXHO8qPDKfLduytHDZ11aXMgVeMdHddC1h3CMY/D47P0U8dz+ZKNAO1XH0ysIaD3gDXzT5z3zdWYF4CkBNxFbP25FUEjC2qrDwUk1RjNlQ2PZbRrCrUlEGBynUQuue+9bN435/9x+9E54bcrkCd37EUZxAMtpbG+bZ8/sizBsIQYfiKlGV3FJ68OTnkCzvjltYmzWn4q1a6CDqN40G6IfBJD1g1ENkkKJvi4hu6U7LhkpI3oil4+zZuxdGNphICz6L5CQVn01MahnfJlNszQD1H0sq/G9ymHtzYyvq6Fu8URjksw4doaqYVRuGuZL58qP33BNSzilwQKBgQDHZDC5YgViTmqAC9/GGnm1Cwhi8SkbsG0j6jCRx4e6nYgux4TOg9V6MdzXrm/w6X5ZtTTDPoB4vn+l2pX8SGyO1c2JfaL3w+iMahSAee6CFDbBzmiF5b+PiiKmYKzrNTtjPNkcDsrwErIhiyplgkj/+gsiVAepliJRUVTVeApvHwKBgQC79EUDck2kwSMsw3kXb/ZUIG6BPH0j/A0xn7SqcsVc/Rt3WFzfUJV9qCsN9TwGm3lk8fIsdXYoLrm96MlNOU3uNUzwwYwqespkdJ5R6iniWA+LAVuGgHhDYk84VFDxcldMLlG16O7uuIoUSeXdVwCChx1OllKFxsEj1z6X4mPZoQKBgQCy883zI/FXGK/m+kE9aFehUCSXwH+3lTFvEWnD/MNpjqdB7NnaC2JWiFf/z1QycS1wT/zp2retJrQj47nHMi0USPluk67nFhIpq69423ZfksrOSHVw7xFtP3n3vz6S3zTMzTjCQNiMfQsYpfFIJ5VjAERr6+TwpIlqWEd+S3152wKBgH+t6FP3ChepvCNkhpYNUODFR0wzsy8Gwk+7lhdT8A7DQi1IsY5iR6sc2mKY/TXf2A9i7IiXIrUZSMRhpp33F6GCQ8opMPaKg4LKVeJ/mARSnfxn56zvCMN9vSMe4/2hFvyBWrCgk+9HHUW7DZPWzlndP2NrapPF+N5IEhVLjVkBAoGABqIvu4Vpgg3viiE6PRmlA0iAnAz2ZnaqPS7Xk8+Ua44rCxTE62Vhm5ZbfQQzxlqFL/32NnJ3+zG/ONnWqdkGkvE5N/7NZg5CNzTPVqn/PbUAQ1L01yzcAETqr1dMLhGqlMMLkdbLO8VzoagVRuE+jSOwl3a+5Yq/cu0TMKLhrAE=}
------------------------------------------------------------------------------------------
最终加密结果: 
YmGXP+nSAY23ENUryid4zdE6KRAfFGhQWPJ4NAM1odZIEZCh5BbOtw437E85TdzABNE+NTDVogq+AI8WfAiD0yUpDukdRrZMb/IwG5k7xCgsVo0Tgt2SiH9bZFkvMaIIWH6d90muVtA/dyGHPSk/WmdgSl3QCcsZ3JAzMeadZwtL685eBhJD6hwXwKLfQj1OQBlLH3R9D5gBNGf36RHyi20LteTOKIR9lvMQPGbsnvspqi7t3xo5ajLpeuCr9azEovP0UFiiaxrkGLYMG2YM91r7JXUCn2gtVuDnXPFVVfOj84mN51229UJwQWBZe0BGPLSpROmOUZeWj2gjvuyqGg==
------------------------------------------------------------------------------------------
解密结果: 
DREAMING.XIN
------------------------------------------------------------------------------------------

加密实例代码

-(void)saveUserNameAndPwd:(NSString *)userName andPwd:(NSString
*)pwd

{

NSUserDefaults * settings = [NSUserDefaults standardUserDefaults];

[settings removeObjectForKey:@”UserName”];

[settings removeObjectForKey:@”Password”];

[settings setObject:userName forKey:@”UserName”];

pwd = [AESCrypt encrypt:pwd password:@”pwd”];

[settings setObject:pwd forKey:@”Password”];

[settings synchronize];

}

-(NSString *)getPwd

{

NSUserDefaults * settings = [NSUserDefaults standardUserDefaults];

NSString * temp = [settings objectForKey:@”Password”];

return [AESCrypt decrypt:temp password:@”pwd”];

}

discuz经典算法

<?php
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {   
    // 动态密匙长度,相同的明文会生成不同密文就是依靠动态密匙   
    $ckey_length = 4;   

    // 密匙   
    $key = md5($key ? $key : $GLOBALS['discuz_auth_key']);   

    // 密匙a会参与加解密   
    $keya = md5(substr($key, 0, 16));   
    // 密匙b会用来做数据完整性验证   
    $keyb = md5(substr($key, 16, 16));   
    // 密匙c用于变化生成的密文   
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): 
substr(md5(microtime()), -$ckey_length)) : '';   
    // 参与运算的密匙   
    $cryptkey = $keya.md5($keya.$keyc);   
    $key_length = strlen($cryptkey);   
    // 明文,前10位用来保存时间戳,解密时验证数据有效性,10到26位用来保存$keyb(密匙b), 
//解密时会通过这个密匙验证数据完整性   
    // 如果是解码的话,会从第$ckey_length位开始,因为密文前$ckey_length位保存 动态密匙,以保证解密正确   
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) :  
sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;   
    $string_length = strlen($string);   
    $result = '';   
    $box = range(0, 255);   
    $rndkey = array();   
    // 产生密匙簿   
    for($i = 0; $i <= 255; $i++) {   
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);   
    }   
    // 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上对并不会增加密文的强度   
    for($j = $i = 0; $i < 256; $i++) {   
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;   
        $tmp = $box[$i];   
        $box[$i] = $box[$j];   
        $box[$j] = $tmp;   
    }   
    // 核心加解密部分   
    for($a = $j = $i = 0; $i < $string_length; $i++) {   
        $a = ($a + 1) % 256;   
        $j = ($j + $box[$a]) % 256;   
        $tmp = $box[$a];   
        $box[$a] = $box[$j];   
        $box[$j] = $tmp;   
        // 从密匙簿得出密匙进行异或,再转成字符   
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));   
    }   
    if($operation == 'DECODE') {  
        // 验证数据有效性,请看未加密明文的格式   
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) &&  
substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {   
            return substr($result, 26);   
        } else {   
            return '';   
        }   
    } else {   
        // 把动态密匙保存在密文里,这也是为什么同样的明文,生产不同密文后能解密的原因   
        // 因为加密后的密文可能是一些特殊字符,复制过程可能会丢失,所以用base64编码   
        return $keyc.str_replace('=', '', base64_encode($result));   
    }   
}

2.5 java代码实现加签验签

  1 package xin.dreaming.rsa;
  2 
  3 import org.apache.commons.codec.binary.Base64;
  4 
  5 import javax.crypto.Cipher;
  6 import java.io.ByteArrayInputStream;
  7 import java.security.KeyFactory;
  8 import java.security.PrivateKey;
  9 import java.security.PublicKey;
 10 import java.security.Signature;
 11 import java.security.cert.Certificate;
 12 import java.security.cert.CertificateFactory;
 13 import java.security.spec.PKCS8EncodedKeySpec;
 14 
 15 /**
 16  * 
 17  * @author DREAMING.XIN
 18  *
 19  */
 20 public class RSAUtil {
 21 
 22     private static final String CHARSET = "UTF-8";
 23 
 24     private static final String algorithm = "SHA256withRSA";
 25 
 26     /**
 27      * 网联请求报文签名
 28      * 
 29      * @param privateKey
 30      *            机构私钥字符串
 31      * @param content
 32      *            签名原文
 33      * @return 签名密文
 34      * @throws Exception
 35      */
 36     public static String sign(String privateKey, String content) throws Exception {
 37         Signature signature = Signature.getInstance(algorithm);
 38         signature.initSign(convertPrivateKey(privateKey));
 39         signature.update(content.getBytes(CHARSET));
 40         return Base64.encodeBase64String(signature.sign());
 41     }
 42 
 43     /**
 44      * 网联返回报文验签
 45      * 
 46      * @param publicKey
 47      *            网联公钥字符串
 48      * @param content
 49      *            验签原文报文
 50      * @param signStr
 51      *            网联返回签名字符串
 52      * @return 验签结果
 53      * @throws Exception
 54      */
 55     public static boolean vertify(String publicKey, String content, String signStr) throws Exception {
 56         Signature signature = Signature.getInstance(algorithm);
 57         signature.initVerify(convertPublicKey(publicKey));
 58         signature.update(content.getBytes(CHARSET));
 59         return signature.verify(Base64.decodeBase64(signStr.getBytes(CHARSET)));
 60     }
 61 
 62     /**
 63      * 对称密钥公钥加密
 64      * 
 65      * @param publicKey
 66      *            网联公钥字符串
 67      * @param content
 68      *            密钥原文
 69      * @return 加密密文
 70      * @throws Exception
 71      */
 72     public static String encryptByPublicKey(String publicKey, String content) throws Exception {
 73         String result = null;
 74         try {
 75             Cipher cipher = cipher = Cipher.getInstance("RSA");
 76             cipher.init(Cipher.ENCRYPT_MODE, convertPublicKey(publicKey));
 77             byte[] encoded = cipher.doFinal(content.getBytes(CHARSET));
 78             result = Base64.encodeBase64String(encoded);
 79         } catch (Exception e) {
 80         
 81         }
 82         return result;
 83     }
 84 
 85     /**
 86      * 对称密钥密文解密
 87      * 
 88      * @param privateKey
 89      *            机构私钥字符串
 90      * @param content
 91      *            网联对称密钥密文
 92      * @return 对称密钥明文
 93      * @throws Exception
 94      */
 95     public static String decryptByPrivateKey(String privateKey, String content) throws Exception {
 96         String result = null;
 97         try {
 98             Cipher cipher = cipher = Cipher.getInstance("RSA");
 99             cipher.init(Cipher.DECRYPT_MODE, convertPrivateKey(privateKey));
100             byte[] encoded = cipher.doFinal(Base64.decodeBase64(content.getBytes(CHARSET)));
101             result = new String(encoded, CHARSET);
102         } catch (Exception e) {
103         }
104         return result;
105     }
106 
107     public static PrivateKey convertPrivateKey(String keyStr) throws Exception {
108         PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(keyStr.getBytes(CHARSET)));
109         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
110         return keyFactory.generatePrivate(keySpec);
111     }
112 
113     public static PublicKey convertPublicKey(String keyStr) throws Exception {
114         CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
115         Certificate certificate = certificateFactory
116                 .generateCertificate(new ByteArrayInputStream(Base64.decodeBase64(keyStr.getBytes(CHARSET))));
117         return certificate.getPublicKey();
118     }
119 
120     public static void main(String[] args) throws Exception {
121         // 获取私钥
122         String privatekey = CertConfig.PrivateKey;
123         String publicKey = CertConfig.PublicKeyZ;
124         
125         String sign = sign(privatekey, "DREAMING.XIN");
126 
127         System.out.println("加签结果:"+sign);
128 
129         boolean vertify = vertify(publicKey,"DREAMING.XIN",sign);
130                 
131         System.out.println("验签结果: "+vertify);
132     }
133 
134 }

密钥java类:

 1 package xin.dreaming.rsa;
 2 
 3 public class CertConfig {
 4 
 5     public static final String PrivateKey ="MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDtO4yND2EGec6InFURBZtE6TV5RB/GXmkrSADSor/zPEQsYT3TxD/d3snwOStAfyKbUEIdNHfOKYGLcnEUX7mokQoXn7/0Vtp6XV2+VuL/s8+Dx79iPQ1vpCqn8TN+VlL9bmL5gdd0jenmEJJRmWHV4DTypzXyLSRjMzZsOjcJMeXQDPGDxE5J8JIsz9mh9fggQjDnpPzjcF6X3qFBwq/w/LwZ/g8s2CdLQeql3TJ0hUFhrCt/Ii5bFaYQ/KbUbCXylQHpQ86tRicpSmMLVqNZuH0MnDAdhWVq3qMbYqsb8IkrlPKXh1VrZRI+lc0EvLyT8lvb6DISFbx7drJg4Y+3AgMBAAECggEAT1xwdHAEoUn2UbUasAsUGkV54gtsJcxHmncH728Kj7BFjiMpr8IjK3HwVDCLy5O8XADJXUPEIG+6KpAqTAqJ7V435hdG+9JiXDUHuzkNz0Sz0v3rhE2wRPzCWFRUSZtPQADBk35gOVmQOaqpiCqrlAThMZvGbDG1zom/Vw1Sg/xMY/Mloj/ycfGtNkVB05es5mcwWFJC+Mvj/qHJGc7PM5rw98+nFWZanzwvhrdQdSsA18FalCmeF3+n1bcOt+gCnZuq7/ZFpEuqK6dsj6mIZ5fnAB3P7S63foSQkqSYS8tFH+o8CU898wdJ1Ba26XnQ2ghX5X9zWP+oTYzuVPV1gQKBgQD5VzSr6fsj3CrjLuwQ7LqDemXC8n7AUDDQ5Z87yxpZZtPxu9CYdxxfBKfWjYskSTLm6DPyNQ8eqmpARBLGxRIKzXQF+5wLGqxr0FwSoBUM47uR68ChY4v4T84dxQ9RpNvbn8C+lPru+F2hrCWLwBnY1IGFxPWrro8qVUJCrvd+RwKBgQDzkY7ggsmf68kmVAj2JMwZ01o5vsCQbMZu+v79o5cvUxEmcQo2hb+0l/qizA/Vse/fOs9l7GDZN4nSwFzE141cVC7BmIqZpYxYSksGTlH7JcnuWdSZA4G1cK1rbJdR/M6zTPgTFkRjD1egFIK3P02fXu44toFkJb6CrNicssHrEQKBgC9Ma6Fw8UMMMNaHwCA1x+vI/CTO+1xf2eLGrD4beRQcfXgNuLQzZB5iM7RvhUWM3SsQQUpg5k1a5mzqfOVX3ORPtQKtiBxTIwIQtGaUF2oqiRpVLmVvDM491UuwZgeGzm4LD/UXLcLHOnvAvB6WglCvfyJxCmlW47GUGs2rgydhAoGBAJJ2t/T3kKjSz1118QGatQTenAXXV9JBJr37vrPk2HfDuq9kECEjIllFfpjAntEAs96Hbcm7b62PARizRdW0TLP1hzwxLz8fVpqM6jp7hD7CxX/HktkES85AWHgdj4zkuaMGKLLJlAwBYM7JJqVsso+gNR3zWTFQpRPNPmBT+doRAoGBANhtqTKRAcn4lBam2cOOMCLIrU+UEDDWfzgUUeBHFYTwwPLgRXCRyvgP9B+1r9IR3v18Rb0IJo2p0oDe7l/QM7iR53Vg2HVQ5vlgyvWrLODZQMss52vgvZJhetzFNxkT0UmGyug5Uy1Wf+BUH4lHgCnBOOUxgZoZdVJtgCyLr549";
 6     //签名私钥
 7     //public static final String PrivateKey ="MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC6WywVY3QjRicJyIWB4Huw3aEkUH4oOZQVpAPo1KL2yxx11A2l6WmdbsngxqI/fJIe69RyGbmzZr9vRD4VOlinRCbRJ4WXH061COG6lFBUi/K6hVX4HBgwE8svbNNnFuwLQBeds5XXWSKMSLTf9XTz+uiJLJA+pYaVMmrNzsEgN8nZTPjZrCWyzaAo1Wz7NOH1gLxRDpPYvIzufDxLKby0l5huqszQSsiEzV8eff/axskBLuOkCGd4LznwPvnzMU40JVMt1Bsh5XWpqY+A+woyslhPzax62u5af2dZ7cs8loL9WbA7Ia3ZuhfPwKF3MpUEKW+wyVyfIQc/uhaOea5zAgMBAAECggEAc11bpgYCcI/OPP04wRUyHWSmjC+UWdyDMv5tOSbhl7xXaw4SQOKFcmOScCcna/v3DVNbGiOY1VnHKt9pO4T6Otoy2YoI5mwIMoREEVgdfqmAYz2F4emqg6DNSReqq4gCKljMBeGV4lGY1JVx+68dbqimabz/sviPny8t9SiIYCN5/FcQtsH93EZPQSsWe047Fc5UgVmXdV3x+Bc+cCdso/P0yoCx18VL6krxF3LhOcQs53765rA6yWYFLActV65x32rn9P6+FGLg9nFyERaKujyRujZtSlBzfYi/L+/38wdddt2N+/R0JdooLvHgmlWlRndQcs81Ah/SM81k2r/V2QKBgQDsL0MgE2MQ4OcO8rBC0K+DTioOTNkrAiwxAiPlKW0n9jp5tr4KLRPcRU5gg34nskPfgxOU6gDK7HGvochPuAwv+3LP2lNGdpLsUtx00co0rmwHSiu3fr3iEnHG3pKCJvHW+KfZpqsgLksiXKCWH7AsSEVLwFgiLE8ibg995IuDjwKBgQDJ/bOSITae8uaGqiNs5bti9PEWhgDRR8FPMiTmBH2yllEzwLr94oPMdHTIXOW0U4+8ZcuV3et1vf5tjUbSHfGp1fRmHKJPjEPlLy9VfU6UiDxFdRChQPTWB1//l+bWJjYMrbsthwoEBeP+vL4hNfBkwgvCza7fAmDK60zDe2ck3QKBgDeGOOKejCiYptlFxpg+lTRqOMrZ2CgbP6ZZ2XRzU70UTtT0WCLuS//5rx5Ta2ILr5cpKn5UsNED2wouH3hWTU8ubuRccD1dfNbf+AHinAXch3sDPdnKivtN2L+m7Yx5eVtPY65wV0SefX1bh0kjs/gFGX1gf5exEP2IIE45X28TAoGBALfuEj9FiTRR4QLNGLcHtouUmZg167amTWutMJZXjpI5eLXUkTGwuu1JOjJdDToYQTF/zFOqocc0e+MMG2onpDBPyF3XQyGGiyi9v69sDEsKhz+EKuF7gbcHPi5DBwsH/n2rEV+SsNca+hKzkboyILXPUOBRZSRjSPpeKydyTmjtAoGAeEp+MatIX+SohXJe4uYak3zuoOCze4XqS9rH4wecSHn2J7jfOoZg2UzvOpEeKpfVngC6qfet8F2liWQ4UMcFC+ydnWfmVOF0KjkdV5gU8rlcF+mTs0cEOTF+3xf+nDMFkjC8XrQ5ZOqdSvDGkVfvFyzUkZ9DmqHbR3LQlf6OTFk=";
 8     //验签公钥
 9     public static final String PublicKey ="MIIESDCCAzCgAwIBAgIFQAAGiCkwDQYJKoZIhvcNAQELBQAwXTELMAkGA1UEBhMCQ04xMDAuBgNVBAoMJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEcMBoGA1UEAwwTQ0ZDQSBBQ1MgVEVTVCBPQ0EzMTAeFw0xNzAyMDkwMjI5NDdaFw0yMjAyMDkwMjI5NDdaMGkxCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhPQ0EzMVJTQTENMAsGA1UECwwERVBDQzEZMBcGA1UECwwQT3JnYW5pemF0aW9uYWwtMTEdMBsGA1UEAwwURVBDQ0B3YW5nbGlhbkBaMTIzQDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZEowS2/FFgW/MNp1k+NUROPfQ1HHwN7N3dM6Q70T6hSOVYEpTVWTjrWYkcuZIItf4K1MGgzDuvJRJBefP1T4MpW1sfBzxJ+IJP5GGEFLNMXOR5+9f315eebULdfFfVH7qmrFuEsmpnu+t93AeZx2f4xQEtYEAU9j3+dUzx0qVNaVDa0oeUMlt209THbamgltQNhMRZpEQnKdLrPcS9lJ9vWwU9Ro3VSxsbCXSWnTs3tG2JUdsov22I6MV+vTassz5Da/uhhFCh7T6vGkplHnEcrtDb1hDvn0uyCHr+kONV1BEkYha0/TDU7Py8mC2I8tuZVERMxSlRr5mj2QAJDWNAgMBAAGjggEBMIH+MEYGCCsGAQUFBwEBBDowODA2BggrBgEFBQcwAYYqaHR0cDovLzIxMC43NC40Mi4xMTo4MDg1L29jc3Bfc2VydmVyL29jc3AvMB8GA1UdIwQYMBaAFJo9tK5lWPvOWgV4JqBtKwSGusbsMAwGA1UdEwEB/wQCMAAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovLzIxMC43NC40Mi4zL09DQTMxL1JTQS9jcmw4OS5jcmwwDgYDVR0PAQH/BAQDAgbAMB0GA1UdDgQWBBSAsKx7L3tslIlUn7nm21OT5uzXfDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwDQYJKoZIhvcNAQELBQADggEBAIpP7adHCgrPoTGYLpZ4ENZO7t24G29ksaBd/BjmjEAAU1vqJkWPrrkgbr/llfpYJpMY/lYWUJFctNKp3TwU3ZMIKQ9fQAdi2mAPqWU8GBw/8C5FetBIBxB3g13C76KASgYCMTMTgPbdrRmFSyE0mOubcMwPC1g/S07TKsmGKMs5QaTZ36VAJU21fXXa/sqGeUSKzdmChoNkug8At+shnEU10ogSXfSv55lPGMISYeg7h3Hk2lwbOX0t6ugXgn6RjMDHqB5ZVDF0Kvrzmt++xFhTI5uyNk3t1Wr2Uz3MsDI4SNLcMu7EaTf8rrNPlu3/qsNCXufoIso3UVe56KRfqws=";
10     //验签公钥
11     public static final String PublicKeyZ ="MIIEWzCCA0OgAwIBAgIFQAJQhUAwDQYJKoZIhvcNAQELBQAwXTELMAkGA1UEBhMCQ04xMDAuBgNVBAoMJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEcMBoGA1UEAwwTQ0ZDQSBBQ1MgVEVTVCBPQ0EzMTAeFw0xNzA5MjcwODQwMzRaFw0yMDA5MjcwODQwMzRaMIGBMQswCQYDVQQGEwJDTjEXMBUGA1UECgwOQ0ZDQSBSU0EgT0NBMzExETAPBgNVBAsMCExvY2FsIFJBMRkwFwYDVQQLDBBPcmdhbml6YXRpb25hbC0xMSswKQYDVQQDDCIwNTFAVGVzdDE1MDY1MDE2MzQ2MDJAWkgxMjM0NTY3OEAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7TuMjQ9hBnnOiJxVEQWbROk1eUQfxl5pK0gA0qK/8zxELGE908Q/3d7J8DkrQH8im1BCHTR3zimBi3JxFF+5qJEKF5+/9Fbael1dvlbi/7PPg8e/Yj0Nb6Qqp/EzflZS/W5i+YHXdI3p5hCSUZlh1eA08qc18i0kYzM2bDo3CTHl0Azxg8ROSfCSLM/ZofX4IEIw56T843Bel96hQcKv8Py8Gf4PLNgnS0Hqpd0ydIVBYawrfyIuWxWmEPym1Gwl8pUB6UPOrUYnKUpjC1ajWbh9DJwwHYVlat6jG2KrG/CJK5Tyl4dVa2USPpXNBLy8k/Jb2+gyEhW8e3ayYOGPtwIDAQABo4H8MIH5MD8GCCsGAQUFBwEBBDMwMTAvBggrBgEFBQcwAYYjaHR0cDovL29jc3B0ZXN0LmNmY2EuY29tLmNuOjgwL29jc3AwHwYDVR0jBBgwFoAUmj20rmVY+85aBXgmoG0rBIa6xuwwDAYDVR0TAQH/BAIwADA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vMjEwLjc0LjQyLjMvT0NBMzEvUlNBL2NybDQ4NDYuY3JsMA4GA1UdDwEB/wQEAwIGwDAdBgNVHQ4EFgQU5afVQ1AjMzdZ5o/OVDBU5zw+ZgswHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBCwUAA4IBAQAszGTg4RRzqrJrf598sou0WKLjFUoK2hcnHaUJv9A3Zkbu5XCy5SrBrYOibw0Uw5zwM6cKz0s7YkKusrwDUKg+QRodQvFvMqVI0BsJguc3cqOCy0dvibWseKFlEc+C1ffx1yVK/2ElrLW6TUPixKSzyEo6h852z2w575+/S1S9XZbdtS7OXozA4zfxy5D32QToNCqPFundhB7HYPMbQaZr+sjsZ7sBqKaPq6TRVUcdVQ1OXatK2O4mRwQDHQFqkBLnrijiht6+p2YUpKACbJREqylN+ToJMYcdIlRpQ3DlWZPSuzbWgtw5tqH4bLFaOG07wl7Q1fOOFaVScPzqFRRB";
12     
13     //铭感信息加密
14     public static final String MGJMKEY = "MIIESDCCAzCgAwIBAgIFQAAGiCkwDQYJKoZIhvcNAQELBQAwXTELMAkGA1UEBhMCQ04xMDAuBgNVBAoMJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEcMBoGA1UEAwwTQ0ZDQSBBQ1MgVEVTVCBPQ0EzMTAeFw0xNzAyMDkwMjI5NDdaFw0yMjAyMDkwMjI5NDdaMGkxCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhPQ0EzMVJTQTENMAsGA1UECwwERVBDQzEZMBcGA1UECwwQT3JnYW5pemF0aW9uYWwtMTEdMBsGA1UEAwwURVBDQ0B3YW5nbGlhbkBaMTIzQDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZEowS2/FFgW/MNp1k+NUROPfQ1HHwN7N3dM6Q70T6hSOVYEpTVWTjrWYkcuZIItf4K1MGgzDuvJRJBefP1T4MpW1sfBzxJ+IJP5GGEFLNMXOR5+9f315eebULdfFfVH7qmrFuEsmpnu+t93AeZx2f4xQEtYEAU9j3+dUzx0qVNaVDa0oeUMlt209THbamgltQNhMRZpEQnKdLrPcS9lJ9vWwU9Ro3VSxsbCXSWnTs3tG2JUdsov22I6MV+vTassz5Da/uhhFCh7T6vGkplHnEcrtDb1hDvn0uyCHr+kONV1BEkYha0/TDU7Py8mC2I8tuZVERMxSlRr5mj2QAJDWNAgMBAAGjggEBMIH+MEYGCCsGAQUFBwEBBDowODA2BggrBgEFBQcwAYYqaHR0cDovLzIxMC43NC40Mi4xMTo4MDg1L29jc3Bfc2VydmVyL29jc3AvMB8GA1UdIwQYMBaAFJo9tK5lWPvOWgV4JqBtKwSGusbsMAwGA1UdEwEB/wQCMAAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovLzIxMC43NC40Mi4zL09DQTMxL1JTQS9jcmw4OS5jcmwwDgYDVR0PAQH/BAQDAgbAMB0GA1UdDgQWBBSAsKx7L3tslIlUn7nm21OT5uzXfDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwDQYJKoZIhvcNAQELBQADggEBAIpP7adHCgrPoTGYLpZ4ENZO7t24G29ksaBd/BjmjEAAU1vqJkWPrrkgbr/llfpYJpMY/lYWUJFctNKp3TwU3ZMIKQ9fQAdi2mAPqWU8GBw/8C5FetBIBxB3g13C76KASgYCMTMTgPbdrRmFSyE0mOubcMwPC1g/S07TKsmGKMs5QaTZ36VAJU21fXXa/sqGeUSKzdmChoNkug8At+shnEU10ogSXfSv55lPGMISYeg7h3Hk2lwbOX0t6ugXgn6RjMDHqB5ZVDF0Kvrzmt++xFhTI5uyNk3t1Wr2Uz3MsDI4SNLcMu7EaTf8rrNPlu3/qsNCXufoIso3UVe56KRfqws=";
15 }

输出结果:

加签结果:fbolWDixTffN2oeMSpAUkbDvQ3ZXNeEUPgGOgQ3boCTIft34kIA8LtSwRMD+uAbKSk6vZffDb2Zro7IDGhS8lv35Bz23zs9j04GMB4d55EnjqjyRQAQer8fTujKMPHa2JUPjlUau6wjJaK50A8+TysC7Qq4uz69T0iXtTJPvFxwjCeXL0fShIuD4UQwJkQk7Mqqvzdy71dPs94EobMVEX84lSkfTwZKCwAR58NbYdgWWGKcwbU/N+riU6NyiCVr1rj+j9LqUrgW0HHDfp8hNcRm1lluGgk7BrjD7ZBpdYwuhbA1v2IGEsdhYVyMHdFpg6Ta3uoHoCJRJhtMp1Hw0qw==
验签结果: true

说明:

  一般rsa加密解密,加签验签都会与BASE64编码或url编码结合使用。

4.DES(对称加密)

DES(数据加密标准)原理

DES是一个分组加密算法,它以64位为分组对数据加密。64位一组的明文从算法的一端输入,64位的密文从另一段输出。它是一个对称算法:加密和解密用的是同一个算法。

密钥通常表示为64位的数,但每个第8位都用作奇偶校验,可以忽略,所以密钥长度为56位。密钥可以是任意的56位的数,且可在任意的时候改变。

DES算法只不过是加密的两个基本技术——混乱和扩散的组合,即先代替后置换,它基于密钥作用于明文,这是一轮(round),DES在明文分组上实施16轮相同的组合技术。

用于keychain本地存储钥匙串

加密、解密代码

pod ‘SSKeychain’

NSString *bundleID = [NSBundle mainBundle].bundleIdentifier;

[SSKeychain setPassword:@”111″ forService:bundleID account:@”ni”];

[SSKeychain setPassword:@”222″ forService:bundleID account:@”wo”];

[SSKeychain setPassword:@”333″ forService:bundleID account:@”ta”];

NSString *passwords = [SSKeychain passwordForService:bundleID
account:@”wo”];

NSLog(passwords);

加解密函数encrypt()

<?php
//$string:需要加密解密的字符串;$operation:判断是加密还是解密,E表示加密,D表示解密;$key:密匙
function encrypt($string,$operation,$key=''){ 
    $key=md5($key); 
    $key_length=strlen($key); 
      $string=$operation=='D'?base64_decode($string):substr(md5($string.$key),0,8).$string; 
    $string_length=strlen($string); 
    $rndkey=$box=array(); 
    $result=''; 
    for($i=0;$i<=255;$i++){ 
           $rndkey[$i]=ord($key[$i%$key_length]); 
        $box[$i]=$i; 
    } 
    for($j=$i=0;$i<256;$i++){ 
        $j=($j+$box[$i]+$rndkey[$i])%256; 
        $tmp=$box[$i]; 
        $box[$i]=$box[$j]; 
        $box[$j]=$tmp; 
    } 
    for($a=$j=$i=0;$i<$string_length;$i++){ 
        $a=($a+1)%256; 
        $j=($j+$box[$a])%256; 
        $tmp=$box[$a]; 
        $box[$a]=$box[$j]; 
        $box[$j]=$tmp; 
        $result.=chr(ord($string[$i])^($box[($box[$a]+$box[$j])%256])); 
    } 
    if($operation=='D'){ 
        if(substr($result,0,8)==substr(md5(substr($result,8).$key),0,8)){ 
            return substr($result,8); 
        }else{ 
            return''; 
        } 
    }else{ 
        return str_replace('=','',base64_encode($result)); 
    } 
}
?>

参考:

  1、

 

1
非对称加密算法 1.1 概述
1976年,美国学者Dime和Henman为解决信息公开传送和密钥管理问题,提出一种…

总结:对称加密分为 AES和DES,AES高级加密标准,DES数据加密标准。

一般使用都是将用户名和密码存储到本地。用于本地用户存储化。

对称加密就是需要一个公钥,拿着公钥去加密,并且拿着公钥去解密。带来问题是:一旦公钥被获取,就会被解密。

5.非对称加密

原理简介

RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥。公钥是可发布的供任何人使用,私钥则为自己所有,供解密之用。

解密者拥有私钥,并且将由私钥计算生成的公钥发布给加密者。加密都使用公钥进行加密,并将密文发送到解密者,解密者用私钥解密将密文解码为明文。

以甲要把信息发给乙为例,首先确定角色:甲为加密者,乙为解密者。首先由乙随机确定一个KEY,称之为密匙,将这个KEY始终保存在机器B中而不发出来;然后,由这个
KEY计算出另一个KEY,称之为公匙。这个公钥的特性是几乎不可能通过它自身计算出生成它的私钥。接下来通过网络把这个公钥传给甲,甲收到公钥后,利用公钥对信息加密,并把密文通过网络发送到乙,最后乙利用已知的私钥,就对密文进行解码了。以上就是RSA算法的工作流程。

简单说  甲利用公钥加密  乙利用随机key作为私钥

公钥是通过私钥生成,并且公钥几乎不能解析成私钥,公钥可以通过网络传输给甲,不用担心公钥被劫持。公钥是用来加密的。

私钥保存在服务器,可以使用私钥解密被公钥加密后的数据。

参考网站1

参考网站2

使用地方

支付宝RSA签名

iOS中使用RSA加密

总结:

可能会有人在不理解Base64编码的情况下,将其误用于数据加密或数据校验。

Base64是一种数据编码方式,目的是让数据符合传输协议的要求。标准Base64编码解码无需额外信息即完全可逆,即使你自己自定义字符集设计一种类Base64的编码方式用于数据加密,在多数场景下也较容易破解。

对于数据加密应该使用专门的目前还没有有效方式快速破解的加密算法。比如:对称加密算法AES-128-CBC,对称加密需要密钥,只要密钥没有泄露,通常难以破解;也可以使用非对称加密算法,如
RSA,利用极大整数因数分解的计算量极大这一特点,使得使用公钥加密的数据,只有使用私钥才能快速解密。

对于数据校验,也应该使用专门的消息认证码生成算法,如 HMAC –
一种使用单向散列函数构造消息认证码的方法,其过程是不可逆的、唯一确定的,并且使用密钥来生成认证码,其目的是防止数据在传输过程中被篡改或伪造。将原始数据与认证码一起传输,数据接收端将原始数据使用相同密钥和相同算法再次生成认证码,与原有认证码进行比对,校验数据的合法性。

可以看出MD5作用主要是用户数据校验;对称加密和非对称加密用于数据加密;base64是数据的编码方式。

以下是查看的链接

链接:

发表评论

电子邮件地址不会被公开。 必填项已用*标注