using GostCryptography.Asn1.Ber; using GostCryptography.Asn1.Gost.Gost_28147_89; using GostCryptography.Asn1.Gost.PublicKey; using GostCryptography.Properties; using System; namespace GostCryptography.Asn1.Gost.Gost_R3410 { /// /// Информация о ключе цифровой подписи ГОСТ Р 34.10 /// public abstract class Gost_R3410_KeyExchange { /// /// Информация о зашифрованном ключе ГОСТ 28147-89 /// public Gost_28147_89_KeyExchangeInfo SessionEncryptedKey { get; set; } /// /// Параметры ключа цифровой подписи ГОСТ Р 34.10 /// public Gost_R3410_KeyExchangeParams TransportParameters { get; set; } protected abstract OidValue KeyAlgorithm { get; } protected abstract Gost_R3410_PublicKeyParams CreatePublicKeyParams(); protected abstract Gost_R3410_KeyExchangeParams CreateKeyExchangeParams(); /// /// Расшифровать информацию о ключе /// public void Decode(byte[] data) { if (data == null) { throw ExceptionUtility.ArgumentNull(nameof(data)); } try { var asnDecoder = new Asn1BerDecodeBuffer(data); var keyTransport = new Gost_R3410_KeyTransport(); keyTransport.Decode(asnDecoder); DecodeSessionKey(keyTransport); DecodePublicKey(keyTransport); } catch (Exception exception) { throw ExceptionUtility.CryptographicException(exception, Resources.Asn1DecodeError, nameof(Gost_R3410_KeyTransport)); } } private void DecodeSessionKey(Gost_R3410_KeyTransport keyTransport) { SessionEncryptedKey = new Gost_28147_89_KeyExchangeInfo { EncryptionParamSet = keyTransport.TransportParams.EncryptionParamSet.Oid.Value, EncryptedKey = keyTransport.SessionEncryptedKey.EncryptedKey.Value, Mac = keyTransport.SessionEncryptedKey.MacKey.Value, Ukm = keyTransport.TransportParams.Ukm.Value }; } private void DecodePublicKey(Gost_R3410_KeyTransport keyTransport) { var publicKeyInfo = keyTransport.TransportParams.EphemeralPublicKey; var publicKeyAlgOid = publicKeyInfo.Algorithm.Algorithm.Oid.Value; if (!publicKeyAlgOid.Equals(KeyAlgorithm.Value)) { throw ExceptionUtility.CryptographicException(Resources.Asn1DecodeAlg, publicKeyAlgOid); } var choice = publicKeyInfo.Algorithm.Parameters as Asn1Choice; if (choice == null) { throw ExceptionUtility.CryptographicException(Resources.Asn1DecodeAlgorithmParameters); } var publicKeyParams = choice.GetElement() as Gost_R3410_PublicKeyParams; if (publicKeyParams == null) { throw ExceptionUtility.CryptographicException(Resources.Asn1DecodeAlgorithmParameters); } var asnDecoder = new Asn1BerDecodeBuffer(publicKeyInfo.SubjectPublicKey.Value); var publicKey = new Asn1OctetString(); publicKey.Decode(asnDecoder); TransportParameters = CreateKeyExchangeParams(); TransportParameters.PublicKeyParamSet = publicKeyParams.PublicKeyParamSet.Oid.Value; TransportParameters.DigestParamSet = publicKeyParams.DigestParamSet?.Oid.Value; TransportParameters.EncryptionParamSet = publicKeyParams.EncryptionParamSet?.Oid.Value; TransportParameters.PublicKey = publicKey.Value; TransportParameters.PrivateKey = null; } /// /// Зашифровать информацию о ключе /// public byte[] Encode() { var asnEncoder = new Asn1BerEncodeBuffer(); var keyTransport = new Gost_R3410_KeyTransport(); try { keyTransport.SessionEncryptedKey = new Gost_28147_89_EncryptedKey { EncryptedKey = new Gost_28147_89_Key(SessionEncryptedKey.EncryptedKey), MacKey = new Gost_28147_89_Mac(SessionEncryptedKey.Mac) }; keyTransport.TransportParams = new Gost_R3410_TransportParams { EncryptionParamSet = Asn1ObjectIdentifier.FromString(SessionEncryptedKey.EncryptionParamSet), EphemeralPublicKey = EncodePublicKey(TransportParameters), Ukm = new Asn1OctetString(SessionEncryptedKey.Ukm) }; keyTransport.Encode(asnEncoder); } catch (Exception exception) { throw ExceptionUtility.CryptographicException(exception, Resources.Asn1EncodeError, nameof(Gost_R3410_KeyTransport)); } return asnEncoder.MsgCopy; } private SubjectPublicKeyInfo EncodePublicKey(Gost_R3410_KeyExchangeParams transportParameters) { var asnEncoder = new Asn1BerEncodeBuffer(); var publicKey = new Asn1OctetString(transportParameters.PublicKey); publicKey.Encode(asnEncoder); var publicKeyValue = asnEncoder.MsgCopy; var publicKeyInfo = new SubjectPublicKeyInfo { SubjectPublicKey = new Asn1BitString(publicKeyValue.Length * 8, publicKeyValue) }; var publicKeyParams = CreatePublicKeyParams(); publicKeyParams.PublicKeyParamSet = Asn1ObjectIdentifier.FromString(transportParameters.PublicKeyParamSet); publicKeyParams.DigestParamSet = Asn1ObjectIdentifier.FromString(transportParameters.DigestParamSet); publicKeyParams.EncryptionParamSet = Asn1ObjectIdentifier.FromString(transportParameters.EncryptionParamSet); asnEncoder.Reset(); publicKeyParams.Encode(asnEncoder); var publicKeyAlgOid = new Asn1ObjectIdentifier(KeyAlgorithm); publicKeyInfo.Algorithm = new AlgorithmIdentifier(publicKeyAlgOid, new Asn1OpenType(asnEncoder.MsgCopy)); return publicKeyInfo; } } }