Powershell - base64 encoded with key/passphrase - powershell

With citrix netscaler update, the OTP is now encrepted in the active Directory attribute.
The OTP explorer tool created by Andreas Nick was working perfectly up to now.
https://www.andreasnick.com/102-otpedit.html
The citrix Documentation says that the OTP secret is now encrypted by the certificate. After the encryption, the HASH string that is stored in the Active Directory attribute looks like this.
OTP Secret
3DHAZHNBYLK72SFKVUOLU6E4ZE
Hash (in Active Directory)
jjtTl0YY3MGIF77HPcqYs2w2bAc=.sbntdorhH2Ju15c5.kbJ8_AP8Ytu7BiNuICEfkiSgOVJMudtNXgn2eStfoOGyV42v6VbzLA==
I tried to encrypt the OTP secret with the certificate used but they are a lot more caracters (346 in total - citrix encryption has 102).
On the citrix website it says that it is using base64 to encrypt the data.
https://docs.citrix.com/en-us/citrix-adc/current-release/aaa-tm/authentication-methods/native-otp-authentication/otp-encryption-tool.html
I tried to use this code but the HASH is not good.
$enc = [system.Text.Encoding]::UTF8
$string = "3DHAZHNBYLK72SFKVUOLU6E4ZE"
$data=$enc.GetBytes($string)
$sha1 = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
$ResultHash = $sha1.ComputeHash($data)
$str_out = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($ResultHash))
write-host $str_out
My guess is that it is using the certificate thumprint as a "key" but I was not able to find a function that encrypts a string in base64 using a key / passphrase.
I have tried other functions created to encrypt strings from a certificate, but was unable to find one that matches the one done by Citrix.
I am not good in all the encryption. I only know the very basics so the answer might be obvious and that I can simply not see it due to my lack of skills in that area.
Thank you in advance for your help.

Related

Digital Signature Certificate

I've been all around Google and I feel like I've just gone into a deep rabbit hole.
I'm looking to create a Digital Signature certificate (I assume self-signed?). I ran into the method of using certreq -new .\certname.txt by providing simple parameters.
But the only thing I've come to know that I need in my file is:
[NewRequest]
Subject = "CN=Test Sign, E=email#address.com"
KeyLength = 2048
HashAlgorithm = Sha256
KeyUsage = 0x0080 ; Digital Signature
RequestType = Cert
ValidityPeriodUnits = 1
ValidityPeriod = Years
But I'm unsure of what else should be here in order to make it a proper signature certificate.
I want to be able to use this signature file in whatever project I have going.
I messed around with Adobe Acrobat Pro and you can create a digital sig in that program; but it limits the OID to 1.2.840.113583.1.1.10 which is for Adobe.
In short, I need to place a Digital Sig into slot 9c of my Yubikey. If you generate the certificate from the Yubikey; then the private key is not exportable. So I'm attempting to generate the pfx file this way so that I can import into multiple keys without the need for multiple different certificates.
Any help to finish this up would be greatly appreciated.
Regards

IIS FTP passwords encryption schema

This is one of my first approaches to "crypto in practice". I have found myself a new aim when I stumbled upon my password (AES encrypted) on my FTP server. Since I am eager to get to know new stuff, I decided I'll give it a go and try to 'recover' my password from AES cipher. If I can make it to decipher it 'on the paper' I think I will have a good enough understanding on how it works and how to call it.
As MSDN points out:
The AesProvider provider is an AES provider that uses a session key encrypted using an RSA key container that has permissions for the IIS_IUSRS group, therefore allowing IIS worker processes to encrypt and decrypt configuration encrypted with this provider.
So, the available data:
Session key (RSA encrypted) from <configProtectedData>
AES cipher from the same file (enc:AesProvider:89v45avZx.....)
Machine RSA key (obtained using aspnet_regiis -px "SampleKeys"
keys.xml -pri) (since useMachineContainer flag is true).
If I understand correctly:
In order to decrypt the password:
I need to decrypt the RSA-Encrypted session key with Machine RSA key.
Once I have the decrypted session key I use it as AES key to decrypt the password. Am I mistaken in this thinking?
If the above is correct, I will now describe my attempts:
Using Powershell (my preferable environment):
[xml]$IISXML = [xml](cat .\IISConfigKey.xml)
[System.Xml.XmlElement]$IISElement = $IISXML.RSAKeyValue
$RSA = New-Object System.Security.Cryptography.Xml.RSAKeyValue
$RSA.LoadXml($IISElement)
## Now I have RSA-key loaded as an object from exported XML
$AESSessionKey = "LIAAAZ..1aVods=" // Total length 188
## I am importing the session key from the file
$AESProviderSessionKeyBytes = (Convert-FromBase64 $AESProviderSessionKey).ToCharArray() | % { [byte]$_ }
## 'Convert-FromBase64' is my custom function, which basically converts from Base64 to String
And this seems to be the first culprit I can't get around. Casting $RSA.Key.Decrypt($AESProviderSessionKeyBytes, $true) returns an error that the data exceeded 128 bytes. Which happened in fact, as the SessionKeyBytes is of 140-length.
As the method I am calling happily throws exceptions at me, I have no idea what to try next. The sessionKey seems too long to be RSA-encrypted? Or maybe I should divide it? Or maybe I am just mistaken in principle that it is RSA encrypted.. I tried couple of versions, but none of them progressed me any closer.
Hope you can point me in the right direction!

sagepay form protocol 3 encryption e new form error

We are unable to make the form for protocol 3 work correctly and getting a "5068 encryption method is not supported by this protocol version" message. The code we have for the encryption is shown below. Can anyone tell me where we are going wrong?
$stuff = #pkcs5_pad($stuff, 16);
$crypt = #base64_encode(#mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $order['gateway']['transkey'], $stuff, MCRYPT_MODE_CBC, '1234567812345678'));
function pkcs5_pad ($text, $blocksize) {
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
Are you trying to use a simulator account for that request? If so, the version 3 protocol does not yet work with the simulator account, nor do Sage Pay have an estimate on when it will be available.
You will need to use a test account to test a full v3 integration, otherwise you can integrate to v2.23, commenting out the additional v3 fields, and test with the simulator account.
Then later on adding in the v3 additional fields and testing via the simulator when it's available or on a test account.
The encryption password will differ on your Test and Live account. If you require your encryption password please call our Support line on 0845 111 4455 who will be able to send it to a registered contact on the Sage Pay account.
If you are using Simulator - it is not available on v3.00. The above comment is correct, you may use v2.23 to test your integration. If ok, change to v3.00 ensuring your are checking all mandatory fields are being used and the return responses are ok.
V3.00 Form Protocol and Integration Guideline is available here. The Crypt field should contain all the other transaction information in plain text as Name=Value fields separated by ‘&’ characters. This string should then be encrypted using the AES/CBC/PCKS#5 algorithm and the pre-registered Encryption password, then subsequently Base64 encoded to allow safe transport in an HTML form. The crypt must be 16 characters.
If you need further support, you may email feedback#sagepay.com and reference this forum post URL.
Sage Pay Support

Perl code to generate secret key for HMAC SHA256 signing?

I'm planning to use code similar to Amazon AWS samples to authenticate signed API requests. So users will have something like:
use Digest::SHA qw(hmac_sha256_base64);
my $digest = hmac_sha256_base64 ($request, $self->{SecretKey});
and attach $digest as a parameter to their request URI. The server-side will use the same algorithm to create a digest from the client URI and compare that to the value sent by the client.
What I can't find is Perl support for generating the SecretKey of the correct length to use when generating HMAC SHA256 digest.
For my Amazon AWS account I'm being given a 40 ASCII character base64 encoded string.
How do I generate a proper secret-key for my clients?
I suggest you use a PBKDF2 algorithm. PBKDF2 = "Password-based Key Derivation Function (#2)". It is defined in PKCS #5 (RFC 2898). This is the recommended way to derive a key from a password. You will need a salt, as well. A typical iteration count is 1000.
This page says it has a perl implementation of PBKDF2. I haven't tried it.
Apparently there is also a Crypto::PBKDF2, but it is saddled with dependencies you may not want.
EDIT
I just tried Anthony Thyssen's perl program for pbkdf2 - it works great. Simple, easy.

Compatible encryption between C# and PHP, ColdFusion, Ruby, Python

We're developing a service that will accept a POST request. Some of the POST data will need to be encrypted before the POST as it will be stored in hidden fields on a form.
The application is written in C#, but we want third party clients to be able to easily integrate with it. We find that most clients use PHP, Classic ASP or VB.Net.
The third parties should only be doing the encryption. We'd do the decryption. There is no two-way communication.
What are the most compatible combinations of encryption algorithm, padding mode and other options?
Assuming that you have a safe way of sharing a key (whether RSA encryption of it, retrieval over an SSH or HTTPS link, or callling the other developer on a secured phone line), any of the major modern encryptions (like AES, as mentioned by #Ed Haber) would be suitable. I would second his suggestion of AES. There should be libraries for PHP, VB, Ruby, etc.
However, remember that with "no two-way communication" you will have to find an out-of-channel method for securely getting the symmetric key to the encrypting party.
If you mean that it should be impossible for third-parties to decrypt data, then you will want to use an asymmetric encryption algorithm such as RSA. This will the third-party to encrypt data with your public key, and then only you can decrypt the data with your private key, which you do not disclose. There should be implementations of RSA available for all the languages you mentioned.
If you don't care if the third-party can decrypt the data, then AES is the way to go. You will have one key which you share with the third-parties. This key is used both for encryption and decryption.
I would use AES for the bulk data encryption and RSA for encrypting the AES Key.
If the data is small enough then just encrypt the whole thing with RSA.
Ed Haber said
I would use AES for the bulk data
encryption and RSA for encrypting the
AES Key. If the data is small enough
then just encrypt the whole thing with
RSA.
I think this is a good solution. What I would do is have your application publish an API for getting a public RSA key. When I third party wants to send you something it gets the public key. It then generates a session key to do the actual encryption using a block cipher, (ie AES), and sends the key to you by encrypting with your public key. You decrypt the session key with your private key. The third party then encrypts the data it wants to send you with AES (using a padding scheme that you also publish) and sends it to you. You decrypt it using the session key.
There are some problems with the method above. Since you are not sending any information (other than publishing your public key, you cannot control how the session key is generated. This means that third parties can use very insecure ways to of generating the session key and you will never know. A second problem is everyone who wants to send you data has to pad data for AES in the same way you do. So you will have to make sure every one co-ordinates. The second issue isn't to big, but the first could be a problem especially if you don't trust the third parties all that much to generate really good session keys from a good cryptographically secure random number generator
You could very easily implement your own XOR key-based bit encryption. With a little thought and ingenuity, you can come up with something that's more than suitable for you application.
Here's a PHP example:
function XOREncryption($InputString, $KeyPhrase){
$KeyPhraseLength = strlen($KeyPhrase);
for ($i = 0; $i < strlen($InputString); $i++){
$rPos = $i % $KeyPhraseLength;
$r = ord($InputString[$i]) ^ ord($KeyPhrase[$rPos]);
$InputString[$i] = chr($r);
}
return $InputString;
}
ColdFusion has the encrypt and decrypt functions capable of handling a range of algorithms and encodings, including the AES recommended above.
Information at: http://www.cfquickdocs.com/cf8/?getDoc=encrypt#Encrypt
Quick example code:
Key = generateSecretKey( 'AES' , 128 )
EncryptedText = encrypt( Text , Key , 'AES' , 'Hex' )
Text = decrypt( EncryptedText , Key, 'AES' , 'Hex' )
Similar functionality is available with this library for PHP:
http://www.chilkatsoft.com/p/php_aes.asp
...and Java, Python, Ruby, and others...
http://www.example-code.com/java/crypt2_aes_matchPhp.asp
http://www.example-code.com/python/aes_stringEncryption.asp
Sounds like RSA is the algorithm for you.
Why not have your server exposed over HTTPS? That way, any client which can handle HTTPS can consume the service securely.