我如何解码vb.net中的laravel加密字符串

发布于 2025-01-31 05:08:49 字数 522 浏览 2 评论 0 原文

我似乎找不到有关此问题的有效答案...

我正在使用内置的 crypt :: gencrypt() helper函数并传递简单字符串值(假设'abcde'出于本示例的目的) 如果我能提供帮助,我不想在Laravel中安装任何第三方库。我也有我的laravel app_key ,它是一个以 base64:开始的字符串值,但我不确定它的何处。

这为我生成了一个加密的字符串,我将其传递给VB.NET应用程序。 我无法锻炼如何简单地解码我的应用程序中的加密字符串,以删除'abcde''的原始密码。

我尝试了许多可以在线找到的示例,但是我一直遇到有关“不是有效键”或“不是有效的base64字符串”等的错误

。在.net?

我能做到的最好的是将加密的字符串分解为 iv value mac ,但我似乎无法进一步。

任何帮助将不胜感激。

I can't seem to find a valid answer to this issue...

I am encrypting a password in Laravel using the built in Crypt::encrypt() helper function and passing in a simple string value (let's say 'abcde' for the purpose of this example)
I don't want to install any 3rd party libraries in Laravel if I can help it. I also have my Laravel APP_KEY which is a string value starting with Base64:, but I'm not sure where this comes into it.

This generates me an encrypted string to which I pass down to a VB.Net application.
I cannot workout how to simply decode the encrypted string in my application to pluck out the raw password of 'abcde'.

I have tried many examples that I can find online, but I keep getting errors about "Not a valid key" or "Not a valid Base64 string", etc.

Does someone have an example of a code snippet that will decode a Laravel encrypted string in .Net?

The best I can get to is breaking the encrypted string down into iv, value and mac, but I can't seem to get any further.

Any help would be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

晨敛清荷 2025-02-07 05:08:49

文档

加密您可以使用加密助手加密值的值。
所有加密值均使用 openssl 进行加密
AES-256-CBC 密码。此外,所有加密值均使用消息身份验证代码(MAC)签名以检测任何修改
到加密字符串

开始开始,让我们看“内部” crypt file vendor/laravel/framework/src/src/inluminate/concryption/encrypter.php

class Encrypter implements EncrypterContract, StringEncrypter
{
     /**
     * The encryption key.
     *
     * @var string
     */
    protected $key;

    /**
     * The algorithm used for encryption.
     *
     * @var string
     */
    protected $cipher;
     /**
     * Create a new encrypter instance.
     *
     * @param  string  $key
     * @param  string  $cipher
     * @return void
     *
     * @throws \RuntimeException
     */
    public function __construct($key, $cipher = 'aes-128-cbc')
    {
        $key = (string) $key;

        if (! static::supported($key, $cipher)) {
            $ciphers = implode(', ', array_keys(self::$supportedCiphers));

            throw new RuntimeException("Unsupported cipher or incorrect key length. Supported ciphers are: {$ciphers}.");
        }

        $this->key = $key;
        $this->cipher = $cipher;
    }
...
}

param> param 键/code> in __构造方法是base64解码值(在调用中更深的地方)app_key的 .env .env 之后的文件:

//APP_KEY=base64:uk1lwVRJIWHaMkiGRcFIzAcTzzGaauYtMSy4L+0ViDk=
$key = base64decode('uk1lwVRJIWHaMkiGRcFIzAcTzzGaauYtMSy4L+0ViDk=');
// and then it passes into __construct method

cipher < /code>在 AES-256-CBC rel =“ nofollow noreferrer”> docs 需要提及,该部分在所有现有版本的Laravel(包括V9)(当时)中保持不变,

请接下来寻找加密以

/**
     * Encrypt the given value.
     *
     * @param  mixed  $value
     * @param  bool  $serialize
     * @return string
     *
     * @throws \Illuminate\Contracts\Encryption\EncryptException
     */
    public function encrypt($value, $serialize = true)
    {
        // openssl_cipher_iv_length for initialization vector (IV) is 16 bytes for AES-256-CBC
        $iv = random_bytes(openssl_cipher_iv_length(strtolower($this->cipher)));
        // not used in our case
        $tag = '';
        
        $value = self::$supportedCiphers[strtolower($this->cipher)]['aead']
            ? \openssl_encrypt(
                $serialize ? serialize($value) : $value,
                strtolower($this->cipher), $this->key, 0, $iv, $tag
            )
            : \openssl_encrypt(
                $serialize ? serialize($value) : $value,
                strtolower($this->cipher), $this->key, 0, $iv
            );

        if ($value === false) {
            throw new EncryptException('Could not encrypt the data.');
        }

        $iv = base64_encode($iv);
        $tag = base64_encode($tag);
        // not used in our case
        $mac = self::$supportedCiphers[strtolower($this->cipher)]['aead']
            ? '' // For AEAD-algoritms, the tag / MAC is returned by openssl_encrypt...
            : $this->hash($iv, $value);
        // here is a tricky part, pay attention that we didn't encode $value in base64
        $json = json_encode(compact('iv', 'value', 'mac', 'tag'), JSON_UNESCAPED_SLASHES);

        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new EncryptException('Could not encrypt the data.');
        }

        return base64_encode($json);
    }

在此处 获取操作订单我们有基本64编码的JSON数组,它具有base64编码 iv 未手动编码 value


c#part(解析JSON newtonsoft json ,.net472)

来自 Microsoft docs (此部分保持'as'是',因为

static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException("cipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;

            // Create an Aes object
            // with the specified key and IV.
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Mode = CipherMode.CBC; // this is defaul value
                aesAlg.Padding = PaddingMode.PKCS7; // this is default value                

                aesAlg.Key = Key;
                aesAlg.IV = IV;
                
                // Create a decryptor to perform the stream transform.
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {

                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {
                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.                            
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }

            return plaintext;
        }

​要绑所有这些东西,

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key">app_key from .env after :</param>
        /// <param name="encodedText">result of Crypt::encrypt($value) or Crypt::encryptString($value) methods</param>
        /// <returns>decoded string</returns>
        private string parse(string key, string encodedText)
        {   
            // getting bytes from app_key same as in laravel
            byte[] keyBytes = Convert.FromBase64String(key);             
            
            // going back step by step                     
            // getting from base64 json and getting array of values 
            byte[] dataBytes = Convert.FromBase64String(encodedText);
            string base64decodedData = Encoding.UTF8.GetString(dataBytes);

            var parts = JsonConvert.DeserializeObject<Dictionary<string, string>>(base64decodedData);
            // iv in laravel was encoded with base64 before packing, so undo
            byte[] iv = Convert.FromBase64String(parts["iv"]);            
            
            // and here is the tricky part i've mentioned in encryption method
            // in laravel docs - there were no manual encoding $value to base64
            // but to get valid bytes for decryption we need to treat parts["value"] as 
            // it was encoded
            byte[] valueBytes = Convert.FromBase64String(parts["value"]);

            return DecryptStringFromBytes_Aes(valueBytes, keyBytes, iv);

        }

需要说我并没有很努力地挖掘加密算法,甚至没有尝试此代码可以处理使用 $ mac param的algos,因此,如果某人想要要添加更多信息 - 欢迎您

docs

Encrypting A Value You may encrypt a value using the encrypt helper.
All encrypted values are encrypted using OpenSSL and the
AES-256-CBC cipher. Furthermore, all encrypted values are signed with a message authentication code (MAC) to detect any modifications
to the encrypted string

to begin let's look 'inside' Crypt facade in file vendor/laravel/framework/src/Illuminate /Encryption/Encrypter.php

class Encrypter implements EncrypterContract, StringEncrypter
{
     /**
     * The encryption key.
     *
     * @var string
     */
    protected $key;

    /**
     * The algorithm used for encryption.
     *
     * @var string
     */
    protected $cipher;
     /**
     * Create a new encrypter instance.
     *
     * @param  string  $key
     * @param  string  $cipher
     * @return void
     *
     * @throws \RuntimeException
     */
    public function __construct($key, $cipher = 'aes-128-cbc')
    {
        $key = (string) $key;

        if (! static::supported($key, $cipher)) {
            $ciphers = implode(', ', array_keys(self::$supportedCiphers));

            throw new RuntimeException("Unsupported cipher or incorrect key length. Supported ciphers are: {$ciphers}.");
        }

        $this->key = $key;
        $this->cipher = $cipher;
    }
...
}

param key in __construct method is base64 decoded value (somewhere deeper in calls) of APP_KEY from .env file after :

//APP_KEY=base64:uk1lwVRJIWHaMkiGRcFIzAcTzzGaauYtMSy4L+0ViDk=
$key = base64decode('uk1lwVRJIWHaMkiGRcFIzAcTzzGaauYtMSy4L+0ViDk=');
// and then it passes into __construct method

cipher also somewhere deeper is set to AES-256-CBC as mentioned in the docs (need to mention that this part stays the same across all existing versions of laravel including v9 at the moment)

next looking for encryption to get actions order

/**
     * Encrypt the given value.
     *
     * @param  mixed  $value
     * @param  bool  $serialize
     * @return string
     *
     * @throws \Illuminate\Contracts\Encryption\EncryptException
     */
    public function encrypt($value, $serialize = true)
    {
        // openssl_cipher_iv_length for initialization vector (IV) is 16 bytes for AES-256-CBC
        $iv = random_bytes(openssl_cipher_iv_length(strtolower($this->cipher)));
        // not used in our case
        $tag = '';
        
        $value = self::$supportedCiphers[strtolower($this->cipher)]['aead']
            ? \openssl_encrypt(
                $serialize ? serialize($value) : $value,
                strtolower($this->cipher), $this->key, 0, $iv, $tag
            )
            : \openssl_encrypt(
                $serialize ? serialize($value) : $value,
                strtolower($this->cipher), $this->key, 0, $iv
            );

        if ($value === false) {
            throw new EncryptException('Could not encrypt the data.');
        }

        $iv = base64_encode($iv);
        $tag = base64_encode($tag);
        // not used in our case
        $mac = self::$supportedCiphers[strtolower($this->cipher)]['aead']
            ? '' // For AEAD-algoritms, the tag / MAC is returned by openssl_encrypt...
            : $this->hash($iv, $value);
        // here is a tricky part, pay attention that we didn't encode $value in base64
        $json = json_encode(compact('iv', 'value', 'mac', 'tag'), JSON_UNESCAPED_SLASHES);

        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new EncryptException('Could not encrypt the data.');
        }

        return base64_encode($json);
    }

here we have base64 encoded json array with base64 encoded iv and not encoded manually value


c# part (to parse json newtonsoft json, .net472)

from microsoft docs (this part stays 'as is' because php uses same pkcs7 padding by default)

static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException("cipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;

            // Create an Aes object
            // with the specified key and IV.
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Mode = CipherMode.CBC; // this is defaul value
                aesAlg.Padding = PaddingMode.PKCS7; // this is default value                

                aesAlg.Key = Key;
                aesAlg.IV = IV;
                
                // Create a decryptor to perform the stream transform.
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {

                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {
                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.                            
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }

            return plaintext;
        }

and our working parse method to tie all this stuff

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key">app_key from .env after :</param>
        /// <param name="encodedText">result of Crypt::encrypt($value) or Crypt::encryptString($value) methods</param>
        /// <returns>decoded string</returns>
        private string parse(string key, string encodedText)
        {   
            // getting bytes from app_key same as in laravel
            byte[] keyBytes = Convert.FromBase64String(key);             
            
            // going back step by step                     
            // getting from base64 json and getting array of values 
            byte[] dataBytes = Convert.FromBase64String(encodedText);
            string base64decodedData = Encoding.UTF8.GetString(dataBytes);

            var parts = JsonConvert.DeserializeObject<Dictionary<string, string>>(base64decodedData);
            // iv in laravel was encoded with base64 before packing, so undo
            byte[] iv = Convert.FromBase64String(parts["iv"]);            
            
            // and here is the tricky part i've mentioned in encryption method
            // in laravel docs - there were no manual encoding $value to base64
            // but to get valid bytes for decryption we need to treat parts["value"] as 
            // it was encoded
            byte[] valueBytes = Convert.FromBase64String(parts["value"]);

            return DecryptStringFromBytes_Aes(valueBytes, keyBytes, iv);

        }

need to say that i didn't dig very hard into varians of encryption algos and didn't even try this code can deal with algos that uses $mac param, so if someone wants to add more info - you are welcome

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文