Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The sample code did not get the expected results #46922

Closed
lx4556332 opened this issue Jan 13, 2021 · 10 comments
Closed

The sample code did not get the expected results #46922

lx4556332 opened this issue Jan 13, 2021 · 10 comments
Labels
area-System.Security untriaged New issue has not been triaged by the area owner

Comments

@lx4556332
Copy link

Hello, I didn't get the right result according to the example code.
URL : https://docs.microsoft.com/zh-cn/dotnet/api/system.security.cryptography.frombase64transform.-ctor?redirectedfrom=MSDN&view=netcore-2.2#System_Security_Cryptography_FromBase64Transform__ctor_System_Security_Cryptography_FromBase64TransformMode_
Error details:Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
method:DecodeFromFile(string inFileName, string outFileName)
Error line: int bytesWritten = myTransform.TransformBlock(myInputBytes, i, 4/myTransform.InputBlockSize/, myOutputBytes, 0);

@lx4556332
Copy link
Author

net core 3.0 and above no problem.

@lx4556332
Copy link
Author

3.0 and below are problematic,How to solve?

@javiercn javiercn transferred this issue from dotnet/aspnetcore Jan 13, 2021
@dotnet-issue-labeler dotnet-issue-labeler bot added area-System.Security untriaged New issue has not been triaged by the area owner labels Jan 13, 2021
@ghost
Copy link

ghost commented Jan 13, 2021

Tagging subscribers to this area: @bartonjs, @vcsjones, @krwq
See info in area-owners.md if you want to be subscribed.

Issue Details

Hello, I didn't get the right result according to the example code.
URL : https://docs.microsoft.com/zh-cn/dotnet/api/system.security.cryptography.frombase64transform.-ctor?redirectedfrom=MSDN&view=netcore-2.2#System_Security_Cryptography_FromBase64Transform__ctor_System_Security_Cryptography_FromBase64TransformMode_
Error details:Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
method:DecodeFromFile(string inFileName, string outFileName)
Error line: int bytesWritten = myTransform.TransformBlock(myInputBytes, i, 4/myTransform.InputBlockSize/, myOutputBytes, 0);

Author: lx4556332
Assignees: -
Labels:

area-System.Security, untriaged

Milestone: -

@vcsjones
Copy link
Member

vcsjones commented Jan 13, 2021

This looks related to, or a duplicate of #30993. As said in the issue:

the only workaround that I can think of for 2.1 is to pre-filter whitespace out of your input before letting the FromBase64Transform process it. The probably easier answer is to upgrade to 3.1 [or newer], since the bug is fixed in that release.

It would seem that your base64 input has whitespace or new lines in it. Is this the case for your input?

As also mentioned, the easiest solution is to use a version of .NET that has issue fixed.

@vcsjones
Copy link
Member

My Base64 input has no spaces

Can you provide a sample base64 input that reproduces the problem?

2.2 is no longer supported, but perhaps I can determine a work around.

@lx4556332
Copy link
Author

`
string appPath = (System.IO.Directory.GetCurrentDirectory());
var sourceFile = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "pwd.txt");
var targetFile = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "code.enc");
var outFileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "roundtrip.txt");
DecodeFromFile(targetFile, outFileName);

    public static void DecodeFromFile(string inFileName, string outFileName)
    {
        using (FromBase64Transform myTransform = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces))
        {

            byte[] myOutputBytes = new byte[myTransform.OutputBlockSize];

            //Open the input and output files.
            using (FileStream myInputFile = new FileStream(inFileName, FileMode.Open, FileAccess.Read))
            {
                using (FileStream myOutputFile = new FileStream(outFileName, FileMode.Create, FileAccess.Write))
                {

                    //Retrieve the file contents into a byte array. 
                    byte[] myInputBytes = new byte[myInputFile.Length];
                    myInputFile.Read(myInputBytes, 0, myInputBytes.Length);

                    //Transform the data in chunks the size of InputBlockSize. 
                    int i = 0;
                    while (myInputBytes.Length - i > 4/*myTransform.InputBlockSize*/)
                    {
                        int bytesWritten = myTransform.TransformBlock(myInputBytes, i, 4/*myTransform.InputBlockSize*/, myOutputBytes, 0);
                        i += 4/*myTransform.InputBlockSize*/;
                        myOutputFile.Write(myOutputBytes, 0, bytesWritten);
                    }

                    //Transform the final block of data.
                    myOutputBytes = myTransform.TransformFinalBlock(myInputBytes, i, myInputBytes.Length - i);
                    myOutputFile.Write(myOutputBytes, 0, myOutputBytes.Length);

                    //Free up any used resources.
                    myTransform.Clear();
                }
            }
        }
    }

`
file code.enc The content is "aGVsbG93b3Jk"
The above code will report an error in version 2.2 and below.

@danmoseley
Copy link
Member

@lx4556332 I believe we need the sample inputs (nothing confidential of course)

Also could you please use triple back ticks to format your code to make it a bit easier to read? This has an example
https://guides.github.com/features/mastering-markdown/

@vcsjones
Copy link
Member

@danmosemsft

file code.enc The content is "aGVsbG93b3Jk"

I think we / I have everything now, just haven't had a minute to look, but will soon.

@vcsjones
Copy link
Member

The issue with 2.2 is the way that it handles the buffer size calculation when given the input array is larger than expected. Even though you are specifying an offset and length, it is not handled correctly in 2.2.

As a work around, if you copy the input data to an array that is at most the size of the data being transformed, I believe it will work. Perhaps something like this:

static void DecodeFromFile(string inFileName, string outFileName)
{
    using (FromBase64Transform myTransform = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces))
    {
        const int ReadSize = 4;
        byte[] myOutputBytes = new byte[myTransform.OutputBlockSize];
        byte[] inputBuffer = new byte[ReadSize];

        //Open the input and output files.
        using (FileStream myInputFile = new FileStream(inFileName, FileMode.Open, FileAccess.Read))
        {
            using (FileStream myOutputFile = new FileStream(outFileName, FileMode.Create, FileAccess.Write))
            {

                //Retrieve the file contents into a byte array. 
                byte[] myInputBytes = new byte[myInputFile.Length];

                myInputFile.Read(myInputBytes, 0, myInputBytes.Length);

                //Transform the data in chunks the size of InputBlockSize. 
                int i = 0;
                while (myInputBytes.Length - i > ReadSize/*myTransform.InputBlockSize*/)
                {
                    System.Buffer.BlockCopy(myInputBytes, i, inputBuffer, 0, ReadSize);
                    int bytesWritten = myTransform.TransformBlock(inputBuffer, 0, inputBuffer.Length, myOutputBytes, 0);
                    i += 4/*myTransform.InputBlockSize*/;
                    myOutputFile.Write(myOutputBytes, 0, bytesWritten);
                }

                //Transform the final block of data.
                System.Buffer.BlockCopy(myInputBytes, i, inputBuffer, 0, myInputBytes.Length - i);
                myOutputBytes = myTransform.TransformFinalBlock(inputBuffer, 0, myInputBytes.Length - i);
                myOutputFile.Write(myOutputBytes, 0, myOutputBytes.Length);

                //Free up any used resources.
                myTransform.Clear();
            }
        }
    }
}

The best solution is to upgrade to .NET Core 3.1 or newer. Then the code can be as simple as:

static void DecodeFromFile(string inFileName, string outFileName)
{
    using (FromBase64Transform myTransform = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces))
    using (FileStream myInputFile = new FileStream(inFileName, FileMode.Open, FileAccess.Read))
    using (FileStream myOutputFile = new FileStream(outFileName, FileMode.Create, FileAccess.Write))
    using (CryptoStream cryptoStream = new CryptoStream(myInputFile, myTransform, CryptoStreamMode.Read))
    {
        cryptoStream.CopyTo(myOutputFile);
    }
}

@lx4556332
Copy link
Author

lx4556332 commented Jan 18, 2021

Thanks for the answer. It works

@lx4556332 lx4556332 reopened this Jan 18, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Feb 17, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Security untriaged New issue has not been triaged by the area owner
Projects
None yet
Development

No branches or pull requests

3 participants