0

I'm creating an C# MVC application by calling Api, Its token encryption method is in PHP i want to convert it to C# code.Can any one help in conversion on below php code to c#?

PHP Code

<?php
//ini_set("display_errors", 1);
//ini_set("display_startup_errors", 1);
function encryptToken($token)
{  
    $cipher_method = 'aes-128-ctr';  
    $enc_key = openssl_digest

('*****************************', 'SHA256', TRUE);  
    $enc_iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher_method)); 
     $crypted_token = openssl_encrypt($token, $cipher_method, $enc_key, 0, $enc_iv) . "::" . bin2hex($enc_iv); 
      unset($token, $cipher_method, $enc_key, $enc_iv);  
      return $crypted_token; 
    }  
function createAccessToken(){ 
  //$date = new DateTime("now", new DateTimeZone('Asia/Kolkata') );  
 //$now = $date('YmdHis'); 
 $now = date("YmdHis");
 $secret ='********************************';  
 $plainText = $now."::".$secret;  
 $encrypted = encryptToken($plainText);  
 return $encrypted; 
} 

$value="";
if($_POST){
    if(isset($_POST['test'])){

         $value= createAccessToken();
    }
}
?>

So far i tried this much. But the token generated using this C# code will not validate in Api by using the same secret and password.

C# Code

   public string GenerateToken()
        {
            var Date = DateTime.Now.ToString("yyyyMMddHHmmss");
            var secret = "#############################";
            string plainText = Date + "::" + secret;
            var accessToken = EncryptString(plainText);
            return accessToken;
        }


public string EncryptString(string plainText)
    {
        try
        {
            string password = "************************";
            // Create sha256 hash
            SHA256 mySHA256 = SHA256Managed.Create();
            byte[] key = mySHA256.ComputeHash(Encoding.ASCII.GetBytes(password));
            // Instantiate a new Aes object to perform string symmetric encryption
            Aes encryptor = Aes.Create();
            encryptor.Mode = CipherMode.ECB;
            encryptor.Padding = PaddingMode.None;
            encryptor.BlockSize = 128;
            // Create secret IV
            var iv = generateIV();
            // Set key and IV
            byte[] aesKey = new byte[32];
            Array.Copy(key, 0, aesKey, 0, 32);
            encryptor.Key = aesKey;
            encryptor.IV = iv;

            // Instantiate a new MemoryStream object to contain the encrypted bytes
            MemoryStream memoryStream = new MemoryStream();

            // Instantiate a new encryptor from our Aes object
            ICryptoTransform aesEncryptor = encryptor.CreateEncryptor();

            // Instantiate a new CryptoStream object to process the data and write it to the 
            // memory stream
            CryptoStream cryptoStream = new CryptoStream(memoryStream, aesEncryptor, CryptoStreamMode.Write);

            // Convert the plainText string into a byte array
            byte[] plainBytes = Encoding.ASCII.GetBytes(plainText);

            // Encrypt the input plaintext string
            cryptoStream.Write(plainBytes, 0, plainBytes.Length);

            // Complete the encryption process
            cryptoStream.FlushFinalBlock();

            // Convert the encrypted data from a MemoryStream to a byte array
            byte[] cipherBytes = memoryStream.ToArray();

            // Close both the MemoryStream and the CryptoStream
            memoryStream.Close();
            cryptoStream.Close();

            // Convert the encrypted byte array to a base64 encoded string
            string cipherText = Convert.ToBase64String(cipherBytes, 0, cipherBytes.Length) + "::" + ByteArrayToString(iv);

            // Return the encrypted data as a string
            return cipherText;
        }
        catch (Exception)
        {

            throw;
        }
    }
    private static byte[] generateIV()
    {
        using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
        {
            byte[] nonce = new byte[IV_LENGTH];
            rng.GetBytes(nonce);
            return nonce;
        }
    }
  • What have you tried so far with C#? – Selim Yildiz Mar 20 '20 at 10:34
  • I added the C# code above.But the token generated is not validating in the API. But token generated using PHP code is validating in API. Am i missing something? – Linoy Joseph Mar 20 '20 at 10:47
  • I know that it is super annoying that C# doesn't even include CTR mode, but just trying ECB and then complaining that it doesn't work isn't doing it for me. Try BouncyCastle (note that it may be called SIC mode (Segmented Integer Counter) in there. As always, do try to set the IV to a value that is compatible with ECB mode. – Maarten Bodewes Mar 20 '20 at 11:08
  • To solve this issue a few years ago I added for loops and tried every combination of properties (Mode, Padding, BlockSize) to find answer. In this case I think it is the padding mode. What version of Net are you using? People are having issues with encryption in Net 4.7. I think it is a 32/64 issue. Do not believe the PHP comments. They may not be correct. If you use Fiddler is will try every combination of options and give you a output with the option that worked. So try capturing the php output with fiddler. – jdweng Mar 20 '20 at 11:09
  • @jdweng Is that stuff specific to CTR mode which is used in the PHP code or did you skip over that? Because CTR doesn't even use padding. – Maarten Bodewes Mar 20 '20 at 11:28
  • See my answer [here](https://stackoverflow.com/a/25388348/589259) – Maarten Bodewes Mar 20 '20 at 11:31
  • I do not know the internals of the Net library encryption nor do I have memorized the hundreds of combinations of properties for encryption to know which combinations are valid and which are not. And it is possible to use non standard combinations. Sometimes it is just easier to try every combination than to read through documentation that can take hours. – jdweng Mar 20 '20 at 12:41

0 Answers0