Secure communication PHP (phpseclib) and C# (Unity 3D)

后端 未结 2 1382
故里飘歌
故里飘歌 2021-01-05 23:43

im trying to establish secure RSA connection between PHP server and Unity 3D game (in Web Player). At the end of process $rsa->decrypt() return \"false\" :-(

Server

相关标签:
2条回答
  • 2021-01-05 23:54

    SOLVED!

    By another way - XML key format

    Server code:

    $rsa = new Crypt_RSA();
    $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
    $rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_XML);
    $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_XML);
    
    $keys = $rsa->createKey(1024);
    extract($keys);
    $rsa->loadKey($publickey);
    $_SESSION["privatekey"] = $privatekey;
    $this->payload->publickey = $publickey;
    

    Generate JSON:

    {"publickey":"<RSAKeyValue>\r\n  <Modulus>sCL/O7uUl4T32nUxZhKj1svDG88k4jkGsh/7IiFX/kTbj3mXmtYPLn5xTyLxEt9FxA/aoVxBmh1k7wA7lvcu5z4Avw6+AA/j793iDEhGdfvmXmHxm05xkjYO+LZ449YGDst9DUDO8SDA948Rld+eA187d/nhVPPAmun7RbLXBrs=</Modulus>\r\n  <Exponent>AQAB</Exponent>\r\n</RSAKeyValue>"}
    

    Unity Web Player code:

    var N = JSON.Parse (generatedJSON);
    var csp = new RSACryptoServiceProvider(1024);
    csp.FromXmlString (N ["publickey"]);
    var plainTextData = "Hello from Web Player";
    var bytesPlainTextData = System.Text.Encoding.Unicode.GetBytes(plainTextData);
    var bytesCypherText = csp.Encrypt(bytesPlainTextData, false);
    var cypherText = Convert.ToBase64String(bytesCypherText);
    

    And finally Server Decryption:

    $rsa = new Crypt_RSA();
    $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
    $rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_XML);
    $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_XML);
    
    $rsa->loadKey($_SESSION["privatekey"]);
    $cypherText= $_POST["cypherText"];
    $bytesCipherText = base64_decode($message);
    $this->payload->encrypted = $rsa->decrypt($bytesCipherText);
    

    And you get JSON:

    {"message":"Hello from Web Player"}
    

    Thanks for perfect phpsec library! Its epic!

    0 讨论(0)
  • 2021-01-06 00:05

    I share my example Unity project here. Hoping that it is useful to some people ;)

    GitHub: unity-php-secure-communication

    <?php
    <?php
    /**
     * test with curl:
     *
     *  // Generate keypair : return XML public key
     *  curl -c cookies.txt -d "keygen=1" http://exemple.com//encrypt.php
     *
     *  // Test encrypt/decrypt : return encrypted and decrypted `my text to encode`
     *  curl -b cookies.txt -d "test=my text to encode" http://exemple.com//encrypt.php
     *
     *  // Test encrypt : return encrypted
     *  curl -b cookie.txt -d "encrypt=my text to encode" http://exemple.com//encrypt.php > encrypted.txt; cat encrypted.txt
     *
     *  // Test decrypt : return decrypted `my text to encode`
     *  curl -b cookie.txt -d "decrypt=`cat encrypted.txt`" http://exemple.com//encrypt.php
     */
    
    include 'vendor/autoload.php';
    use phpseclib\Crypt\RSA;
    
    function generateKeyPair(){
        if (!isset($_SESSION['publickey'])){
            $rsa = new RSA();
            $rsa->setPrivateKeyFormat(RSA::PRIVATE_FORMAT_XML);
            $rsa->setPublicKeyFormat(RSA::PUBLIC_FORMAT_XML);
            $keys = $rsa->createKey();
            $_SESSION['privatekey'] = $keys['privatekey'];
            $_SESSION['publickey'] = $keys['publickey'];
        }
        return $_SESSION['publickey'];
    }
    
    function encrypt($cleartext){
        $rsa = new RSA();
        $rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1);
        $rsa->setPublicKeyFormat(RSA::PUBLIC_FORMAT_XML);
        $rsa->loadKey($_SESSION['publickey']);
        $bytesCipherText = $rsa->encrypt($cleartext);
        return rawurlencode(base64_encode($bytesCipherText));
    }
    
    function decrypt($encrypted){
        $rsa = new RSA();
        $rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1);
        $rsa->setPrivateKeyFormat(RSA::PRIVATE_FORMAT_XML);
        $rsa->loadKey($_SESSION['privatekey']);
        $bytesCipherText = base64_decode(rawurldecode($encrypted));
        return $rsa->decrypt($bytesCipherText);
    }
    
    if (isset($_POST['session_id'])) {
        session_id($_POST['session_id']);
    }
    session_start();
    
    if (isset($_POST['keygen'])) {
        echo generateKeyPair();
        exit();
    }
    
    if (isset($_POST['encrypt'])) {
        echo encrypt($_POST['encrypt']);
        exit();
    }
    
    if (isset($_POST['decrypt'])) {
        echo decrypt($_POST['decrypt']);
        exit();
    }
    
    if (isset($_POST['test'])) {
        generateKeyPair();
        $ciphertext = encrypt($_POST['test']);
        echo "encrypted: $ciphertext\n\n";
        $clearText = decrypt($ciphertext);
        echo "decrypted: $clearText\n";
        exit();
    }
    
    using System;
    using System.Collections;
    using System.Security.Cryptography;
    using System.Text;
    using UnityEngine;
    using UnityEngine.Analytics;
    using UnityEngine.Networking;
    using UnityEngine.UI;
    
    
    public class EncryptController : MonoBehaviour
    {
        public string ScriptUrl = "http://example.com/encrypt.php";
    
        public InputField ClearTextInputField;
        public InputField EncryptedTextInputField;
        public InputField ClearResponseInputField;
    
        public Text SessionIdText;
        public Text PublicKeyText;
    
        public void OnKeygenButtonClick()
        {
            StartCoroutine(GenerateRsaKeyPair());
        }
    
        public void OnEncryptButtonClick()
        {
            if (PublicKeyText.text.Length < 100)
            {
                Debug.LogError("You must generate RSA key pair before");
                return;
            }
            var csp = new RSACryptoServiceProvider(1024);
            csp.FromXmlString(PublicKeyText.text);
            var plainTextData = ClearTextInputField.text;
            var bytesPlainTextData = Encoding.Unicode.GetBytes(plainTextData);
            var bytesCypherText = csp.Encrypt(bytesPlainTextData, false);
            var cypherText = Convert.ToBase64String(bytesCypherText);
            EncryptedTextInputField.text = cypherText;
        }
    
        public void OnDecryptButtonClick()
        {
            if (PublicKeyText.text.Length < 100)
            {
                Debug.LogError("You must generate RSA key pair before");
                return;
            }
            StartCoroutine(SendEncryptedText(EncryptedTextInputField.text));
        }
    
        IEnumerator GenerateRsaKeyPair()
        {
            var form = new WWWForm();
            form.AddField("keygen", 1);
            form.AddField("session_id", AnalyticsSessionInfo.sessionId.ToString());
            SessionIdText.text = "sessionId=" + AnalyticsSessionInfo.sessionId.ToString();
    
            using (var www = UnityWebRequest.Post(ScriptUrl, form))
            {
                yield return www.SendWebRequest();
    
                if (www.isNetworkError)
                {
                    Debug.LogError(www.error);
                }
                else
                {
                    LogHeaders(www);
    
                    Debug.Log(www.downloadHandler.text);
                    PublicKeyText.text = www.downloadHandler.text;
                }
            }
        }
    
        IEnumerator SendEncryptedText(string text)
        {
            var form = new WWWForm();
            form.AddField("decrypt", text);
            form.AddField("session_id", AnalyticsSessionInfo.sessionId.ToString());
            SessionIdText.text = "sessionId=" + AnalyticsSessionInfo.sessionId.ToString();
    
            using (var www = UnityWebRequest.Post(ScriptUrl, form))
            {
                //www.SetRequestHeader("cookie", SessionIdText.text);
                yield return www.SendWebRequest();
    
                if (www.isNetworkError)
                {
                    Debug.LogError(www.error);
                }
                else
                {
                    LogHeaders(www);
    
                    // Print Body
                    Debug.Log(www.downloadHandler.text);
                    ClearResponseInputField.text = www.downloadHandler.text;
                }
            }
        }
    
        private void LogHeaders(UnityWebRequest www)
        {
            var sb = new StringBuilder();
            foreach (var dict in www.GetResponseHeaders())
            {
                sb.Append(dict.Key).Append(": \t[").Append(dict.Value).Append("]\n");
    
                if (dict.Key == "Set-Cookie")
                {
                    SessionIdText.text = dict.Value + " (from response headers)";
                }
            }
            Debug.Log(sb.ToString());
        }
    }
    
    0 讨论(0)
提交回复
热议问题