/// <summary> /// Упаковка открытого ключа ГОСТ 34.10-2012 512 и его параметров в Asn1c структуру. /// </summary> /// /// <param name="pub">Открытый ключ.</param> /// /// <returns>Asn1c структура <c>SubjectPublicKeyInfo</c> открытого /// ключа.</returns> private static SubjectPublicKeyInfo PackPublicKeyInfo2012_512( Gost3410CspObject pub) { SubjectPublicKeyInfo spki = new SubjectPublicKeyInfo(); Asn1BerEncodeBuffer buffer = new Asn1BerEncodeBuffer(); Asn1OctetString publicKey = new Asn1OctetString(pub._publicKey); publicKey.Encode(buffer); byte[] octetString = buffer.MsgCopy; spki.subjectPublicKey = new Asn1BitString( octetString.Length * 8, octetString); GostR3410_2012_PublicKeyParameters par = new GostR3410_2012_PublicKeyParameters(); par.publicKeyParamSet = fromString(pub._publicKeyParamSet); par.digestParamSet = fromString(pub._digestParamSet); par.encryptionParamSet = CreateGost28147_89_ParamSet( pub._encryptionParamSet); buffer.Reset(); par.Encode(buffer); spki.algorithm = new AlgorithmIdentifier( fromString(GostConstants.OID_CP_GOST_R3410_12_512), new Asn1OpenType(buffer.MsgCopy)); return(spki); }
/// <summary> /// Кодирование Public ключа ГОСТ 34.10 в BLOB для импорта. /// </summary> /// /// <param name="cspObject">Открытый ключ с параметрами.</param> /// <param name="alg">Тип алгоритма</param> /// /// <returns>BLOB для импорта.</returns> /// /// <exception cref="CryptographicException">При ошибках /// кодирования структуры.</exception> /// <argnull name="cspObject" /> /// /// <intdoc><para>Аналог в MS отсутствует, часть реализации /// присутствует в ImportKey. У нас функция используется еще /// и при разборе открытого клуча в обходе /// CryptoPro.Sharpei.NetDetours.CPPublicKey.</para></intdoc> /// /// <unmanagedperm action="LinkDemand" /> internal static byte[] EncodePublicBlob(Gost3410CspObject cspObject, CspAlgorithmType alg) { int keySize; int algId; switch (alg) { case CspAlgorithmType.PROV_GOST_2001_DH: keySize = GostConstants.GOST_3410EL_SIZE; algId = GostConstants.CALG_GR3410EL; break; case CspAlgorithmType.PROV_GOST_2012_256: keySize = GostConstants.GOST3410_2012_256KEY_SIZE; algId = GostConstants.CALG_GR3410_2012_256; break; case CspAlgorithmType.PROV_GOST_2012_512: keySize = GostConstants.GOST3410_2012_512KEY_SIZE; algId = GostConstants.CALG_GR3410_2012_512; break; default: throw new CryptographicException(SR.Cryptography_CSP_WrongKeySpec); } if (cspObject == null) { throw new ArgumentNullException("cspObject"); } byte[] encodedParameters = cspObject.EncodeParameters(); byte[] data = new byte[16 + encodedParameters.Length + cspObject._publicKey.Length]; data[0] = GostConstants.PUBLICKEYBLOB; data[1] = GostConstants.CSP_CUR_BLOB_VERSION; byte[] algid = BitConverter.GetBytes(algId); Array.Copy(algid, 0, data, 4, 4); byte[] magic = BitConverter.GetBytes(GostConstants.GR3410_1_MAGIC); Array.Copy(magic, 0, data, 8, 4); byte[] bitlen = BitConverter.GetBytes(keySize); Array.Copy(bitlen, 0, data, 12, 4); Array.Copy(encodedParameters, 0, data, 16, encodedParameters.Length); Array.Copy(cspObject._publicKey, 0, data, 16 + encodedParameters.Length, cspObject._publicKey.Length); return(data); }
/// <summary> /// Упаковка открытого ключа ГОСТ 34.10 и его параметров в Asn1c структуру. /// </summary> /// /// <param name="pub">Открытый ключ.</param> /// <param name="alg"></param> /// /// <returns>Asn1c структура <c>SubjectPublicKeyInfo</c> открытого /// ключа.</returns> /// private static SubjectPublicKeyInfo PackPublicKeyInfo( Gost3410CspObject pub, CspAlgorithmType alg) { switch (alg) { case CspAlgorithmType.Gost2001: return(PackPublicKeyInfo2001(pub)); case CspAlgorithmType.Gost2012_256: return(PackPublicKeyInfo2012_256(pub)); case CspAlgorithmType.Gost2012_512: return(PackPublicKeyInfo2012_512(pub)); default: throw new CryptographicException( "Cryptography_CSP_WrongKeySpec"); } }
/// <summary> /// Разбор декодированной ASN1c структуры ГОСТ 34.10-2012 <c>SubjectPublicKeyInfo</c>. /// </summary> /// /// <param name="spki">ASN1c структура <c>SubjectPublicKeyInfo</c>. /// </param> /// /// <returns>Параметры открытого ключа.</returns> /// <argnull name="spki" /> /// <exception cref="ArgumentException">Если вложенная структура /// не приводится к <c>GostR3410_2001_PublicKeyParameters</c> /// </exception> private static Gost3410CspObject UnpackPublicKeyInfo2012( SubjectPublicKeyInfo spki) { if (spki == null) { throw new ArgumentNullException("spki"); } Asn1Choice choice = spki.algorithm.parameters as Asn1Choice; if (choice == null) { throw new ArgumentException( "spki.algorithm.parameters"); } GostR3410_2012_PublicKeyParameters publicKeyParameters = choice.GetElement() as GostR3410_2012_PublicKeyParameters; if (publicKeyParameters == null) { throw new ArgumentException( "spki.algorithm.parameters.element"); } byte[] bitString = spki.subjectPublicKey.Value; Asn1BerDecodeBuffer buffer = new Asn1BerDecodeBuffer(bitString); Asn1OctetString publicKey = new Asn1OctetString(); publicKey.Decode(buffer); Gost3410CspObject ret = new Gost3410CspObject(); ret._publicKeyParamSet = toString( publicKeyParameters.publicKeyParamSet); ret._digestParamSet = toString( publicKeyParameters.digestParamSet); ret._encryptionParamSet = toString( publicKeyParameters.encryptionParamSet); ret._publicKey = publicKey.Value; ret._privateKey = null; return(ret); }
/// <summary> /// Разбор BLOB открытого ключа ГОСТ 34.10. /// </summary> /// /// <param name="obj">Gost3410CspObject</param> /// <param name="data">BLOB</param> /// <param name="alg">Тип алгоритма</param> /// /// <argnull name="obj" /> /// <exception cref="CryptographicException">Если /// <paramref name="obj"/> не объект типа /// <see cref="Gost3410CspObject"/></exception> /// /// <intdoc><para>Аналог в MS отсутствует, часть реализации /// присутствует в ImportKey. </para></intdoc> /// /// <unmanagedperm action="LinkDemand" /> internal static void DecodePublicBlob(Object obj, byte[] data, CspAlgorithmType alg) { int keySize; switch (alg) { case CspAlgorithmType.PROV_GOST_2001_DH: keySize = GostConstants.GOST_3410EL_SIZE; break; case CspAlgorithmType.PROV_GOST_2012_256: keySize = GostConstants.GOST3410_2012_256KEY_SIZE; break; case CspAlgorithmType.PROV_GOST_2012_512: keySize = GostConstants.GOST3410_2012_512KEY_SIZE; break; default: throw new CryptographicException(SR.Cryptography_CSP_WrongKeySpec); } if (obj == null) { throw new ArgumentNullException("obj"); } Gost3410CspObject cspObject = obj as Gost3410CspObject; if (cspObject == null) { throw new CryptographicException(GostConstants.NTE_BAD_ALGID); } if (data.Length < 16 + keySize / 8) { throw new CryptographicException(GostConstants.NTE_BAD_DATA); } // CRYPT_PUBKEYPARAM -> 8 { Magic, BitLen ) uint magic = BitConverter.ToUInt32(data, 8); uint bitlen = BitConverter.ToUInt32(data, 12); if (magic != GostConstants.GR3410_1_MAGIC) { throw new CryptographicException(GostConstants.NTE_BAD_DATA); } if (bitlen != keySize) { throw new CryptographicException(GostConstants.NTE_BAD_DATA); } byte[] tmp = new byte[data.Length - 16 - keySize / 8]; Array.Copy(data, 16, tmp, 0, data.Length - 16 - keySize / 8); var publicKeyParameters = new GostKeyExchangeParameters(); var encodeKeyParameters = new byte[(data.Length - 16) - keySize / 8]; Array.Copy(data, 16, encodeKeyParameters, 0, (data.Length - 16) - keySize / 8); publicKeyParameters.DecodeParameters(encodeKeyParameters); var publicKey = new byte[keySize / 8]; Array.Copy(data, data.Length - keySize / 8, publicKey, 0, keySize / 8); publicKeyParameters.PublicKey = publicKey; cspObject._publicKey = publicKeyParameters.PublicKey; cspObject._publicKeyParamSet = publicKeyParameters.PublicKeyParamSet; cspObject._digestParamSet = publicKeyParameters.DigestParamSet; }