2014年1月21日星期二

RSA加密

這次需求是把用戶在網頁上輸入的文字加密送至後台解密。
  • 使用RSA演算法。
  • Key長度為2048bits。
  • 前台使用Javascript。
  • 後台使用Java。

首先產生加密解密時使用的Private Key及Public Key。
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(new RSAKeyGenParameterSpec(2048, RSAKeyGenParameterSpec.F4));

KeyPair kp = kpg.genKeyPair();
PublicKey publicKey = kp.getPublic();
PrivateKey privateKey = kp.getPrivate();
               
RSAPublicKeySpec pub = (RSAPublicKeySpec) fact.getKeySpec(publicKey, RSAPublicKeySpec.class);
BigInteger modulus = pub.getModulus();
System.out.println(modulus.toString(16));
System.out.println(Utils.byteArrayToBase64String(publicKey().getEncoded()));
System.out.println(Utils.byteArrayToBase64String(privateKey().getEncoded()));
Modulus
008FFAF9E528760E1B31324FC11D2ED0291589630D1F1FC954E67A2A82D28CA4BEAC2A41AACBBFB37F3E77A7C31F7AEC3D7A33699FB6C6D6E3AD2826702A5DAB928FBDEAB79EBB64287C56C4896ECC912D2FE831B8900B81F1653DA3DA2D1FE47E454456CAB9C877ED48BDD2C376E7AF82E620414CC2A019D0D7D01C0C2CD108C

Public Key
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCP+vnlKHYOGzEyT8EdLtApFYljDR8fyVTmeiqC0oykvqwqQarLv7N/Pnenwx967D16M2mftsbW460oJnAqXauSj73qt567ZCh8VsSJbsyRLS/oMbiQC4HxZT2j2i0f5H5FRFbKuch37Ui90sN256+C5iBBTMKgGdDX0BwMLNEIwwIDAQAB
-----END PUBLIC KEY-----
Private Key
-----BEGIN RSA PRIVATE KEY-----MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI/6+eUodg4bMTJPwR0u0CkViWMNHx/JVOZ6KoLSjKS+rCpBqsu/s38+d6fDH3rsPXozaZ+2xtbjrSgmcCpdq5KPveq3nrtkKHxWxIluzJEtL+gxuJALgfFlPaPaLR/kfkVEVsq5yHftSL3Sw3bnr4LmIEFMwqAZ0NfQHAws0QjDAgMBAAECgYAu9i2MESZwc24YeusCGcLLo7qsFBuSwphulGpJQWOeWJLPNZv/2Qcy+a0Nixc5gNSMhzhsX7F7ZceU0PTE3MiZB/+AW9ZIB5g8Yn9wlcugBfVpC9KtD4jEydLi00yhuKLEttKfrcEKRo4irl30e81RHVMhK3rBGsjmJUFUN1dcAQJBAMVVfGQRZR+pfuaMo5kOX8Ir09USkmDZ+0t+s9QeUtNKNWY9NFntfZnaaFVLvfzofe3KzLc+wJRKCKjgRuLRO38CQQC6yOfeAvGAqRkYH+ilgDsr6LC01+V/FtsNMufm1K5YblhgHq7lmGQB5KR6ZOjlY/2PqQSyTnP1T5zHuAQ6JeS9AkEAkLN78IEU7x/CD1tHx79TlrW+svrYXa7aZ+S0BzJpN8it2Ze94MeWl5Ahe5J78Y2mcg2JCkI4w0R6jyNOt5oIDwJAZ8hFfQfpo/FQ7iScoYiUWBtcQ79J1smeQMEuNQWrMZtuI0opJ4z61Ep0UUVMWliqhG4HHAOXTpBDrnzCbIStiQJAWvGE4DSlHYEsDnJTCfpEg7b8XGijMVIGOUG1JYqA+bjcq/+RfOCCJy5tsBlLw+BvG2mFispJ3PY7t4w9dhk8NQ==
-----END RSA PRIVATE KEY-----

頁面的Javascript加密方式使用Tom Wu提供的Demo作示範。

  • 在Plaintext輸入需加密的文字This is a test!
  • 在Public exponent (hex, F4=0x10001):輸入10001
  • 在Modulus (hex):輸入 008FFAF9E528760E1B31324FC11D2ED0291589630D1F1FC954E67A2A82D28CA4BEAC2A41AACBBFB37F3E77A7C31F7AEC3D7A33699FB6C6D6E3AD2826702A5DAB928FBDEAB79EBB64287C56C4896ECC912D2FE831B8900B81F1653DA3DA2D1FE47E454456CAB9C877ED48BDD2C376E7AF82E620414CC2A019D0D7D01C0C2CD108C
  • 按Encrypt得到加密後的值(base64)。(例︰  Y0OOWkCHB8HXOv1J7DbBSp1TGEiuR58AxqewXbjH1FTGJ9c2n/czN8/y1FDfxrpdNvIRyPL8B6nePqyL5xvp+VJUUfEGmYpOQy4oMh6S0lJB01yJwyHkznZSaaO1WFPRjC8xbq02FSRNBvjlFAeHGrUC7WxrqnBMKPintDC7weY=)

後台得到加密後文字進行解密
String priKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI/6+eUodg4bMTJPwR0u0CkViWMNHx/JVOZ6KoLSjKS+rCpBqsu/s38+d6fDH3rsPXozaZ+2xtbjrSgmcCpdq5KPveq3nrtkKHxWxIluzJEtL+gxuJALgfFlPaPaLR/kfkVEVsq5yHftSL3Sw3bnr4LmIEFMwqAZ0NfQHAws0QjDAgMBAAECgYAu9i2MESZwc24YeusCGcLLo7qsFBuSwphulGpJQWOeWJLPNZv/2Qcy+a0Nixc5gNSMhzhsX7F7ZceU0PTE3MiZB/+AW9ZIB5g8Yn9wlcugBfVpC9KtD4jEydLi00yhuKLEttKfrcEKRo4irl30e81RHVMhK3rBGsjmJUFUN1dcAQJBAMVVfGQRZR+pfuaMo5kOX8Ir09USkmDZ+0t+s9QeUtNKNWY9NFntfZnaaFVLvfzofe3KzLc+wJRKCKjgRuLRO38CQQC6yOfeAvGAqRkYH+ilgDsr6LC01+V/FtsNMufm1K5YblhgHq7lmGQB5KR6ZOjlY/2PqQSyTnP1T5zHuAQ6JeS9AkEAkLN78IEU7x/CD1tHx79TlrW+svrYXa7aZ+S0BzJpN8it2Ze94MeWl5Ahe5J78Y2mcg2JCkI4w0R6jyNOt5oIDwJAZ8hFfQfpo/FQ7iScoYiUWBtcQ79J1smeQMEuNQWrMZtuI0opJ4z61Ep0UUVMWliqhG4HHAOXTpBDrnzCbIStiQJAWvGE4DSlHYEsDnJTCfpEg7b8XGijMVIGOUG1JYqA+bjcq/+RfOCCJy5tsBlLw+BvG2mFispJ3PY7t4w9dhk8NQ=="

// don't use this for real projects!
BASE64Decoder decoder = new BASE64Decoder();
keyBytes = decoder.decodeBuffer(priKey);

PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(spec);

Cipher cipher = Cipher.getInstance("RSA");
byte[] dec = Utils.base64StringToByteArray(ciphertext);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decrypted = cipher.doFinal(dec);
System.out.println(new String(decrypted, "UTF-8"));
解密結果
This is a test!

使用OpenSSL檢視PublicKey.pem及PrivateKey.pem
openssl rsa -in public.pem -pubin -text -noout
openssl rsa -in private.pem -text -noout
openssl rsa -in private.pem -modulus -noout

參考連結
http://www-cs-students.stanford.edu/~tjw/jsbn/
http://cryptojs.altervista.org/
http://cryptojs.altervista.org/publickey/doc/doc_rsa_java.html

沒有留言:

發佈留言