コード例 #1
0
 private static void AssertSignerTraits(SignerInfo signerInfo, SignerProfile profile)
 {
     Assert.Equal(profile.Type, signerInfo.SignerIdentifier.Type);
     Assert.Equal(profile.Cert, signerInfo.Certificate);
     AssertMaybeEmpty(profile.HasSignedAttrs, signerInfo.SignedAttributes);
     AssertMaybeEmpty(profile.HasUnsignedAttrs, signerInfo.UnsignedAttributes);
     AssertMaybeEmpty(profile.HasCounterSigners, signerInfo.CounterSignerInfos);
 }
コード例 #2
0
        public static void CounterSigningReindexes()
        {
            ContentInfo content = new ContentInfo(new byte[] { 7 });
            SignedCms   cms     = new SignedCms(content);

            using (X509Certificate2 cert1 = Certificates.RSA2048SignatureOnly.TryGetCertificateWithPrivateKey())
                using (X509Certificate2 cert2 = Certificates.RSAKeyTransferCapi1.TryGetCertificateWithPrivateKey())
                {
                    CmsSigner signer = new CmsSigner(SubjectIdentifierType.SubjectKeyIdentifier, cert1);
                    cms.ComputeSignature(signer);

                    SignerProfile yellow = new SignerProfile(
                        cert1,
                        SubjectIdentifierType.SubjectKeyIdentifier,
                        hasSignedAttrs: false,
                        hasUnsignedAttrs: false,
                        hasCounterSigners: false);

                    AssertSignerTraits(cms.SignerInfos[0], yellow);

                    signer.SignedAttributes.Add(new Pkcs9SigningTime());
                    signer.SignerIdentifierType = SubjectIdentifierType.IssuerAndSerialNumber;
                    cms.ComputeSignature(signer);

                    SignerProfile green = new SignerProfile(
                        cert1,
                        SubjectIdentifierType.IssuerAndSerialNumber,
                        hasSignedAttrs: true,
                        hasUnsignedAttrs: false,
                        hasCounterSigners: false);

                    // No reordering.  0 stayed 0, new entry becomes 1.
                    AssertSignerTraits(cms.SignerInfos[0], yellow);
                    AssertSignerTraits(cms.SignerInfos[1], green);

                    signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert2);
                    cms.ComputeSignature(signer);

                    SignerProfile grey = new SignerProfile(
                        cert2,
                        SubjectIdentifierType.IssuerAndSerialNumber,
                        hasSignedAttrs: false,
                        hasUnsignedAttrs: false,
                        hasCounterSigners: false);

                    // No reordering.  0 stayed 0, 1 stays 1, new entry is 2.
                    AssertSignerTraits(cms.SignerInfos[0], yellow);
                    AssertSignerTraits(cms.SignerInfos[1], green);
                    AssertSignerTraits(cms.SignerInfos[2], grey);

                    CmsSigner  counterSigner = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert1);
                    SignerInfo toCounterSign = cms.SignerInfos[0];
                    toCounterSign.ComputeCounterSignature(counterSigner);

                    // Reordering just happened.
                    // We counter-signed the first element, so it gets bigger by ~a signerinfo, or 100% bigger.
                    // The sizes of the three were
                    //   yellow: 311 bytes
                    //   green: 455 bytes (IssuerAndSerialNumber takes more bytes, and it has attributes)
                    //   grey: 212 bytes (1024-bit RSA signature instead of 2048-bit)
                    //
                    // Because yellow also contains cyan (444) bytes (then also some overhead) it has grown
                    // to 763 bytes.  So the size-sorted order (DER SET-OF sorting) is { grey, green, yellow }.

                    // Record that yellow gained a countersigner (and thus an unsigned attribute)
                    yellow.HasUnsignedAttrs  = true;
                    yellow.HasCounterSigners = true;

                    SignerProfile cyan = new SignerProfile(
                        cert1,
                        SubjectIdentifierType.IssuerAndSerialNumber,
                        hasSignedAttrs: true,
                        hasUnsignedAttrs: false,
                        hasCounterSigners: false);

                    AssertSignerTraits(cms.SignerInfos[0], grey);
                    AssertSignerTraits(cms.SignerInfos[1], green);
                    AssertSignerTraits(cms.SignerInfos[2], yellow);
                    AssertSignerTraits(cms.SignerInfos[2].CounterSignerInfos[0], cyan);

                    counterSigner.UnsignedAttributes.Add(new Pkcs9SigningTime());
                    toCounterSign.ComputeCounterSignature(counterSigner);

                    SignerProfile red = new SignerProfile(
                        cert1,
                        SubjectIdentifierType.IssuerAndSerialNumber,
                        hasSignedAttrs: true,
                        hasUnsignedAttrs: true,
                        hasCounterSigners: false);

                    // Since "red" has one more attribute than "cyan", but they're otherwise the same
                    // it will sort later.

                    AssertSignerTraits(cms.SignerInfos[0], grey);
                    AssertSignerTraits(cms.SignerInfos[1], green);
                    AssertSignerTraits(cms.SignerInfos[2], yellow);
                    AssertSignerTraits(cms.SignerInfos[2].CounterSignerInfos[0], cyan);
                    AssertSignerTraits(cms.SignerInfos[2].CounterSignerInfos[1], red);

                    counterSigner.SignerIdentifierType = SubjectIdentifierType.SubjectKeyIdentifier;
                    toCounterSign.ComputeCounterSignature(counterSigner);

                    SignerProfile clear = new SignerProfile(
                        cert1,
                        SubjectIdentifierType.SubjectKeyIdentifier,
                        hasSignedAttrs: true,
                        hasUnsignedAttrs: true,
                        hasCounterSigners: false);

                    // By changing from IssuerAndSerialNumber to SubjectKeyIdentifier, this copy will
                    // sort higher.  It saves so many bytes, in this specific case, that it goes first.

                    AssertSignerTraits(cms.SignerInfos[0], grey);
                    AssertSignerTraits(cms.SignerInfos[1], green);
                    AssertSignerTraits(cms.SignerInfos[2], yellow);
                    AssertSignerTraits(cms.SignerInfos[2].CounterSignerInfos[0], clear);
                    AssertSignerTraits(cms.SignerInfos[2].CounterSignerInfos[1], cyan);
                    AssertSignerTraits(cms.SignerInfos[2].CounterSignerInfos[2], red);

                    // Now start removing things.

                    cms.SignerInfos[2].RemoveCounterSignature(1);

                    // Fairly predictable.
                    AssertSignerTraits(cms.SignerInfos[0], grey);
                    AssertSignerTraits(cms.SignerInfos[1], green);
                    AssertSignerTraits(cms.SignerInfos[2], yellow);
                    AssertSignerTraits(cms.SignerInfos[2].CounterSignerInfos[0], clear);
                    AssertSignerTraits(cms.SignerInfos[2].CounterSignerInfos[1], red);

                    cms.SignerInfos[2].RemoveCounterSignature(1);

                    // Fairly predictable.
                    AssertSignerTraits(cms.SignerInfos[0], grey);
                    AssertSignerTraits(cms.SignerInfos[1], green);
                    AssertSignerTraits(cms.SignerInfos[2], yellow);
                    AssertSignerTraits(cms.SignerInfos[2].CounterSignerInfos[0], clear);

                    cms.SignerInfos[2].RemoveCounterSignature(0);

                    // We have removed the last counter-signer.
                    // yellow is now smaller than grey.
                    // But the document only re-normalizes on addition.

                    yellow.HasCounterSigners = false;
                    yellow.HasUnsignedAttrs  = false;

                    AssertSignerTraits(cms.SignerInfos[0], grey);
                    AssertSignerTraits(cms.SignerInfos[1], green);
                    AssertSignerTraits(cms.SignerInfos[2], yellow);

                    // Export/import to normalize. Everyone's back to their original size,
                    // but they were unsorted before. { grey, yellow, green } was the right order.
                    cms.Decode(cms.Encode());

                    AssertSignerTraits(cms.SignerInfos[0], grey);
                    AssertSignerTraits(cms.SignerInfos[1], yellow);
                    AssertSignerTraits(cms.SignerInfos[2], green);

                    cms.SignerInfos[0].ComputeCounterSignature(counterSigner);

                    // Move to the end of the line, Mr. Grey
                    grey.HasUnsignedAttrs  = true;
                    grey.HasCounterSigners = true;

                    AssertSignerTraits(cms.SignerInfos[0], yellow);
                    AssertSignerTraits(cms.SignerInfos[1], green);
                    AssertSignerTraits(cms.SignerInfos[2], grey);
                    AssertSignerTraits(cms.SignerInfos[2].CounterSignerInfos[0], clear);
                }
        }