Completed
Last Updated: 31 Jan 2024 18:07 by ADMIN
Release 2024 Q1
MichaelC
Created on: 30 Dec 2021 20:47
Type: Bug Report
2
PictureBox throws exception This implementation is not part of the Windows Platform FIPS cryptographic algorithms

The error below is thrown in PictureBox when System cryptography Use FIPS compliant algorithms is enabled:

An error has occurred while processing PictureBox 'pictureBox1': Exception has been thrown by the target of an invocation.
--------------- InnerException ---------------
This implementation is not part of the Windows Platform FIPS validated cryptographic algorithms.
2 comments
ADMIN
Milen | Product Manager @DX
Posted on: 31 Jan 2024 18:07

Hi,

This is to notify you that the images storage algorithm is now FIPS-compliant:  2024 Q1 release. Any feedback you can give is always welcome.

Regards,
Milen | Product Manager @DX
Progress Telerik

Stay tuned by visiting our roadmap and feedback portal pages, enjoy a smooth take-off with our Getting Started resources, or visit the free self-paced technical training at https://learn.telerik.com/.
ADMIN
Neli
Posted on: 30 Dec 2021 20:54

Hello,

We would thank you for bringing this issue to our attention. In fact, the issue is not related to the format of the image, as we initially suspected. It is reproducible with any image that obtains its data as byte array.

During the report processing stage, the PictureBox item tries to resolve its Value property to an Image instance which will be later rendered in the requested rendering format - in the current scenario it's WPF. When the image data is successfully obtained, it's being cached internally for performance and memory optimization: it doesn't make sense to keep multiple instances of the same image in the memory. The internal dictionary that we use for caching the images, takes a string as a key. If the image is resolved from an URI - the key is the normalized representation of that URI. If the image is resolved as an inline bitmap (embedded in the report), the key is the hash code of the image instance. However, when the image is produced by byte array (the current scenario), we calculate the hash of that array and use it as a key in the cache. To calculate the hash we use MD5 hashing algorithm, which is not FIPS-compliant and this is where the exception is being thrown.

We can suggest two simple workarounds:

The first workaround requires creating a UserFunction that will accept a byte array and will return an Image instance. Assign this function to the Value property of your PictureBox. This way the processing engine will receive an Image instance when the report is being processed. The downside of this approach is that the caching won't work, because each image will be a new instance. This can be improved by handling the caching in the UserFunction, using a FIPS-approved hashing algorithm (or any other approach that works for your scenario). A sample implementation is shown below:

namespace Telerik.Reporting.Examples.CSharp
{
    using System;
    using System.Collections.Concurrent;
    using System.Drawing;
    using System.IO;
    using System.Security.Cryptography;

    public static class ImageProvider
    {
        static readonly SHA256Cng hasher = new SHA256Cng();
        static readonly ConcurrentDictionary<string, Image> imageCache = new ConcurrentDictionary<string, Image>();

        public static Image CreateImage(byte[] rawData)
        {
            var hash = Convert.ToBase64String(hasher.ComputeHash(rawData));
            if (!imageCache.TryGetValue(hash, out Image cachedImage))
            {
                cachedImage = Image.FromStream(new MemoryStream(rawData));
                imageCache.TryAdd(hash, cachedImage);
            }

            return cachedImage;
        }
    }
}

The second workaround is way simpler and I would recommend to use it if it's applicable to your scenario. The PictureBox item can obtain its data from a Base64-encoded string that contains the image data. Since MSSQL supports Base64-encoding out-of-the-box, you can return the Base64-encoded representation of the image rather than the image bytes, and assign the PictureBox's Value property to the data set field that contains the Base64 string. This approach is better, because there's no need to write UserFunctions and the caching mechanism will work out of the box. Here's how the SQL query would look like in this case:

SELECT     
PP.LargePhoto, -- this is the datatable field that contains the image bytes
cast('' as xml).value('xs:base64Binary(sql:column("LargePhoto"))', 'varchar(max)') as Base64Photo, -- this is the Base64-encoded representation of the image bytes.
... the rest of the query

We can confirm that they work and satisfy the FIPS requirements. 

Regards,
Neli
Progress Telerik

Brand new Telerik Reporting course in Virtual Classroom - the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products. Check it out at https://learn.telerik.com/.