2

PHP code:

mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $to_encrypt, MCRYPT_MODE_ECB);

I need the corresponding powershell code which can produce the same result.

I have already tried ConvertTo-SecureString/ ConvertFrom-SecureString.

Powershell Code (Not producing correct encryption):

$api_code = "214e3854a1ec5433ae986d1e5d40c436"
$params = @{"controller" = $controller; "action"= $action;  "all"= $TRUE; }
[Byte[]] $key = $api_code[0..$api_code.length]
$param_object = $params | ConvertTo-SecureString -AsPlainText -Force
$param_aes = $param_object | ConvertFrom-SecureString -key $key

The encrypted string is coming out different. Is there a parameter that I am missing? Or Is there another module?

kira_111
  • 95
  • 8
  • 1
    SecureString has nothing in common with Rijndael / AES. It's a windows thing that uses DPAPI. You should instead look at using the .NET AesManaged class. – vcsjones Jun 23 '15 at 15:54
  • 2
    I've got no knowledge of PowerShell whatsoever, but judging by the `$param_aes` variable that you're using, you seem to be assuming that you need AES encryption ... However (and this is a common mistake), MCRYPT_RIJNDAEL_256 is NOT AES, only MCRYPT_RIJNDAEL_128 is. – Narf Jun 23 '15 at 15:57
  • @Narf So... the `256` in `MCRYPT_RIJNDAEL_256` refers to block size, not key length? – Mathias R. Jessen Jun 23 '15 at 16:20
  • 2
    @MathiasR.Jessen Yes, precisely. :) If you need AES-256, just use a 256-bit key with Rijndael-128. – Narf Jun 23 '15 at 16:23
  • Thanks for the discussion guys! Very helpful. I will try working with AesManaged class. If anyone has a good resource for implementing MCRYPT_RIJNDAEL_256 using AesManaged, please post it here. Actually I found it here: http://stackoverflow.com/a/14258619/2970271 – kira_111 Jun 23 '15 at 18:19
  • Actually the above link does the same encryption as ConvertTo-SecureString/ ConvertFrom-SecureString. Any help on this? – kira_111 Jun 23 '15 at 19:20
  • 1
    @kira_111 adapted a PowerShell equivalent from the `RijndaelManaged` documentation on MSDN, posted answer – Mathias R. Jessen Jun 23 '15 at 20:28
  • Thanks a lot Mathias! – kira_111 Jun 23 '15 at 21:26

1 Answers1

3

As pointed out in the comments, SecureStrings have nothing to do with the Rijndael specification, and MCRYPT_RIJNDAEL_256 is not the same as AES256 (which refer Rijndael-128 with a 256-bit key)

So, to solve your problem, we just need a function to encrypt a plaintext in ECB cipher mode using Rijndael with a block size of 256.

For this, the obvious choice is the RijndaelManaged class. Fortunately, the MSDN documentation provides a basic but fully functional example of how to use the RijndaelManaged class and a CryptoStream to encrypt and decrypt strings - all we need to do is rewrite it in PowerShell and change the block size and cipher mode:

function Encrypt-Rijndael256ECB {
    param(
        [byte[]]$Key,
        [string]$Plaintext
    )

    $RijndaelProvider = New-Object -TypeName System.Security.Cryptography.RijndaelManaged

    # Set block size to 256 to imitate MCRYPT_RIJNDAEL_256
    $RijndaelProvider.BlockSize = 256
    # Make sure we use ECB mode, or the generated IV will fuck up the first block upon decryption
    $RijndaelProvider.Mode      = [System.Security.Cryptography.CipherMode]::ECB
    $RijndaelProvider.Key       = $key

    # This object will take care of the actual cryptographic transformation
    $Encryptor = $RijndaelProvider.CreateEncryptor()

    # Set up a memorystream that we can write encrypted data back to
    $EncMemoryStream = New-Object System.IO.MemoryStream
    $EncCryptoStream = New-Object System.Security.Cryptography.CryptoStream -ArgumentList $EncMemoryStream,$Encryptor,"Write"
    $EncStreamWriter = New-Object System.IO.StreamWriter -ArgumentList $EncCryptoStream

    # When we write data back to the CryptoStream, it'll get encrypted and written back to the MemoryStream
    $EncStreamWriter.Write($Plaintext)

    # Close the writer
    $EncStreamWriter.Close()
    # Close the CryptoStream (pads and flushes any data still left in the buffer)
    $EncCryptoStream.Close()
    $EncMemoryStream.Close()

    # Read the encrypted message from the memory stream
    $Cipher     = $EncMemoryStream.ToArray() -as [byte[]]
    $CipherText = [convert]::ToBase64String($Cipher)

    # return base64 encoded encrypted string
    return $CipherText
}

The decryption process is almost the same, although this time we'll need to reverse it and read the cipher text back through the CryptoStream from the MemoryStream:

function Decrypt-Rijndael256ECB {
    param(
        [byte[]]$Key,
        [string]$CipherText
    )

    $RijndaelProvider = New-Object -TypeName System.Security.Cryptography.RijndaelManaged

    $RijndaelProvider.BlockSize = 256
    $RijndaelProvider.Mode      = [System.Security.Cryptography.CipherMode]::ECB
    $RijndaelProvider.Key       = $key

    $Decryptor = $RijndaelProvider.CreateDecryptor()

    # Reverse process: Base64Decode first, then populate memory stream with ciphertext and lastly read decrypted data through cryptostream
    $Cipher = [convert]::FromBase64String($CipherText) -as [byte[]]

    $DecMemoryStream = New-Object System.IO.MemoryStream -ArgumentList @(,$Cipher)
    $DecCryptoStream = New-Object System.Security.Cryptography.CryptoStream -ArgumentList $DecMemoryStream,$Decryptor,$([System.Security.Cryptography.CryptoStreamMode]::Read)
    $DecStreamWriter = New-Object System.IO.StreamReader -ArgumentList $DecCryptoStream

    $NewPlainText = $DecStreamWriter.ReadToEnd()

    $DecStreamWriter.Close()
    $DecCryptoStream.Close()
    $DecMemoryStream.Close()

    return $NewPlainText
}

Rijndael256 in action

Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206