Yes, you're right, the current CMS RFC talks about the message digest attribute, which
SignedAttributes in signerInfo MUST include only one instance of the message digest attribute. Similarly, AuthAttributes in AuthenticatedData MUST include only one instance of the message digest attribute.
So, the truth is, the only way to provide multiple message digest values using standard signed attributes is to provide multiple signed indexes.
And yes, any security system is as strong as its weak connection, so theoretically you won’t get anything by adding SignedInfo with SHA-256 if you still accept SHA-1 - as you said, stronger signatures can always flow.
Your custom attribute schema is a little harder to break - but there is still SHA-1 chaos that can be attacked. This is no longer as simple as simply removing the attribute - since it is covered by the signature. But:
There is also a digest algorithm that is used to digest signed attributes, which serves as the basis for the final signature value. What are you going to use there? SHA-256 or SHA-1? If it is SHA-1, then you will be in the same situation as before:
If I can make collisions for SHA-1, I would cancel your own SHA-256 attribute and fake the SHA-1 attribute so that the final SHA-1 digest for signature is added again. This shows that only gain is safe if the signature digest algorithm is also SHA-256, but I assume this is not an option since you want to stay backward compatible.
What I would like to suggest in your situation is to continue to use SHA-1, but apply RFC 3161 to your signature as an unsigned attribute. These timestamps are actually their signatures. It's good that you can use SHA-256 to print the message there, and often the timestamp server uses its signature using the same digest algorithm that you provided. Then reject any signature that either does not contain such a timestamp or contains only timestamps with fingerprint / message digest digest algorithms, weaker than SHA-256.
What is the advantage of this solution? Your legacy applications should check for the unsigned timestamp attribute and if a strong digest has been used for it, but otherwise they will be ignored and they will continue to verify signatures as before. On the other hand, new applications will verify the signature, but additionally check the timestamp. Since the timestamp signature "covers" the value of the signature, the attacker no longer has the opportunity to fake the signature. Although the signature uses SHA-1 for digest values, an attacker would have to break a stronger timestamp digest.
An additional advantage of the timestamp is that you can relate the production date to your signature - you can confidently claim that the signature was issued before the timestamp. Therefore, even if the signature certificate needs to be revoked, using the time stamp you can still decide exactly whether to reject or accept the signature depending on the time the certificate was revoked. If the certificate was revoked after the time stamp, then you can accept the signature (add a security margin (otherwise called the “grace period”) - it takes some time before the information is published), if it was revoked before the time stamp, then you want to reject the signature.
The last advantage of timestamps is that you can update them over time if some algorithms become weak. For example, you can apply a new timestamp every 5-10 years using modern algorithms, and new timestamps cover all old signatures (including old timestamps). Thus, weak algorithms are then covered by a newer, stronger timestamp signature. Look at CAdES (there is also an RFC , but it's deprecated already) that is based on CMS and is trying to apply these strategies to ensure long-term archiving of CMS signatures.