Is there a way to generate a FIPS compliant MAC for PKCS12 files?

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Is there a way to generate a FIPS compliant MAC for PKCS12 files?

Surikov Pavel
I'm trying to generate a FIPS compliant PKCS12 file, and it looks like the
default Pkcs12MacFactory cannot be used to generate a MAC, throwing the
exception 'PKCS12 PBE unavailable in approved mode: OpenSSL'. I checked the
user guide for C# NET FIPS lib, and it looks like only PBKDF2 is available
with UTF8 password converter. So I went ahead and created a custom MAC
provider that uses PBKDF2:

       
//--------------------------------------------------------------------------

        private static void ExportToPkcs12(KeyPair keyPair, string password)
        {
            using (var stream = File.Create(@"d:\share\output.pfx"))
            {
                var pbeEncryptor = GetPbeEncryptor(password);
                var pfxPduBuilder = new Pkcs12PfxPduBuilder();
               
                var certBagBuilder = new
Pkcs12SafeBagBuilder(keyPair.Certificate);
                var certBag = certBagBuilder.Build();
                pfxPduBuilder.AddEncryptedData(pbeEncryptor, certBag);

                var keyBagBuilder = new Pkcs12SafeBagBuilder(keyPair.Key,
pbeEncryptor);
                var keyBag = keyBagBuilder.Build();
                pfxPduBuilder.AddData(keyBag);

                var macFactory = GetMacFactory(password);
                var pfxPdu = pfxPduBuilder.Build(macFactory);
                var pfxBytes = pfxPdu.GetEncoded();
                stream.Write(pfxBytes, 0, pfxBytes.Length);
                stream.Flush();
            }
        }

        private static IMacFactory<Pkcs12MacAlgDescriptor>
GetMacFactory(string password)
        {
            // Throws 'PKCS12 PBE unavailable in approved mode: OpenSSL'
            /*var macFactoryBuilder = new Pkcs12MacFactoryBuilder();
            var macFactory =
macFactoryBuilder.Build(password.ToCharArray());
            return macFactory;*/

            var macFactory = new MacFactory(password);
            return macFactory;
        }

        public class MacFactory : IMacFactory<Pkcs12MacAlgDescriptor>
        {
            private IMacFactory<FipsShs.AuthenticationParameters>
baseFactory;
            private Pkcs12MacAlgDescriptor algorithmDetails;

            public MacFactory(string password)
            {
                algorithmDetails = new Pkcs12MacAlgDescriptor(new
AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance),
GetSalt(), 1024);
                var pbeDeriverBuilder =
CryptoServicesRegistrar.CreateService(FipsPbkd.PbkdF2).From(PasswordConverter.UTF8,
password.ToCharArray());
                var pbeDeriver =
pbeDeriverBuilder.WithPrf(FipsShs.Sha1).WithSalt(algorithmDetails.GetIV()).WithIterationCount(algorithmDetails.IterationCount).Build();
                baseFactory = CryptoServicesRegistrar.CreateService(new
FipsShs.Key(FipsShs.Sha1HMac, pbeDeriver.DeriveKey(TargetKeyType.MAC,
20))).CreateMacFactory(FipsShs.Sha1HMac);
            }

            public Pkcs12MacAlgDescriptor AlgorithmDetails
            {
                get { return algorithmDetails; }
            }

            public int MacLength
            {
                get { return baseFactory.MacLength; }
            }

            public IStreamCalculator<IBlockResult> CreateCalculator()
            {
                return baseFactory.CreateCalculator();
            }

            private byte[] GetSalt()
            {
                var random = new SecureRandom();
                return BigInteger.ProbablePrime(256,
random).ToByteArrayUnsigned();
            }
        }

       
//-----------------------------------------------------------------------------------

But this of course doesn't work, because the information about PBKDF2 is not
stored anywhere in the MAC itself. The question is, does the library provide
any other means to generate a MAC that will be FIPS compatible and could be
used in PKCS12 files, and if not are there any restrictions imposed by the
FIPS standard?



--
Sent from: http://bouncy-castle.1462172.n4.nabble.com/Bouncy-Castle-Dev-f1462173.html

Reply | Threaded
Open this post in threaded view
|

Re: Is there a way to generate a FIPS compliant MAC for PKCS12 files?

David Hook-3

Sorry, but the PBE algorithm used by PKCS#12 is not FIPS compliant. You
need to be using PBKDF2.

Regards,

David

On 19/3/20 1:10 am, Surikov Pavel wrote:

> I'm trying to generate a FIPS compliant PKCS12 file, and it looks like the
> default Pkcs12MacFactory cannot be used to generate a MAC, throwing the
> exception 'PKCS12 PBE unavailable in approved mode: OpenSSL'. I checked the
> user guide for C# NET FIPS lib, and it looks like only PBKDF2 is available
> with UTF8 password converter. So I went ahead and created a custom MAC
> provider that uses PBKDF2:
>
>        
> //--------------------------------------------------------------------------
>
>         private static void ExportToPkcs12(KeyPair keyPair, string password)
>         {
>             using (var stream = File.Create(@"d:\share\output.pfx"))
>             {
>                 var pbeEncryptor = GetPbeEncryptor(password);
>                 var pfxPduBuilder = new Pkcs12PfxPduBuilder();
>                
>                 var certBagBuilder = new
> Pkcs12SafeBagBuilder(keyPair.Certificate);
>                 var certBag = certBagBuilder.Build();
>                 pfxPduBuilder.AddEncryptedData(pbeEncryptor, certBag);
>
>                 var keyBagBuilder = new Pkcs12SafeBagBuilder(keyPair.Key,
> pbeEncryptor);
>                 var keyBag = keyBagBuilder.Build();
>                 pfxPduBuilder.AddData(keyBag);
>
>                 var macFactory = GetMacFactory(password);
>                 var pfxPdu = pfxPduBuilder.Build(macFactory);
>                 var pfxBytes = pfxPdu.GetEncoded();
>                 stream.Write(pfxBytes, 0, pfxBytes.Length);
>                 stream.Flush();
>             }
>         }
>
>         private static IMacFactory<Pkcs12MacAlgDescriptor>
> GetMacFactory(string password)
>         {
>             // Throws 'PKCS12 PBE unavailable in approved mode: OpenSSL'
>             /*var macFactoryBuilder = new Pkcs12MacFactoryBuilder();
>             var macFactory =
> macFactoryBuilder.Build(password.ToCharArray());
>             return macFactory;*/
>
>             var macFactory = new MacFactory(password);
>             return macFactory;
>         }
>
>         public class MacFactory : IMacFactory<Pkcs12MacAlgDescriptor>
>         {
>             private IMacFactory<FipsShs.AuthenticationParameters>
> baseFactory;
>             private Pkcs12MacAlgDescriptor algorithmDetails;
>
>             public MacFactory(string password)
>             {
>                 algorithmDetails = new Pkcs12MacAlgDescriptor(new
> AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance),
> GetSalt(), 1024);
>                 var pbeDeriverBuilder =
> CryptoServicesRegistrar.CreateService(FipsPbkd.PbkdF2).From(PasswordConverter.UTF8,
> password.ToCharArray());
>                 var pbeDeriver =
> pbeDeriverBuilder.WithPrf(FipsShs.Sha1).WithSalt(algorithmDetails.GetIV()).WithIterationCount(algorithmDetails.IterationCount).Build();
>                 baseFactory = CryptoServicesRegistrar.CreateService(new
> FipsShs.Key(FipsShs.Sha1HMac, pbeDeriver.DeriveKey(TargetKeyType.MAC,
> 20))).CreateMacFactory(FipsShs.Sha1HMac);
>             }
>
>             public Pkcs12MacAlgDescriptor AlgorithmDetails
>             {
>                 get { return algorithmDetails; }
>             }
>
>             public int MacLength
>             {
>                 get { return baseFactory.MacLength; }
>             }
>
>             public IStreamCalculator<IBlockResult> CreateCalculator()
>             {
>                 return baseFactory.CreateCalculator();
>             }
>
>             private byte[] GetSalt()
>             {
>                 var random = new SecureRandom();
>                 return BigInteger.ProbablePrime(256,
> random).ToByteArrayUnsigned();
>             }
>         }
>
>        
> //-----------------------------------------------------------------------------------
>
> But this of course doesn't work, because the information about PBKDF2 is not
> stored anywhere in the MAC itself. The question is, does the library provide
> any other means to generate a MAC that will be FIPS compatible and could be
> used in PKCS12 files, and if not are there any restrictions imposed by the
> FIPS standard?
>
>
>
> --
> Sent from: http://bouncy-castle.1462172.n4.nabble.com/Bouncy-Castle-Dev-f1462173.html
>