https://tools.ietf.org/html/rfc7292
Gotchas:
Algorithms:
Design:
AuthenticatedSafe property: This name comes from a type name in the RFC (the field name is authSafe), and an AuthenticatedSafe is a collection of SafeContents.ContentInfosPKCS12_unpack_authsafes (plural) to read it, suggesting a name of AuthSafe in lieu of SafeContents.Pkcs12SafeContents to [Pkcs12]AuthSafe, rename property to Auth[enticated]SafesPkcs12 on types: Would it be clearer (though somewhat inaccurate) to use Pfx instead?PublicKey enum members be removed until there is support?false when there is no MAC to verify (alternatively, InvalidOperationException)ArgumentNullException in all the expected places.InvalidOperationException:Pkcs12BuilderIsSealed == falseEncodeTryEncodeIsSealed == truePkcs12SafeContents:IsReadOnly == trueDataConfidentialityMode != NoneGetBagsDataConfidentialityMode != PasswordDecryptCryptographicException:```C#
namespace System.Security.Cryptography.Pkcs
{
public sealed partial class Pkcs9LocalKeyId : Pkcs9AttributeObject
{
public ReadOnlyMemory
public Pkcs9LocalKeyId() => throw null;
public Pkcs9LocalKeyId(ReadOnlySpan
}
public sealed partial class Pkcs12Builder
{
public bool IsSealed { get; }
public void AddSafeContentsEncrypted(Pkcs12SafeContents safeContents, ReadOnlySpan
public void AddSafeContentsEncrypted(Pkcs12SafeContents safeContents, ReadOnlySpan
public void AddSafeContentsUnencrypted(Pkcs12SafeContents safeContents) => throw null;
public byte[] Encode() => throw null;
public void SealAndMac(ReadOnlySpan
public void SealWithoutIntegrity() => throw null;
public bool TryEncode(Span
}
public sealed partial class Pkcs12Info
{
private Pkcs12Info() { }
public ReadOnlyCollection
public IntegrityMode DataIntegrityMode { get; }
public bool VerifyMac(ReadOnlySpan
public static Pkcs12Info Decode(ReadOnlyMemory
public enum IntegrityMode
{
Unknown = 0,
None = 1,
Password = 2,
PublicKey = 3,
}
}
public sealed partial class Pkcs12SafeContents
{
public ConfidentialityMode DataConfidentialityMode { get; }
public bool IsReadOnly { get; }
public void AddSafeBag(Pkcs12SafeBag safeBag) => throw null;
public CertBag AddCertificate(X509Certificate2 certificate) => throw null;
public KeyBag AddKeyUnencrypted(AsymmetricAlgorithm key) => throw null;
public ShroudedKeyBag AddShroudedKey(AsymmetricAlgorithm key, ReadOnlySpan<char> password, PbeParameters pbeParameters) => throw null;
public ShroudedKeyBag AddShroudedKey(AsymmetricAlgorithm key, ReadOnlySpan<byte> password, PbeParameters pbeParameters) => throw null;
public SecretBag AddSecret(Oid secretType, ReadOnlyMemory<byte> secretValue, bool skipCopy=false) => throw null;
public void Decrypt(ReadOnlySpan<char> password) => throw null;
public IEnumerable<Pkcs12SafeBag> GetBags() => throw null;
public enum ConfidentialityMode
{
Unknown = 0,
None = 1,
Password = 2,
PublicKey = 3,
}
}
public abstract partial class Pkcs12SafeBag
{
protected Pkcs12SafeBag(string bagIdValue) { }
public CryptographicAttributeObjectCollection Attributes { get; }
public byte[] Encode() => throw null;
public Oid GetBagId() => throw null;
public bool TryEncode(Span<byte> destination, out int bytesWritten) => throw null;
protected abstract bool TryEncodeValue(Span<byte> destination, out int bytesWritten);
}
public sealed partial class CertBag : Pkcs12SafeBag
{
public CertBag(Oid certificateType, ReadOnlyMemory<byte> encodedCertificate, bool skipCopy=false) : base(null) => throw null;
public bool IsX509Certificate { get; }
public ReadOnlyMemory<byte> EncodedCertificate { get; }
public Oid GetCertificateType() => throw null;
public X509Certificate2 GetCertificate() => throw null;
protected override bool TryEncodeValue(Span<byte> destination, out int bytesWritten) => throw null;
}
public sealed partial class KeyBag : Pkcs12SafeBag
{
public KeyBag(ReadOnlyMemory<byte> pkcs8PrivateKey, bool skipCopy=false) : base(null) { }
public ReadOnlyMemory<byte> Pkcs8PrivateKey { get; }
protected override bool TryEncodeValue(Span<byte> destination, out int bytesWritten) => throw null;
}
public sealed partial class SafeContentsBag : Pkcs12SafeBag
{
private SafeContentsBag() : base(null) { }
protected override bool TryEncodeValue(Span<byte> destination, out int bytesWritten) => throw null;
public Pkcs12SafeContents SafeContents { get; }
public static SafeContentsBag CreateEncrypted(Pkcs12SafeContents safeContents, ReadOnlySpan<byte> passwordBytes, PbeParameters pbeParameters) => throw null;
public static SafeContentsBag CreateEncrypted(Pkcs12SafeContents safeContents, ReadOnlySpan<char> password, PbeParameters pbeParameters) => throw null;
public static SafeContentsBag CreateUnencrypted(Pkcs12SafeContents contents) => throw null;
}
public sealed partial class SecretBag : Pkcs12SafeBag
{
private SecretBag() : base(null) { }
public Oid GetSecretType() => throw null;
public ReadOnlyMemory<byte> SecretValue { get; }
protected override bool TryEncodeValue(Span<byte> destination, out int bytesWritten) => throw null;
}
public sealed partial class ShroudedKeyBag : Pkcs12SafeBag
{
public ShroudedKeyBag(ReadOnlyMemory<byte> encryptedPkcs8PrivateKey, bool skipCopy=false) : base(null) { }
public ReadOnlyMemory<byte> EncryptedPkcs8PrivateKey { get; }
protected override bool TryEncodeValue(Span<byte> destination, out int bytesWritten) => throw null;
}
}
```
This functionality is greatly needed. We specifically need access to the contents of the SecretBag, from a read only perspective.
Excellent! Our only must have feature here is read-only SecretBag contents access. Thanks for working on this.
@alexkeh a bit OT, but can I ask how you are actually adding SecretBags in the first place? I haven't found any .NET libraries that have this capability
@ScotMac can answer that question better than I can.
Hi, we are currently using rsa libraries to write the record, as part of
the config setup (ie not a runtime operation). We need the .NET Core api
for the runtime read only for our fully Managed DB Client.
Thanks Scot
On Apr 20, 2018 12:23 PM, "cocowalla" notifications@github.com wrote:
@alexkeh https://github.com/alexkeh a bit OT, but can I ask how you are
actually adding SecretBags in the first place? I haven't found any .NET
libraries that have this capability—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/dotnet/corefx/issues/28249#issuecomment-383196880,
or mute the thread
https://github.com/notifications/unsubscribe-auth/Ae0eiTjI7vJ-QPODnHjcymQW05h0v2pJks5tqjWrgaJpZM4SySAl
.
As an example of the API, to take a Windows-generated PFX and remove the "FriendlyName" attribute from ShroudedKeyBags:
```C#
public static byte[] RemoveKeyNames(byte[] pfxBytes, string password)
{
Pkcs12Info info = Pkcs12Info.Decode(pfxBytes, out _, skipCopy: true);
if (info.DataIntegrityMode == Pkcs12Info.IntegrityMode.Password)
{
if (!info.VerifyMac(password))
{
throw new CryptographicException();
}
}
const string FriendlyNameOid = "1.2.840.113549.1.9.20";
Pkcs12Builder builder = new Pkcs12Builder();
foreach (Pkcs12SafeContents existingContents in info.AuthenticatedSafe)
{
if (existingContents.DataConfidentialityMode != Pkcs12SafeContents.ConfidentialityMode.None)
{
builder.AddSafeContentsUnencrypted(existingContents);
continue;
}
Pkcs12SafeContents newContents = new Pkcs12SafeContents();
foreach (Pkcs12SafeBag safeBag in existingContents.GetBags())
{
foreach (CryptographicAttributeObject attrSet in safeBag.Attributes)
{
if (attrSet.Oid.Value == FriendlyNameOid)
{
safeBag.Attributes.Remove(attrSet);
Console.WriteLine("Removing \"FriendlyName\" attribute");
break;
}
}
newContents.AddSafeBag(safeBag);
}
builder.AddSafeContentsUnencrypted(newContents);
}
builder.SealAndMac(password, HashAlgorithmName.SHA1, 2048);
return builder.Encode();
}
```
Looks good, a few comments:
Pkcs12 to avoid clashesSealAndMac to SealWithMacROS<byte> passwordBytes is named consistently (it's not on Pkcs12SafeContents.AddShroudedKey)Make sure that a language that doesn't have span support can use PKCS12.
string next to ROS<char>.I tried to use this, and can't see the new interface. Here is what i have done:
Installed Core 3.0 preview 7:
-rwxrwxrwa 1 ORADEV\smckinle 125757656 Jul 30 13:30 dotnet-sdk-3.0.100-preview7-012821-win-x64.exe
-rwxrwxrwa 1 ORADEV\smckinle 26124576 Jul 30 13:38 dotnet-runtime-3.0.0-preview7-27912-14-win-x64.exe
Installed VS 2019 Preview Version 16.3.0 Preview 1.0
The above got me to the point of being to set our Core library project to the "target framework" of .NET Standard 2.1 (ie Core 3). However, when i try to reference, eg, the new Pkcs12Info class, it isn't found.
Am i still missing something?
Most helpful comment
I tried to use this, and can't see the new interface. Here is what i have done:
Installed Core 3.0 preview 7:
-rwxrwxrwa 1 ORADEV\smckinle 125757656 Jul 30 13:30 dotnet-sdk-3.0.100-preview7-012821-win-x64.exe
-rwxrwxrwa 1 ORADEV\smckinle 26124576 Jul 30 13:38 dotnet-runtime-3.0.0-preview7-27912-14-win-x64.exe
Installed VS 2019 Preview Version 16.3.0 Preview 1.0
{
"sdk": {
"version": "3.0.100-preview7-012821"
}
}
The above got me to the point of being to set our Core library project to the "target framework" of .NET Standard 2.1 (ie Core 3). However, when i try to reference, eg, the new Pkcs12Info class, it isn't found.
Am i still missing something?