2013-03-26 7 views
9

मेरे पास PHP में एक वेब-सेवा है जो एक संदेश एन्क्रिप्ट करने के लिए एक कीपैयर उत्पन्न करती है, और जावा में एक एप्लिकेशन जो निजीकी को पुनर्प्राप्त करता है और संदेश को डिक्रिप्ट करता है।एन्क्रिप्शन PHP, डिक्रिप्शन जावा

php मैं http://phpseclib.sourceforge.net/ उपयोग कर रहा हूँ और इस दो फ़ाइलों के लिए:

keypair.php

<?php 

set_time_limit(0); 
if(file_exists('private.key')) 
{ 
    echo file_get_contents('private.key'); 
} 
else 
{ 
    include('Crypt/RSA.php'); 
    $rsa = new Crypt_RSA(); 
    $rsa->createKey(); 
    $res = $rsa->createKey(); 

    $privateKey = $res['privatekey']; 
    $publicKey = $res['publickey']; 

    file_put_contents('public.key', $publicKey); 
    file_put_contents('private.key', $privateKey); 
} 

?> 

encrypt.php

<?php 

include('Crypt/RSA.php'); 

//header("Content-type: text/plain"); 

set_time_limit(0); 
$rsa = new Crypt_RSA(); 
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_OAEP); 
$rsa->loadKey(file_get_contents('public.key')); // public key 

$plaintext = 'Hello World!'; 
$ciphertext = $rsa->encrypt($plaintext); 

echo base64_encode($ciphertext); 

?> 

और जावा में मैं इस कोड है:

package com.example.app; 

import java.io.DataInputStream; 
import java.net.URL; 
import java.security.Security; 

import javax.crypto.Cipher; 
import javax.crypto.spec.SecretKeySpec; 

import sun.misc.BASE64Decoder; 

public class MainClass { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) 
    { 
     Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); 

     try { 
      BASE64Decoder decoder = new BASE64Decoder(); 
      String b64PrivateKey = getContents("http://localhost/api/keypair.php").trim(); 
      String b64EncryptedStr = getContents("http://localhost/api/encrypt.php").trim(); 

      System.out.println("PrivateKey (b64): " + b64PrivateKey); 
      System.out.println(" Encrypted (b64): " + b64EncryptedStr); 

      SecretKeySpec privateKey = new SecretKeySpec(decoder.decodeBuffer(b64PrivateKey) , "AES"); 
      Cipher cipher    = Cipher.getInstance("RSA/None/OAEPWithSHA1AndMGF1Padding", "BC"); 
      cipher.init(Cipher.DECRYPT_MODE, privateKey); 

      byte[] plainText   = decoder.decodeBuffer(b64EncryptedStr); 

      System.out.println("   Message: " + plainText); 
     } 
     catch(Exception e) 
     { 
      System.out.println("   Error: " + e.getMessage()); 
     } 

    } 

    public static String getContents(String url) 
    { 
     try { 
      String result = ""; 
      String line; 
      URL u = new URL(url); 
      DataInputStream theHTML = new DataInputStream(u.openStream()); 
      while ((line = theHTML.readLine()) != null) 
       result = result + "\n" + line; 

      return result; 
     } 
     catch(Exception e){} 

     return ""; 
    } 
} 

मेरे प्रश्न हैं:

  1. मुझे "आरएसए कुंजी नहीं" कहने का अपवाद क्यों है?
  2. मैं इस कोड को कैसे सुधार सकता हूं? मैंने जावा और PHP के बीच एन्कोडिंग और कम्यूनिकेशन त्रुटियों से बचने के लिए बेस 64 का उपयोग किया है।
  3. यह अवधारणा सही है? मेरा मतलब है, मैं इसे सही तरीके से उपयोग कर रहा हूँ?
+0

क्या पूर्व-बेस 64 डेटा डीकोडेड बेस 64 डेटा से मेल खाता है? –

+0

हां, मैंने अभी इसका परीक्षण किया है, और बेस 64 के साथ डीकोड किए जाने के बाद PHP और जावा स्ट्रिंग का md5 चेकसम समान है। –

+1

शायद मेरा SecretKeySpec गलत है? मैंने बिना सफलता के एल्गोरिदम के मूल्य को बदलने की कोशिश की है। –

उत्तर

4

उपर्युक्त उत्तर की सहायता से, मुझे पता चला कि गुप्तकिस्पेक गलत इस्तेमाल किया गया है, और मैंने पाया कि ओपनएसएसएल से पीईएम फ़ाइल 'स्टैंडएट प्रारूप' नहीं है, इसलिए मुझे इसे PEMReader को निजीकी क्लास में बदलने के लिए उपयोग करने की आवश्यकता है।

package com.example.app; 

import java.io.BufferedReader; 
import java.io.DataInputStream; 
import java.io.StringReader; 
import java.net.URL; 
import java.security.KeyPair; 
import java.security.PrivateKey; 
import java.security.Security; 

import javax.crypto.Cipher; 

import org.bouncycastle.openssl.PEMReader; 

import sun.misc.BASE64Decoder; 

public class MainClass { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) 
    { 
     Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); 

     try { 
      BASE64Decoder decoder = new BASE64Decoder(); 
      String b64PrivateKey = getContents("http://localhost/api/keypair.php").trim(); 
      String b64EncryptedStr = getContents("http://localhost/api/encrypt.php").trim(); 

      System.out.println("PrivateKey (b64): " + b64PrivateKey); 
      System.out.println(" Encrypted (b64): " + b64EncryptedStr); 

      byte[] decodedKey   = decoder.decodeBuffer(b64PrivateKey); 
      byte[] decodedStr   = decoder.decodeBuffer(b64EncryptedStr); 
      PrivateKey privateKey  = strToPrivateKey(new String(decodedKey)); 

      Cipher cipher    = Cipher.getInstance("RSA/None/OAEPWithSHA1AndMGF1Padding", "BC"); 
      cipher.init(Cipher.DECRYPT_MODE, privateKey); 


      byte[] plainText   = cipher.doFinal(decodedStr); 

      System.out.println("   Message: " + new String(plainText)); 
     } 
     catch(Exception e) 
     { 
      System.out.println("   Error: " + e.getMessage()); 
     } 

    } 

    public static String getContents(String url) 
    { 
     try { 
      String result = ""; 
      String line; 
      URL u = new URL(url); 
      DataInputStream theHTML = new DataInputStream(u.openStream()); 
      while ((line = theHTML.readLine()) != null) 
       result = result + "\n" + line; 

      return result; 
     } 
     catch(Exception e){} 

     return ""; 
    } 

    public static PrivateKey strToPrivateKey(String s) 
    { 
     try { 
      BufferedReader br = new BufferedReader(new StringReader(s)); 
      PEMReader pr  = new PEMReader(br); 
      KeyPair kp   = (KeyPair)pr.readObject(); 
      pr.close(); 
      return kp.getPrivate(); 
     } 
     catch(Exception e) 
     { 

     } 

     return null; 
    } 
} 

यहाँ मेरी keypair.php

<?php 

set_time_limit(0); 
if(file_exists('private.key')) 
{ 
    echo base64_encode(file_get_contents('private.key')); 
} 
else 
{ 
    include('Crypt/RSA.php'); 

    $rsa = new Crypt_RSA(); 
    $rsa->setHash('sha1'); 
    $rsa->setMGFHash('sha1'); 
    $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_OAEP); 
    $rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1); 
    $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1); 

    $res = $rsa->createKey(1024); 

    $privateKey = $res['privatekey']; 
    $publicKey = $res['publickey']; 

    file_put_contents('public.key', $publicKey); 
    file_put_contents('private.key', $privateKey); 

    echo base64_encode($privateKey); 
} 

?> 

है और मेरी encrypt.php

<?php 
    include('Crypt/RSA.php'); 
    set_time_limit(0); 

    $rsa = new Crypt_RSA(); 
    $rsa->setHash('sha1'); 
    $rsa->setMGFHash('sha1'); 
    $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_OAEP); 

    $rsa->loadKey(file_get_contents('public.key')); // public key 

    $plaintext = 'Hello World!'; 
    $ciphertext = $rsa->encrypt($plaintext); 
    $md5  = md5($ciphertext); 
    file_put_contents('md5.txt', $md5); 
    file_put_contents('encrypted.txt', base64_encode($ciphertext)); 

    echo base64_encode($ciphertext); 

?> 

मुझे आशा है कि यह किसी को भी और धन्यवाद मदद करता है:

यहाँ मेरी श्रमिक वर्ग है।

+0

आपका कोड सबसे अच्छा है जो मुझे मिल सकता है। समस्या यह है कि, मैं BouncyCastleProvider पंजीकृत नहीं कर सकता। मुझे निम्न त्रुटि मिलती है "त्रुटि: जेसीई प्रदाता बीसी को प्रमाणित नहीं कर सकता" – MrD

3

कुछ विचार।

  1. क्या आप अन्यथा भी $ निजीकी को प्रतिबिंबित नहीं करना चाहिए?

  2. क्या आप phpseclib का नवीनतम गिट संस्करण उपयोग कर रहे हैं? मैं पूछता हूँ क्योंकि कुछ समय पहले हुई थी इस लिए प्रतिबद्ध:

    https://github.com/phpseclib/phpseclib/commit/e4ccaef7bf74833891386232946d2168a9e2fce2#phpseclib/Crypt/RSA.php

    प्रतिबद्ध https://stackoverflow.com/a/13908986/569976

  3. से प्रेरित था अगर आप bouncycastle और phpseclib शामिल करने के लिए थोड़ा अपने टैग बदलने के सार्थक हो सकता है। मैं उन टैग को जोड़ूंगा लेकिन कुछ टैग्स को हटा दिया जाना चाहिए क्योंकि आप पहले से ही 5 की सीमा पर हैं। मैं आपको यह तय करने दूंगा कि कौन से लोगों को निकालना है (यदि आप इसे भी करना चाहते हैं)।

+0

मैं phpseclib के गिट संस्करण का उपयोग कर रहा हूं और मैंने अपने प्रश्न के टैग बदल दिए हैं। मैंने अपना मुख्य रूप थोड़ा स्पष्ट करने के लिए बदल दिया है: –

1

मैंने आपके द्वारा उपयोग की जा रही कक्षाओं में कुछ खुदाई की है और ऐसा लगता है कि आपने जो पोस्ट किया है, वह आपके स्पष्ट पैरामीटर से मेल खाने वाले अधिकांश डिफ़ॉल्ट पैरामीटर हैं। हालांकि, यह सुनिश्चित नहीं करता है कि यदि आप पुराने कार्यान्वयन का उपयोग कर रहे हैं तो आपके कॉन्फ़िगरेशन में वे सभी मौजूदा दस्तावेज़ों से मेल खाते हैं।

इसके अलावा, एक वरिष्ठ फेसबुक सुरक्षा अभियंता की एक नोक ने हाल ही में एक व्याख्यान में इसी तरह की एक मुद्दे पर चर्चा की; एक ही सुरक्षा प्रोटोकॉल को लागू करने वाले विभिन्न पुस्तकालय कई बार असंगत होंगे और यहां तक ​​कि विभिन्न वातावरण या भाषाओं में समान पुस्तकालय भी कई बार काम करने में असफल हो जाएंगे। इस बात को ध्यान में रखते हुए, कुछ चीजों को यह सुनिश्चित करने का प्रयास किया गया है कि आपके सेटअप के समान काम करने वाले उदाहरण ऑनलाइन मौजूद हैं:

सुनिश्चित करें कि आप पुस्तकालयों के नवीनतम संस्करणों का उपयोग कर रहे हैं। यह भी ध्यान रखें कि कुछ जावएक्स फ़ंक्शंस और कक्षाओं को बहिष्कृत किया गया है और अब java.security का उपयोग करने का सुझाव दिया गया है (यह जांच नहीं की गई है कि यह आपके मामले पर लागू होता है)।

कुंजी आकार को लगातार बनाए रखने के लिए मजबूर करें (1024 या 2048)।जावा कार्यान्वयन या तो कर सकता है और मुझे दोनों पुस्तकालयों के लिए निरंतर दस्तावेज नहीं मिला है कि आपके कॉन्फ़िगरेशन डिफ़ॉल्ट का उपयोग किया जाएगा (समस्या # 2 हो सकती है, हालांकि आपको अमान्य कुंजी आकार के लिए एक अलग अपवाद मिल सकता है)।

सुनिश्चित करें कि आपकी निजीकी अपेक्षाओं से मेल खाती है (लंबाई/जावा और PHP के बीच समान होती है)।

डिफ़ॉल्ट मानों को स्पष्ट रूप से परिभाषित करने के लिए मजबूर करें (CryptRSA हैश sha1, कुंजी लंबाई, कुछ भी जिसे आप स्पष्ट रूप से सेट कर सकते हैं) सेट करें।

जावा और php दोनों के साथ एक ही संदेश को एन्क्रिप्ट करने का प्रयास करें ताकि आप यह देख सकें कि आप एक ही आउटपुट प्राप्त कर सकते हैं या नहीं। यह सुनिश्चित करने के बाद कि आपकी कुंजी एक ही पढ़ी जाए और दोनों अनुप्रयोगों में उपयोग किए जाने पर अपवाद फेंक न दें। एक वर्ण को एन्क्रिप्ट करने से आपको यह बताने में मदद मिल सकती है कि क्या वही पैडिंग योजना वास्तव में उपयोग की जा रही है (यह स्रोत कोड से दिखाई देता है जो दोनों एमजीएफ 1 का उपयोग करते हैं, लेकिन आउटपुट की जांच करने में कभी दर्द नहीं होता है)।

आखिर में php से जावा एन्क्रिप्शन के लिए एक उदाहरण लेने का प्रयास करें, जिसे पहले से ही काम करने के लिए कहा जाता है और जब तक आप अपनी वर्तमान एन्क्रिप्शन योजना पर वापस नहीं आ जाते हैं तब तक एक बदलाव करते हैं। मैंने कुछ उदाहरणों को जल्दी से googling देखा जो CryptRSA और जावा सुरक्षा के साथ विभिन्न मानकों और सेटिंग्स का इस्तेमाल किया जो कहा कि वे एक साथ काम कर रहे थे। एक काम उदाहरण लें और हैश फंक्शन और फिर एन्क्रिप्शन की अदला-बदली की कोशिश, आदि

2
SecretKeySpec privateKey = new SecretKeySpec(decoder.decodeBuffer(b64PrivateKey) , "AES"); 

b64PrivateKey निजी कुंजी सही को रोकने के लिए माना जाता है? 'इसे डॉक्स में देखकर ऐसा लगता है जैसे SecretKeySpec केवल सममित एल्गोरिदम (जैसे एईएस) के लिए है - आरएसए जैसे असममित नहीं।

संबंधित मुद्दे