Home > Enterprise >  Illegal Character in constructed URI in SSIS doing PGP encryption with BouncyCastle in C#
Illegal Character in constructed URI in SSIS doing PGP encryption with BouncyCastle in C#

Time:10-18

This one's had me banging my head on the desk for a day. I've been tasked with building SSIS packages for the first time and they require PGP encryption on the file before it's dropped into a destination folder. I'll start with the code I'm having issues with in the script task:

        string keySource = "file:///C:/PubKeysSSIS/REDACTED/REDACTED.pubkey";
        string outputDest = "file:///c:/REDACTED/REDACTED.txt";
        string uriException = String.Empty;
        Uri key;
        Uri output;
        if (!Uri.TryCreate(keySource, UriKind.RelativeOrAbsolute, out key))
            uriException  = String.Concat("Unable to load public key from ", key, "\n");
        if (!Uri.TryCreate(outputDest, UriKind.RelativeOrAbsolute, out output))
            uriException  = String.Concat("Unable to load target for write command: ", outputDest, "\n");
        if (!String.IsNullOrEmpty(uriException))
            throw new InvalidParameterException(uriException);

       using (MemoryStream outStream = new MemoryStream())
        {   
            PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);
            PgpUtilities.WriteFileToLiteralData(comData.Open(outStream), PgpLiteralData.Binary, new FileInfo(unencryptedData));
        //other code that is unrelated below this point.
        }

These URIs pass the Uri.TryCreate() calls with flying colors, so the InvalidParameterException isn't thrown. However, when the execution reaches PgPUtilities.WriteFileToLiteralData(), an exception is thrown saying there's an invalid character in the URI, which seems bonkers to me unless this is a case where I've been working on something so long I'm just not seeing it.

In an earlier check, I compared the two strings with:

IEnumerable<char> invalid = Path.GetInvalidFileNameChars().Union(Path.GetInvalidPathChars());

I then was able to determine that what the function is freaking out about is a colon. This was true when I tried the path with only the drive letter and not the file:/// callout as well, so I assumed it was the drive letter colon. However, when I remove the colon from the drive letter, I still seem to get it with file:///. After searching through resources I haven't found anything on SO or CodeProject or similar sites that involves this issue. What am I doing incorrectly?

CodePudding user response:

I was correct in my comment; the problem was what was being passed and the method used. The solution was to break out the compression into it's own function and manage it all with streams.

private static byte[] Compress(byte[] data, string filename, CompressionAlgorithmTag algorithm)
    {
        using (MemoryStream compressionStream = new MemoryStream())
        {
            PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(algorithm);
            using (Stream cos = comData.Open(compressionStream))
            {
                PgpLiteralDataGenerator pldg = new PgpLiteralDataGenerator();
                using (Stream cOut = pldg.Open(cos, PgpLiteralData.Binary, filename, data.Length, DateTime.UtcNow))
                {
                    cOut.Write(data, 0, data.Length);
                }

           }
            return compressionStream.ToArray();
        }
    }

I'm now getting an error involving an unsupported method, but I believe that's because of execution in SSIS and has nothing to do with this error, so I'm posting this answer for anyone else who encounters the same problem.

  • Related