CWE-326 on FIPS compliant AES256 - c#

Why does Veracode flag the following FIPS compliant C#?
var cipher = new AesCng()
{
BlockSize = 128,
KeySize = 256,
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7
};

Hi: current Veracode scans likely wouldn't flag CWE 326 on a use of AES with a key size of 256. If this was a recent scan, could you please reach out to Veracode Support so we can take a closer look to find out why this was flagged?
If this was a result from an older scan, you may want to try rescanning the application to see if the issue is still flagged.

Related

Error RSA encrypting in C# and decrypting in Go

I am getting an error decrypting a message in go that was encrypted in C# (using corresponding public/private keys)
My client is written in C# and my server is written in Go. I generated a private and public key via go's crypto/rsa package (using rsa.GenerateKey(random Reader, bits int)). I then store the public key file generated where the client can access it and the private key where the server can access it. I encrypt on the client with the following code (using bouncy castle):
public static string Encrypt(string plainText)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
PemReader pr = new PemReader(
new StringReader(m_publicKey)
);
RsaKeyParameters keys = (RsaKeyParameters)pr.ReadObject();
// PKCS1 OAEP paddings
OaepEncoding eng = new OaepEncoding(new RsaEngine());
eng.Init(true, keys);
int length = plainTextBytes.Length;
int blockSize = eng.GetInputBlockSize();
List<byte> cipherTextBytes = new List<byte>();
for (int chunkPosition = 0; chunkPosition < length; chunkPosition += blockSize)
{
int chunkSize = Math.Min(blockSize, length - chunkPosition);
cipherTextBytes.AddRange(eng.ProcessBlock(
plainTextBytes, chunkPosition, chunkSize
));
}
return Convert.ToBase64String(cipherTextBytes.ToArray());
}
The go server parses this string from the header and uses the private key to decrypt:
func DecryptWithPrivateKey(ciphertext []byte, priv *rsa.PrivateKey) []byte {
hash := sha512.New()
plaintext, err := rsa.DecryptOAEP(hash, rand.Reader, priv, ciphertext, nil)
if err != nil {
fmt.Fprintf(os.Stderr, err.Error())
}
return plaintext
}
The decryption function throws crypto/rsa: decryption error. If I try pasting the cipher text directly into go (rather then sending from the client), the same error occurs.
NOTE: in order to get the public key to load, I needed to change the header from:
-----BEGIN RSA PUBLIC KEY-----
...
to
-----BEGIN PUBLIC KEY-----
...
and the same for the footer. I am assuming this is a formatting issue but not sure how to go about solving.
EDIT: it seems that golang OAEP uses sha256 and bouncy castle uses SHA-1. Go's documentation specifies that the hash for encryption and decryption must be the same. This seems likely to be the issue? If it is, how can I change the hashing algorithm used by either go or C#?
Yes, you need to match the hash. In GoLang you've already set it to SHA-512 if I take a look at your code. Using SHA-256 at minimum should probably be preferred, but using SHA-1 is relatively safe as the MGF1 function doesn't rely on the collision resistance of the underlying hash. It's also the default for most runtimes, I don't know why GoLang decided against that.
Probably the best is to set SHA-512 for both runtimes, so here is the necessary constant for .NET.
Note that the underlying story is even more complex as OAEP uses a hash over a label as well as a hash within MGF1 (mask generation function 1, the only one specified). Both need to be specified in advance and generally the same hash function is used, but sometimes it is not.
The label is generally empty and most runtimes don't even allow setting it, so the hash value over the label is basically a hash-function specific constant that doesn't matter for security. The constant just manages to make things incompatible; "More flexible" isn't always a good thing.

Blowfish in BouncyCastle encrypts only first 8 bytes

I'm trying to implement Blowfish encryption, ECB mode, through BouncyCastle. The problem is that this code encrypts only first 8 bytes of the file. I don't know, what the problem might be. I've worked with BouncyCastle before.
I found that I'm not the one having this problem, but the solution here didn't help:
Blowfish ECB Mode in BouncyCastle
The code is:
byte[] fileIn = File.ReadAllBytes("file.txt"), fileOut = new byte[fileIn.Length];
BlowfishEngine blowfishEngine = new BlowfishEngine();
blowfishEngine.Init(true, new KeyParameter(Encoding.UTF8.GetBytes("ahoi")));
blowfishEngine.ProcessBlock(fileIn, 0, fileOut, 0);
File.WriteAllBytes("file2.txt", fileOut);

AES Missing Mode

I'm using AES on WP8 (Windows Phone 8) in C# on Visual Studio, and System.Security.Cryptography does not contain the attribute 'Mode' for AESManaged.
I've looked up this problem for the past 3 days now, and haven't found any reference or anything to import.
The code I am currently using is:
AesManaged cipher = new AesManaged();
cipher.BlockSize = 8;
/*cipher.Mode = CipherMode.CFB;
cipher.Padding = PaddingMode.None;*/
//cipher.KeySize = 128;
//cipher.FeedbackSize = 8;
cipher.Key = key;
cipher.IV = key;
return cipher;
While the BlockSize throws an exception 'Specified block size is not valid for this algorithm.'
I was originally using RijndaelManaged but that isn't available on WP8 but according to this it should be available.
Silverlight verison of AES have no mode property. Here is MSDN article about that.
"The AES algorithm is essentially the Rijndael symmetric algorithm with a fixed block size and iteration count. This class functions the same way as the .NET Framework RijndaelManaged class but limits blocks to 128 bits and does not allow feedback modes.
The cipher mode is always CBC, and the padding mode is always PKCS7."
You can extract AES from BounceCastle library if you need more modes and flexibility. I did that before.

AES/GCM (AES-128-GCM) authentication-tag differs in C# and Ruby

I'm trying to generate a authentication-tag in C# which I already generated in Ruby (for testing purposes). However the results are different, but as far as I can see,the inputs are equal.
In Ruby 2.0 using OpenSSL 1.0.1c (Ubuntu 13.04):
require 'openssl'
require 'base64'
iv = Base64.decode64('kEWio77T7qWdytrIbUmRxA==')
key = Base64.decode64('FnUoIZvBUzC1Q/rn5WMi7Q==')
aad = Base64.decode64('/tTP07sPkoX8gah60eH89w==')
cipher = OpenSSL::Cipher.new('aes-128-gcm').encrypt
cipher.iv = iv
cipher.key = key
cipher.auth_data = aad
cipher.final
tag = Base64.strict_encode64(cipher.auth_tag)
The resulting (encoded) tag is ie74XTWtSLNad0BKdrhvmQ==
In C# using BouncyCastle (snippet):
var iv = Convert.FromBase64String("kEWio77T7qWdytrIbUmRxA==");
var key = Convert.FromBase64String("FnUoIZvBUzC1Q/rn5WMi7Q==");
var aad = Convert.FromBase64String("/tTP07sPkoX8gah60eH89w==");
var cipher = new GcmBlockCipher(new AesFastEngine());
var parameters = new AeadParameters(new KeyParameter(passkey), 128, iv, aad);
cipher.Init(true, parameters);
var cipherText = new byte[cipher.GetOutputSize(0)];
cipher.DoFinal(cipherText, 0);
var tag = Convert.ToBase64String(cipher.GetMac());
The resulting tag in C# is sawCcwM1T8sGl5y6VT0CHA==
What am I doing wrong here? Thanks in advance for your response!
Okay, I installed ruby 2.0.0 and did some tests.
First of all, to replicate your original output "ie74XTWtSLNad0BKdrhvmQ==" in C#, set the IV in C# to "new byte[12]".
The reason that works, is that in the ruby code setting cipher.key clears whatever IV you set, so the effective IV is the default all-zeroes of default length (96 bits for GCM). So you should set the IV after the key.
If we change the ruby code to do that, then the output changes to "d1tAJ6Js94tSuPNbds0EJw=="; still not a match. To reproduce this value in C#, truncate the IV to 12 bytes, i.e. "kEWio77T7qWdytrI", and the output now matches.
From this I infer that openssl/EVP is truncating any IV you give it. That shouldn't strictly be necessary, as GCM does support longer IVs, but 96 bits is in some sense the "preferred" length; I'm not sure where that policy is being enforced here.

AES Decryption - Porting code from C# to Java

I am trying to port the following code from C# into Java. I have made multiple attempts to try and decrypt my encrypted data and I get gibberish every time. The code below uses the org.bouncycastle library and unfortunately there doesn't seem to be a 1-1 mapping between the C# code and the Java code.
I basically know three things:
byte[] file - This contains my encrypted file. Usually a pretty large array of bytes.
byte[] padding - It is 32*bytes* every time and it seems that the first 16 bytes of this are used as the IV.
byte[] aesKey - It is 32*bytes* every time and I do not know how exactly the C# code is using this array.
Original C# Code
private byte[] decryptmessage(byte[] cmessage, byte[] iVector, byte[] m_Key)
{
{
//// randomly generated number acts as inetialization vector
m_IV = new byte[16];
Array.Copy(iVector, 0, m_IV, 0, 16);
// GenerateAESKey();
KeyParameter aesKeyParam = ParameterUtilities.CreateKeyParameter("AES", m_Key);
ParametersWithIV aesIVKeyParam = new ParametersWithIV(aesKeyParam, m_IV);
IBufferedCipher cipher = CipherUtilities.GetCipher("AES/CFB/NoPadding");
cipher.Init(false, aesIVKeyParam);
return cipher.DoFinal(cmessage);
}
}
My attempt in Java
private static byte[] decryptMessage(byte[] file, byte[] iVector, byte[] aesKey) throws Exception {
IvParameterSpec spec = new IvParameterSpec(Arrays.copyOfRange(iVector, 0, 16));
SecretKeySpec key = new SecretKeySpec(Arrays.copyOfRange(aesKey, 0, 16), "AES");
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, key, spec);
return cipher.doFinal(file);
}
P.S: This is the final step of decryption. Before all this I had to take out some initial set of bytes from my encrypted file and decrypt them using an RSA private key to get this AES key.
If someone has a link / document I can read that properly explains the whole process of using AES to encrypt a file, then using RSA on the key and iv to the begining of the encrypted file, I will be extremely happy. I have just been staring at the C# code, I'd like to see something with pictures.
EDIT: Bytes not bits.
EDIT2: Renamed padding to iVector for consistency and correctness.
In the C# code, you initialize the key with 256 bits (32 bytes) and thus get AES-256. In the Java code, you only use 128 bit (16 bytes) and get AES-128.
So the fix is probably:
SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
You might then find that Java doesn't want to use 256 bit keys (for legal reason). You then have to intall the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6.

Categories

Resources