简体   繁体   中英

AES-256-CBC PKCS7 Padding from PHP to connect to a .NET server

I need to encrypt user and password with AES-256-CBC and PKCS7 padding to connect to a .NET server application that it is not mine.

Firstly, I got the public server key using Diffie-Hellman algorithm, following the instructions on this site:

https://doc.developer.milestonesys.com/mipsdkmobile/index.html?base=content_0.html&tree=tree_home.html

The code to get the public key from server is:

private const DH_PRIME = 'F488FD584E49DBCD20B49DE49107366B336C380D451D0F7C88B31C7C5B2D8EF6F3C923C043F0A55B188D8EBB558CB85D38D334FD7C175743A31D186CDE33212CB52AFF3CE1B1294018118D7C84A70A72D686C40319C807297ACA950CD9969FABD00A509B0246D3083D66A45D419F9C7CBD894B221926BAABA25EC355E92F78C7';
private const DH_GENERATOR = '02';

$privateKey = gmp_init(uniqid(), 32);
$publicKey = gmp_powm(self::DH_GENERATOR, $privateKey, base_convert( self::DH_PRIME, 16,10));

Once I got the key, so it is working great here, I must compute the server key with my private key, previously decoding base64 server key, and converting it from binary to hexadecimal:

// Decode server public returned key (encoded in base 64)
$serverPKBase64Decoded = base64_decode($apiResponse['response']['Command']['OutputParams']['Param']['7']['@attributes']['Value']);
$serverPublicKey16 = bin2hex($serverPKBase64Decoded);

// Calculate shared key
$prime = gmp_init(self::DH_PRIME,16);
$serverPk = gmp_init($serverPublicKey, 16);
$localPk = gmp_init($localPrivateKey,32);
$sharedKey = gmp_powm($serverPk, $localPk, $prime);

// Get shared key as hexadecimal value
$sharedKeyHex = gmp_strval($sharedKey, 16);

Now, it comes the part to get the initialization vector (iv) and the key to encrypt the username and password:

$iv = substr($sharedKeyHex,0,16);
$key = strlen($sharedKeyHex)-32,32);
// Encrypt username and password
$encryptedUsername = base64_encode(openssl_encrypt($username,$cipher,$key,OPENSSL_RAW_DATA,$iv));
$encryptedPassword = base64_encode(openssl_encrypt($password,$cipher,$key,OPENSSL_RAW_DATA,$iv));

When I send the data and got the response, it throws an error 16 with the text "Incorrect public key".

Our provider's SDK gives examples (on JS with CryptoJS) where the login process is equivalent. Please, could you confirm the code is equal in JS than in PHP:

JS Code:

/**
     * Encode a string using client and server public keys
     * 
     * @param       str         string      String to encode
     * @access                  public
     * @return                  string      Base64 encoded encrypted string
     */
    this.encodeString = function(str) {
        var secretString = this._sharedKey || this.getSharedKey().substring(0, 96);

        var key = CryptoJS.enc.Hex.parse(secretString.substring(32, 96)); 
        var iv = CryptoJS.enc.Hex.parse( secretString.substring(0,32) ); 
        
        var params = { 'iv': iv };
        if (XPMobileSDKSettings.defaultEncryptionPadding && CryptoJS.pad[XPMobileSDKSettings.defaultEncryptionPadding]) {
            params.padding = CryptoJS.pad[XPMobileSDKSettings.defaultEncryptionPadding];
        }
        return CryptoJS.AES.encrypt(str, key, params).ciphertext.toString(CryptoJS.enc.Base64);
    };

I have tested with many PADDINGS but I am not able to get it working. Any ideas why it is not working or what I must change to get it working?

您应该在您的用户名和密码前加上您自己的公钥,否则服务器无法计算共享密钥。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM