Why I'm getting different results in C# and Python - python

I'm struggling to encode a string to SHA-256 with a specific key.
There is a python code that is used a reference.
The problem is that I cannot achieve the same result in C#.
import base64
import hmac
import hashlib
# Base64 encoded key (get it with /hook/{hookId}/key request)
webhook_key_base64 = 'JcyVhjHCvHQwufz+IHXolyqHgEc5MoayBfParl6Guoc='
# notification parameters
data = '643|1|IN|+79165238345|13353941550'
webhook_key = base64.b64decode(s))
print(hmac.new(webhook_key, data.encode('utf-8'), hashlib.sha256).hexdigest())
C#
public class Program
{
public static void Main()
{
var key = "JcyVhjHCvHQwufz+IHXolyqHgEc5MoayBfParl6Guoc=";
var message = "643|1|IN|+79165238345|13353941550";
var decodedKey = Base64Decode(key);
var result = HmacSha256Digest(message, decodedKey);
Console.WriteLine(result);
Console.ReadLine();
}
private static string HmacSha256Digest(string message, string secret)
{
var keyBytes = Encoding.UTF8.GetBytes(secret);
var messageBytes = Encoding.UTF8.GetBytes(message);
var cryptographer = new HMACSHA256(keyBytes);
var bytes = cryptographer.ComputeHash(messageBytes);
return BitConverter.ToString(bytes).Replace("-", "").ToLower();
}
private static string Base64Decode(string base64EncodedData)
{
var base64EncodedBytes = Convert.FromBase64String(base64EncodedData);
return Encoding.UTF8.GetString(base64EncodedBytes);
}
}
What could be wrong?
Thanks

Related

Extract zip file inline in Oracle OCI - Object Storage without downloading to save time

Is it possible to extract a zip file 'inline' which is in cloud say Oracle cloud, Object storage. Meaning, without downloading it and extracting it in the o/s and re-uploading it to object storage, because the file size is big and we need to save time on upload/download.. Any sample code, with Oracle Functions, or python, java etc. ? Is it possible ? I tried with S3 browser/explorer or other similar tools, but that basically at the background, downloads and extract on local computer.
If I understand the question correctly, your use case would be that you have a compressed value on the server and want to extract it on the server and keep it there.
This is possible and mostly depends on how the values has been compressed.
If you use the Lempel-Ziv-Welch algorithm used in the UTL_COMPRESS package, you can extract it directly in PL/SQL.
For other formats like zip, you will need to use some custom Java code like the following example:
CREATE OR REPLACE
JAVA SOURCE NAMED ZIP_Java
AS
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import java.util.zip.ZipInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.BufferedOutputStream;
import java.sql.Blob;
public class Java_Class {
public static int ZipBlob(Blob inLob, Blob[] outLob, String filename) {
try {
// create the zipoutputstream from the end of the outLob
Blob zipLob = outLob[0];
OutputStream os = zipLob.setBinaryStream(1);
ZipOutputStream zos = new ZipOutputStream(os);
// add one zip entry
ZipEntry entry = new ZipEntry(filename);
zos.putNextEntry(entry);
// write data to the zip lob
long len = inLob.length();
long offset = 0;
byte[] buffer;
int chunksize = 32768;
while (offset < len) {
buffer = inLob.getBytes(offset + 1, chunksize);
if (buffer == null)
break;
zos.write(buffer, 0, buffer.length);
offset += buffer.length;
}
zos.closeEntry();
zos.close();
outLob[0] = zipLob;
} catch (Exception e) {
System.out.println("Exception: " + e.toString());
e.printStackTrace(System.out);
return 0;
}
return 1;
}
public static int UnzipBlob(Blob inLob, Blob[] outLob, String filename) {
try {
final int kBUFFER = 2048;
InputStream inps = inLob.getBinaryStream();
ZipInputStream zis = new ZipInputStream(inps);
ZipEntry entry;
Blob fileLob = outLob[0];
OutputStream os = fileLob.setBinaryStream(1);
while((entry = zis.getNextEntry()) != null) {
if (entry.getName().equalsIgnoreCase(filename)) {
byte data[] = new byte[kBUFFER];
BufferedOutputStream dest = new BufferedOutputStream(os, kBUFFER);
int count;
while ((count = zis.read(data, 0, kBUFFER)) != -1) {
dest.write(data, 0, count);
}
dest.flush();
dest.close();
}
}
zis.close();
return 1;
} catch (Exception e) {
System.out.println("Exception: " + e.toString());
e.printStackTrace();
return 0;
}
}
}
/
CREATE OR REPLACE
FUNCTION ZipBlobJava(theSource IN BLOB, theDestination IN OUT NOCOPY BLOB, theFilename IN VARCHAR2) RETURN NUMBER
AS LANGUAGE JAVA NAME 'Java_Class.ZipBlob(java.sql.Blob, java.sql.Blob[], java.lang.String) return int';
/
CREATE OR REPLACE
FUNCTION UnzipBlobJava(theSource IN BLOB, theDestination IN OUT NOCOPY BLOB, theFilename IN VARCHAR2) RETURN NUMBER
AS LANGUAGE JAVA NAME 'Java_Class.UnzipBlob(java.sql.Blob, java.sql.Blob[], java.lang.String) return int';
/

TripleDES decryption in python

I'm trying to convert the following c# function to python
the orginal C# function
public static string Decrypt(string Key, string toDecrypt) // key.length = 16 Byte
{
if (Key != "") {
try {
byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(Key);
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.Zeros;
ICryptoTransform cTransform = tdes.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0,
toEncryptArray.Length);
tdes.Clear();
return UTF8Encoding.UTF8.GetString(resultArray);
} catch {
return "";
}
} else
return "";
}
that's my try in python
import base64
from Crypto.Cipher import DES3
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
mac='OtTL6k9yLn6VJIZRXRj1OA=='
key='nOwy4iuE8c8WcktG'
toEncryptArray = base64.b64encode(mac.encode('utf-8'))
keyArray = key.encode('utf-8')
print(DES3.adjust_key_parity(keyArray))
cipher = DES3.new(keyArray, DES3.MODE_ECB)
decriptText = cipher.decrypt(toEncryptArray)
print(decriptText)
the result that i get in python is not equal to the c# result

Change Rijndael decryption logic from C# to Python

I have some already encrypted data which needs to be decrypted using python. The decryption logic in C# looks as given below.
using System.Security.Cryptography;
private const string Url_ENCRYPTION_KEY = "abcd123456";
private readonly static byte[] URL_SALT = Encoding.ASCII.GetBytes(Url_ENCRYPTION_KEY.Length.ToString());
public static string Decrypt(string inputText) {
try {
if (!string.IsNullOrEmpty(inputText)) {
RijndaelManaged rijndaelCipher = new RijndaelManaged();
byte[] encryptedData = Convert.FromBase64String(inputText.Replace(" ", "+"));
PasswordDeriveBytes secretKey = new PasswordDeriveBytes(Url_ENCRYPTION_KEY, URL_SALT);
using (ICryptoTransform decryptor =
rijndaelCipher.CreateDecryptor(secretKey.GetBytes(32), secretKey.GetBytes(16))) {
using (MemoryStream memoryStream = new MemoryStream(encryptedData)) {
using (CryptoStream cryptoStream =
new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) {
byte[] plainText = new byte[encryptedData.Length];
int decryptedCount = cryptoStream.Read(plainText, 0, plainText.Length);
return Encoding.Unicode.GetString(plainText, 0, decryptedCount);
}
}
}
}
}
catch(Exception ex) {
//clsErrorHandler.LogError(ex);
}
return inputText;
}
I have tried libs like pprp and python's cryptography but the solutions out there use PBKDF2, while the C# code here supplies the decryptor bytes of key and salt as key and IV values.
From what I looked the PasswordDeriveBytes function basically work as a somewhat modified PBKDF1,
but all of the solutions I tried fail with somekind of esoteric this size doesn't match with that size errors.
Here is one implementation of PasswordDeriveBytes I found floating out there but I am at a loss on how to do something similar to secretKey.GetBytes(32) and creating a decryptor
import hashlib
from base64 import b64decode
def MS_PasswordDeriveBytes(pstring, salt, hashfunc, iterations, keylen):
if iterations > 0:
lasthash = hashlib.sha1(pstring+salt).digest()
iterations -= 1
else:
print("Iterations must be > 0")
#If iterations is 1 then basically the same thing happens as 2 based on my testing
#if iterations == 0 and keylen > len(lasthash):
#print("Dunno what happens here")
#return -1
for i in range(iterations-1):
lasthash = hashlib.sha1(lasthash)
bytes = hashlib.sha1(lasthash).digest()
ctrl = 1
while len(bytes) < keylen:
bytes += hashlib.sha1(str(ctrl)+lasthash).digest()
ctrl += 1
return(bytes[:keylen])
stpass = 'amp4Z0wpKzJ5Cg0GDT5sJD0sMw0IDAsaGQ1Afik6NwXr6rrSEQE='
slt = 'aGQ1Afik6NampDT5sJEQE4Z0wpsMw0IDAD06rrSswXrKzJ5Cg0G='
initv = '#1B2c3D4e5F6g7H8'
enc_str = b64decode('B5YDTLEDBjd+8zy5lzEfjw==')
derbytes = MS_PasswordDeriveBytes(stpass, slt, hashlib.sha1, iterations=2, keylen=32)

Create keys with python and use it in .net

I try to create keys with the python package ecdsa, export it to der and use them with BouncyCastle under .Net (and vice versa).
This is my code in Python:
import base64
from ecdsa.keys import SigningKey
from ecdsa.curves import NIST521p, NIST384p, NIST256p
#classmethod
def CreateKey(self) -> SigningKey:
privateKey = SigningKey.generate(NIST256p)
return privateKey
#classmethod
def GetPublicKey(self, privateKey: SigningKey) -> str:
publicKey = privateKey.get_verifying_key()
der = publicKey.to_der()
return base64.b64encode(der)
I get two strings that I want to import in .Net:
Const plainDerBase64Pub = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyJW32bO4wswhE9ZC5klCjRNDJQSB0lIBphe9wIa/W2n3fBJ0cDpSpy9qlq2L6sa4W5lgRHYD9IyfETom6YOH/g=="
Const plainDerBase64Priv = "MHcCAQEEIKjIPCG9CGMunu34jXnDZg1LmNYrcJo8EqzKbRu2E24MoAoGCCqGSM49AwEHoUQDQgAEyJW32bO4wswhE9ZC5klCjRNDJQSB0lIBphe9wIa/W2n3fBJ0cDpSpy9qlq2L6sa4W5lgRHYD9IyfETom6YOH/g=="
Dim keyPriv = PrivateKeyFactory.DecryptKey({}, Base64.Decode(plainDerBase64Priv))
Dim keyPub = PrivateKeyFactory.DecryptKey({}, Base64.Decode(plainDerBase64Pub))
But I get an exception:
Test method LicenseProtectorTest.KeyManagementTest.ImportKeyFromPythonTest threw exception:
System.ArgumentException: Wrong number of elements in sequence
Parametername: seq
Result StackTrace:
bei Org.BouncyCastle.Asn1.Pkcs.EncryptedPrivateKeyInfo..ctor(Asn1Sequence seq) in C:\BouncyCastle\crypto\src\asn1\pkcs\EncryptedPrivateKeyInfo.cs:Zeile 18.
bei Org.BouncyCastle.Asn1.Pkcs.EncryptedPrivateKeyInfo.GetInstance(Object obj) in C:\BouncyCastle\crypto\src\asn1\pkcs\EncryptedPrivateKeyInfo.cs:Zeile 42.
bei Org.BouncyCastle.Security.PrivateKeyFactory.DecryptKey(Char[] passPhrase, Asn1Object asn1Object) in C:\BouncyCastle\crypto\src\security\PrivateKeyFactory.cs:Zeile 196.
bei Org.BouncyCastle.Security.PrivateKeyFactory.DecryptKey(Char[] passPhrase, Byte[] encryptedPrivateKeyInfoData) in C:\BouncyCastle\crypto\src\security\PrivateKeyFactory.cs:Zeile 182.
bei LicenseProtectorTest.KeyManagementTest.ImportKeyFromPythonTest() in ...
Any idea what I'm doing wrong here?
I'm not familiar with the python library, but I was able to guess at the formats and the following code will parse the example data:
using System;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
namespace BCTests
{
class MainClass
{
public static void Main(string[] args)
{
var plainDerBase64Pub = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyJW32bO4wswhE9ZC5klCjRNDJQSB0lIBphe9wIa/W2n3fBJ0cDpSpy9qlq2L6sa4W5lgRHYD9IyfETom6YOH/g==";
var plainDerBase64Priv = "MHcCAQEEIKjIPCG9CGMunu34jXnDZg1LmNYrcJo8EqzKbRu2E24MoAoGCCqGSM49AwEHoUQDQgAEyJW32bO4wswhE9ZC5klCjRNDJQSB0lIBphe9wIa/W2n3fBJ0cDpSpy9qlq2L6sa4W5lgRHYD9IyfETom6YOH/g==";
var pubKeyBytes = Base64.Decode(plainDerBase64Pub);
var privKeyBytes = Base64.Decode(plainDerBase64Priv);
var pubKey = PublicKeyFactory.CreateKey(pubKeyBytes);
var privKeyStruct = ECPrivateKeyStructure.GetInstance(privKeyBytes);
var x9 = ECNamedCurveTable.GetByName("P-256");
var ec = new ECDomainParameters(x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed());
var privKey = new ECPrivateKeyParameters(privKeyStruct.GetKey(), ec);
}
}
}
pubKey and privKey are then ECPublicKeyParameters and ECPrivateKeyParameters that you can use with various algorithms.
Note that DER is an encoding, not really a format. For the public key, the python code is producing a SubjectPublicKeyInfo, which is the standard X.509 format for public keys.
There ought to be an option with the private key of generating a PrivateKeyInfo (or EncryptedPrivateKeyInfo using a password), both of these are formats from the PKCS#8 standard. If the python code can output one of these, then decoding the private key would be easier as just PrivateKeyFactory.CreateKey(bytes) or .DecryptKey(password, bytes).

Python AES encryption(PyCrypto) -> AS3 decryption (as3Crypto) using AES

I've a django app which serves encrypted media files to Flash apps. Encryption in python is done with PyCrypto as follows (I include description too in case useful):
def encrypt_aes(key, text):
try:
raw = _pad(text)
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
return base64.b64encode(iv + cipher.encrypt(raw))
except Exception as e:
print e.message
return text
def decrypt_aes(key, text):
try:
enc = base64.b64decode(text)
iv = enc[:AES.block_size]
cipher = AES.new(key, AES.MODE_CBC, iv)
return _unpad(cipher.decrypt(enc[AES.block_size:]))
except Exception as e:
print e.message
return text
def _pad(s):
bs = 16
return s + (bs - len(s) % bs) * chr(bs - len(s) % bs)
def _unpad(s):
return s[:-ord(s[len(s) - 1:])]
I cannot yet decrypt the Python provided media files (downloaded with LoaderMax by GreenSock, using 'DataLoader'). My AS3 code (using AS3Crypto) is as follows:
public static function decipher(_key:String):void{
key=_key;
cipher = Crypto.getCipher("simple-aes-cbc", Hex.toArray(key));
cipher.decrypt(ByteArray(_content));
}
I get
RangeError: Error #2006
One suspicion is that in Python I have 64bit base but I think that AS3 ByteArray is 32bit base. I have tried the below, but get the same Error.
cipher.decrypt(ByteArray(com.hurlant.util.Base64.decodeToByteArray(_content)));
Another suspicion is that I have not appropriately removed 'padding' from the _content / set up my IV appropriately (which is specified by the padding I must remove from the _content). This should be done via that "simple" statement however. I have been trying this, but with no success:
var pad:IPad = new PKCS5
cipher = Crypto.getCipher("simple-aes", Hex.toArray(key),pad);
pad.setBlockSize(cipher.getBlockSize());
Could anyone advise on how I can fix this ? :)
Many thanks!
OK finally figured out what was going wrong. Besides some AS3 tweaks, we wrongly were transmitting files as MP3/image (should have been text/html).
Our Python remains as above. Our AS3 is tweaked to the below.
Here's the AS3 class we used:
package com.xperiment.preloader
{
import com.greensock.loading.DataLoader;
import com.hurlant.crypto.Crypto;
import com.hurlant.crypto.symmetric.ICipher;
import com.hurlant.util.Base64;
import flash.events.Event;
import flash.utils.ByteArray;
public class EncryptedDataLoader extends DataLoader
{
private static var backlog:Vector.<EncryptedDataLoader>;
private static var cipher:ICipher;
private var decrypted:Boolean = true;
public function EncryptedDataLoader(urlOrRequest:*, vars:Object=null)
{
this.addEventListener(Event.COMPLETE,decryptL);
super(urlOrRequest, vars);
}
public function decryptL(e:Event):void {
trace("start decrypt");
e.stopImmediatePropagation();
this.removeEventListener(Event.COMPLETE,decryptL);
backlog ||= new Vector.<EncryptedDataLoader>;
backlog.push(this);
if(cipher) pingBacklog();
}
public function decipher():void
{
_content = Base64.decodeToByteArray( _content );
cipher.decrypt( _content );
decrypted=true;
this.dispatchEvent(new Event(Event.COMPLETE));
}
public static function setCipher(_key:String):void{
var keyBA:ByteArray = new ByteArray;
keyBA.writeMultiByte(_key, "iso-8859-1");
cipher = Crypto.getCipher("simple-aes", keyBA);
pingBacklog();
}
public static function kill():void{
cipher.dispose();
cipher = null;
}
public static function pingBacklog():void{
if(backlog){
var encrypted:EncryptedDataLoader;
while(backlog.length>0){
encrypted=backlog.shift();
encrypted.decipher();
}
backlog=null;
}
}
}
}

Categories