天天看點

【資訊安全_其他】JAVA(Android),PHP,IOS三平台RSA加解密互通算法

JAVA(Android),PHP,IOS三平台RSA加解密互通算法

RSA算法

RSA公開密鑰密碼體制。所謂的公開密鑰密碼體制就是使用不同的加密密鑰與解密密鑰,是一種“由已知加密密鑰推導出解密密鑰在計算上是不可行的”密碼體制。

在公開密鑰密碼體制中,加密密鑰(即公開密鑰)PK是公開資訊,而解密密鑰(即秘密密鑰)SK是需要保密的。加密算法E和解密算法D也都是公開的。雖然解密密鑰SK是由公開密鑰PK決定的,但卻不能根據PK計算出SK。

正是基于這種理論,1978年出現了著名的RSA算法,它通常是先生成一對RSA 密鑰,其中之一是保密密鑰,由使用者儲存;另一個為公開密鑰,可對外公開,甚至可在網絡伺服器中注冊。為提高保密強度,RSA密鑰至少為500位長,一般推薦使用1024位。這就使加密的計算量很大。為減少計算量,在傳送資訊時,常采用傳統加密方法與公開密鑰加密方法相結合的方式,即資訊采用改進的DES或IDEA對話密鑰加密,然後使用RSA密鑰加密對話密鑰和資訊摘要。對方收到資訊後,用不同的密鑰解密并可核對資訊摘要。

RSA算法是第一個能同時用于加密和數字簽名的算法,也易于了解和操作。RSA是被研究得最廣泛的公鑰算法,從提出到現今的三十多年裡,經曆了各種攻擊的考驗,逐漸為人們接受,普遍認為是目前最優秀的公鑰方案之一。

概述

RSA加解密主要實作公鑰加密,私鑰加密,公鑰解密,私鑰解密這四個方法。

RSA密鑰分為公鑰和私鑰,其中比較特殊的是JAVA的私鑰,PHP,IOS使用X509格式的密鑰,JAVA的公鑰使用X509格式,JAVA的私鑰使用PKCS8格式的私鑰(附件中private_key.pem)。

IOS和PHP加解密使用OpenSSL,JAVA使用Cipher類。

RSA加解密使用的密鑰長度是1024,待加密的位元組數不能超過密鑰的長度值除以 8 再減去 11,目前實作的是隻能處理117位資料。解密的密文最大長度為128。

三種語言都使用Base64編碼進行編碼。

IOS

IOS使用openssl,但是需要編譯生成靜态庫libssl.a和libcrypto.a,openssl.framework導入工程進行加解密操作。

公鑰加密

NSData *d = [encrypt dataUsingEncoding:NSUTF8StringEncoding];

int flen = [d length];

unsigned char from[flen];

bzero(from, sizeof(from));

memcpy(from, [d bytes], [d length]);

unsigned char to[128];

bzero(to, sizeof(to));

RSA *rsa_publickey = [self getPublicKeyByChar:key];

int bytes = RSA_public_encrypt(flen, from, to, rsa_publickey, RSA_PKCS1_PADDING);

NSData *result = [NSData dataWithBytes:to length:bytes];

RSA_free(rsa_publickey);

私鑰解密

RSA *rsa_privatekey = [self getPrivateKeyByChar:key];

NSData *data = [decrypt base64DecodedData];

int flen = [data length];

memcpy(from, [data bytes], [data length]);

int count = RSA_private_decrypt(flen, from, to, rsa_privatekey, RSA_PKCS1_PADDING);

RSA_free(rsa_privatekey);

然後将to轉為NSString

私鑰加密

int bytes = RSA_private_encrypt(flen, from, to, rsa_privatekey, RSA_PKCS1_PADDING);

公鑰解密

NSData *data = [decrypt base64DecodedData]; //base64

JAVA

使用Cipher;

加載公鑰

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); (RSAPublicKey) keyFactory.generatePublic(keySpec);

加載私鑰

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);

KeyFactory keyFactory = KeyFactory.getInstance(RSA);

(RSAPrivateKey) keyFactory.generatePrivate(keySpec);

Cipher cipher = Cipher.getInstance(RSA);

cipher.init(Cipher.DECRYPT_MODE, privateKey);

cipher.doFinal(encryptedData);

cipher.init(Cipher.DECRYPT_MODE, publicKey);

cipher.init(Cipher.ENCRYPT_MODE, privateKey);

cipher.doFinal(data);

cipher.init(Cipher.ENCRYPT_MODE, publicKey);

PHP

使用openssl。

使用openssl_private_encrypt; openssl_public_encrypt; openssl_private_decrypt; openssl_public_decrypt 這些方法進行加解密操作,padding使用預設OPENSSL_PKCS1_PADDING

參考資料

https://github.com/x2on/OpenSSL-for-iPhone http://blog.csdn.net/wangqiuyun/article/details/42143957/ http://php.net/manual/zh/ref.openssl.php