Всем спасибо за отклики.
Лирика (больше к этому возвращаться не буду): так уж вышло, что с этой задачкой решил разобраться сам (не владея C#, ничего не ведая вообще о криптографии). Обсуждать почему так, наверное нет смысла, так уж вышло (правильно это или нет - тоже вопрос спорный - уж как есть). Соответственно вводная такая: решает задачу профан, на сильно узком специализированном форуме, где люди в теме и как программировать и что такое криптография, отсюда и сухие ответы и "нет рассусоливаний и вообще учится надо было в школе". Посему лишний раз не знаешь как сформулировать вопрос: ибо тут и синтаксис языка, тут и маршализация, тут абсолютное незнание предметной области и все это наслоение приводит к тому, что вопрос получится дурацким, на который ответа и не будет.
Поставленная задача благополучно решается с использованием КриптоПро .NET (скачал с сайт. проверил - работает). Просто весь функционал, заключается лишь в одном методе подписания только одного типа файлов (для нашей задачи). В общем решил попробовать обойтись без него.
Есть понимание того, что собственные усилия должны быть, и негоже сидеть и просить на форуме, я написал строчку "А", скорее говорите мне сточку "Б". Стараюсь, но да, незнание предметной области и средства разработки - это сильно ужасно)). Я все понимаю, спасибо всем, кто помогает.
Лирике конец.
Итак,
Автор: two_oceans 
Далее Вы либо можете:
1) в вновь созданный из CertData контекст сертификата сохранить ссылку на контейнер (так как Вы все равно получили данные сертификата из контейнера, то у Вас ссылка по сути уже есть, но надо ее сохранить в pCertContext);
Вот этого бы и хотелось. Не понимаю как сделать. Ведь Крипто-Про .Net как-то это внутри себя делает, например:
Код:CspParameters csp = null;
csp = new CspParameters();
csp.ProviderType = 80;
csp.KeyContainerName = "тут имя контейнера";
cspGost = new Gost3410_2012_256CryptoServiceProvider(csp);
И после этого, о чудо:
certGOST = cspGost.ContainerCertificate;
И тут тебе и ссылка на сертификат и его атрибуты (чтобы сверить с имеющимися подписями в файле: а не подписан ли этот PDF уже этим сертификатом - это для логики программы).
И ссылка на закрытый ключ, тоже доступна:
И далее все подписывается .NET
Код:CmsSigner cmsSigner = new CmsSigner(x509);
signedCms.ComputeSignature(cmsSigner, false);
Именно поэтому и хотелось чтобы:
Код:var pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING, sb, (int)pcbData);
X509Certificate2 x509 = new X509Certificate2();
x509.Import(sb);
Каким-то образом содержал ссылку на контейнер закрытого ключа. Ведь Крипто-Про .Net как то ее получает. (Но на то видать он и отдельный удобный для разработчиков продукт).
И для меня бы p/invoke кончалось получением сертификата с токена (без необходимости помещения его в хранилище Личное). А дальше .Net.
Автор: two_oceans 
2) поискать в хранилище сертификатов этот же сертификат с проставленной ссылкой на контейнер (это для случаев когда получили сертификат не из контейнера или вообще получили только отпечаток сертификата);
Покопавшись, я написал как сделать это программно, а именно крайне кривое решение (для моей задачи), программно экспортировать сертификат в Личное, с установкой на него ссылки на закрытый ключ:
Код:CryptoApi.CRYPT_KEY_PROV_INFO cryptKeyProvInfo =
new CryptoApi.CRYPT_KEY_PROV_INFO();
cryptKeyProvInfo.pwszProvName = name;
cryptKeyProvInfo.pwszContainerName = container +'\0';
cryptKeyProvInfo.dwProvType = 80;
cryptKeyProvInfo.dwFlags = 1; // CERT_SET_KEY_CONTEXT_PROP_ID | CERT_SET_KEY_PROV_HANDLE_PROP_ID
cryptKeyProvInfo.cProvParam = 0;
cryptKeyProvInfo.rgProvParam = IntPtr.Zero;
cryptKeyProvInfo.dwKeySpec = 2 /* AT_SIGNATURE */;
pvData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CryptoApi.CRYPT_KEY_PROV_INFO)));
Marshal.StructureToPtr(cryptKeyProvInfo, pvData, false);
if (CryptoApi.CertSetCertificateContextProperty(certificate.Handle, 2 /* CERT_KEY_PROV_INFO_PROP_ID */, 0, pvData)) //
{
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
store.Add(certificate);
store.Close();
}
Затем искать этот сертификат в хранилище и найдя его (он содержит ссылку на закрытый ключ) спокойно использовать .Net. А потом подписав удалять его из Личного чтоль ...(так как по логике не хотим, чтобы он там хранился). Криво. Очень.
Я действительно (облазив форум и интернет) не смог понять, для контекста сертификата, который получен:
Код:int certSize = 0;
if (!CryptoApi.CryptGetKeyParam(keyHandle, KP_CERTIFICATE, null, ref certSize, 0))
var certResult = new byte[certSize];
if (!CryptoApi.CryptGetKeyParam(keyHandle, KP_CERTIFICATE, certResult, ref certSize, 0))
var pCertContext = CryptoApi.CertCreateCertificateContext(X509_ASN_ENCODING, certResult, certSize);
Нельзя прописать ссылку на закрытый ключ, хотя этот сертификат же лежит рядом с закрытым ключем в контейнере на токене, и дальше им пользоваться с использованием CmsSigner, а вот если ты его экспортируешь в Личное, потом достанешь из Личного - то пожалуйста - пользуйся....Вот совсем не понимаю.
Это бы решило мою задачу и все ). Но остается некое чувство (от недопонимания предметной области, хоть и курю интернет), что я чего-то не знаю, и можно установить ссылку и не использовать дальше p/invoke с его сложной для меня CryptSignMessage.Автор: two_oceans 
3) использовать hProv напрямую в низкоуровневых функциях подписания. То есть каким-то своим способом сохраните соответствие сертификата и имени контейнера (с описателем нужен ключ обмена или ключ подписи из контейнера).
Вот совсем растерялся и скажу честно не понял совсем.
Автор: two_oceans 
Судя по описанию задачи установка в хранилище сертификатов не предусмотрена;
Да.
Автор: two_oceans 
третий вариант наверно будет слишком сложен
Да.
Автор: two_oceans 
тогда Вам остается вариант 1 и далее предложенная функция CryptSignMessage (структура там конечно большая, но есть куча примеров как ее заполнять на разных языках и средах программирования).
Видимо да. Примеры нашел. Даже из них пока многое непонятно, так как не подписывает пока. Следующим постом спрошу про параметры этого метода, напишу, что не понимаю в нем...
Всем спасибо ).