Серия медитаций по асимметричному ключу (3): открытые ключи, подписи и сертификаты
Серия медитаций по асимметричному ключу (3): открытые ключи, подписи и сертификаты

Проверьте информацию сертификата с помощью Easy Encryption Tool

Введение в простые инструменты шифрования

Адрес проекта

Способ установки:pip install easy-encryption-tool

Анализ эффекта сертификата
Анализ эффекта сертификата

Цифровые подписи и сертификаты

в предыдущей статье«Серия медитаций на асимметричный ключ (2): разговоры о RSA и цифровых подписях»середина,Мы рассказали о понятии цифровой подписи,Сравнивалась связь между цифровыми подписями, MAC и значениями хеш-функции.

В этой статье мы говорим о сценариях использования цифровых подписей при аутентификации личности.

Цифровой сертификат, удостоверение личности в онлайн-мире

Многим веб-сайтам или приложениям перед публикацией в Интернете необходимо подать заявку на получение сертификата, чтобы доказать, что веб-сайт является законным.

Что касается цифрового сертификата, мы можем рассматривать его как своего рода удостоверение личности в онлайн-мире. Как правило, это авторитетный электронный документ, выданный авторитетным центром, который может обеспечить проверку личности в Интернете. Люди могут использовать его в Интернете. связи, чтобы подтвердить свою личность и идентифицировать другую сторону.

Например, когда мы посещаемhttps://www.baidu.comчас,Вы можете увидеть узор в форме 🔐 в левом верхнем углу адресной строки браузера.,Нажмите, чтобы просмотреть информацию о сертификате на этом веб-сайте:

image.png
image.png

При использовании браузера для доступа к веб-сайту,Браузер можно абстрактно понимать как сторонний центр сертификации.,https://www.baidu.comможно понимать как Учреждения, получившие Сертификат,И учреждение, выдавшее данный Сертификат,Мы можем назвать это центром сертификации.,В реальном мире его обычно называют CA.

Сертификат подобен удостоверению личности, доказывающему, что «открытый ключ соответствует веб-сайту».

Состав сертификата

В целом сертификат содержит следующее содержание:

  • Издатель Сертификата
  • Срок действия Сертификата
  • открытый ключ
  • Владелец сертификата (Тема)
  • Алгоритм, используемый для подписи
  • Отпечатки пальцев и алгоритмы отпечатков пальцев и т. д.
    Сертификатинформация
    Сертификатинформация
открытый ключ, выданный учреждением Сертификата
открытый ключ, выданный учреждением Сертификата

Простая абстракция модели сертификата

В этой статье мы не будем подробно останавливаться на каждом поле сертификата.

В этой статье основное внимание уделяется ключевым вопросам сертификатов и удостоверений личности, поэтому мы просто абстрагируем сертификаты следующим образом:

абстрактная модель
абстрактная модель

Здесь мы предполагаем, что сертификат содержит следующую простую информацию:

  • Информация об эмитенте
  • одеяло Информация об эмитенте
  • одеялопроблема ВОЗоткрытый ключ
  • Другая дополнительная информация

И в этой статье мы игнорируем цепочку доверия сертификата и абстрагируем только три роли:

  • центр сертификации
  • Учреждения, получившие Сертификат
  • сторонний верификатор

центр сертификации

центр сертификации
центр сертификации

центр сертификации, его открытый ключ доступен всем пользователям или учреждениям.

Здесь мы по умолчанию указываем, что центр сертификации является независимым и авторитетным.

Организация или приложение, которому был выдан сертификат

Организация или приложение, которому был выдан сертификат
Организация или приложение, которому был выдан сертификат

Организация или приложение, которому был выдан сертификат, который также предоставляет услуги всем пользователям Интернета, его открытый ключ также находится в свободном доступе для всех пользователей.

А услуги, предоставляемые организацией, выдавшей сертификат, также могут быть свободно доступны всем пользователям. Таким образом, любой пользователь, обращающийся к приложению, является проверяющим его сертификата.

Простое моделирование применения сертификата

Или реализация моделирования на основе RSA

В этой статье мы по-прежнему проводим эксперименты на основе классического алгоритма асимметричного ключа RSA.

Прежде чем приступить к моделированию реализации сертификата, давайте сначала рассмотрим характеристики подписей RSA.

Генерация ключей

Мы определяем следующую логику генерации пары ключей RSA:

Язык кода:python
кодКоличество запусков:0
копировать
def generate_rsa_keypair(key_size: int = 2048, exponent: int = 65537) -> Tuple[RSAPublicKey, RSAPrivateKey]:
    """
        Справочная документация:
            https://www.cnblogs.com/caidi/p/14794952.html
    """
    private_key = rsa.generate_private_key(
        public_exponent = exponent,
        key_size = key_size,
        backend = default_backend()
    )
    public_key = private_key.public_key()
    # print("pubkey: e={}, n={}".format(public_key.public_numbers().e, public_key.public_numbers().n))
    # print("prikey: d={}, n={}".format(private_key.private_numbers().d, private_key.public_key().public_numbers().n))
    return public_key, private_key

Размер ключа по умолчанию составляет 2048 бит, что соответствует 256 байтам.

Характеристики длины ключа

Длина ключа RSA может быть получена либо из открытого, либо из закрытого ключа и выражается в битовой длине.

Язык кода:python
кодКоличество запусков:0
копировать
    def test_key_size(self):
        """
        Одна и та же пара открытого и закрытого ключей имеет одинаковую длину ключа.
        Либооткрытый ключ Длина зашифрованных данных зашифрованного текста или длина данных подписи после подписи секретным ключом соответствуют длине ключа, оба значения представляют собой длину ключа в байтах.
        Размер длины ключа равен количеству битов, необходимых для значения n.
        """
        pub_key, pri_key = rsa_base.generate_rsa_keypair()
        print("pub_key key size:{}, pri_key key size:{}".format(pub_key.key_size, pri_key.key_size))
        self.assertEqual(pub_key.key_size, pri_key.key_size)
        self.assertEqual(pub_key.key_size, pub_key.public_numbers().n.bit_length())
        self.assertEqual(pri_key.key_size, pub_key.public_numbers().n.bit_length())
key size
key size

Характеристики длины зашифрованного текста

После определения размера пары ключей,Независимо от того, зашифровано оно или подписано, длина группы зашифрованного текста определяется.

Поскольку RSA также является режимом блочного шифрования, длина каждого блока соответствует длине ключа.

Язык кода:python
кодКоличество запусков:0
копировать
    def test_rsa_cipher_size(self):
        pub_key, pri_key = rsa_base.generate_rsa_keypair()
        plain: bytes = b"hello,world"
        cipher = pub_key.encrypt(plaintext = plain, padding = padding.OAEP(
            mgf = padding.MGF1(algorithm = hashes.SHA256()),
            algorithm = hashes.SHA256(),
            label = None))
        self.assertEqual(len(cipher), pub_key.key_size // 8)
        signature = pri_key.sign(data = plain, padding = padding.PSS(
            mgf = padding.MGF1(hashes.SHA256()),
            salt_length = padding.PSS.MAX_LENGTH
        ), algorithm = hashes.SHA256())
        self.assertEqual(len(signature), pub_key.key_size // 8)

Когда длина открытого текста не превышает длину пакета, длина зашифрованного текста и длина значения подписи остаются равными 256 байтам.

О максимальной длине открытого текста в шифровании RSA,Вы можете обратиться к подписанной статье:«Серия медитаций с асимметричным ключом (1): Обзор выборочных атак с использованием зашифрованного текста в режиме заполнения PKCSv1.5 по специальной теме RSA» рассуждение в.

Имитация генерации сертификатов

Определение содержания сертификата

Как мы упоминали ранее, мы просто абстрагируем содержимое сертификата и не восстанавливаем полностью исходные поля сертификата.

Наш сертификат теперь резюмируется как:

аннотация Содержание сертификата
аннотация Содержание сертификата

При реализации мы определяем следующую логику:

Язык кода:python
кодКоличество запусков:0
копировать
SUBJECT_KEY: str = 'subject'
AWARDED_PUB_KEY: str = 'awarded_pub_key'
ISSUER_NAME_KEY: str = 'issuer_name'
HASH_ALG_KEY: str = 'hash_alg'
HASH_NAME_KEY: str = 'hash_name'
HASH_BLOCK_SIZE_KEY: str = 'block_size'
HASH_DIGEST_SIZE_KEY: str = 'digest_size'
SIGNATURE_KEY: str = 'signature'

def mock_serialize_cert_content(subject: str,
                                awarded_pub_key: RSAPublicKey,
                                issuer_name: str,
                                hash_alg: hashes.HashAlgorithm) -> bytes:
    """
    Сначала структурируйте содержимое Сертификата в объект json, а затем закодируйте этот объект json в поток байтов.
    Args:
        hash_alg: Алгоритм хеширования, используемый подписью
        subject: Тема сертификата
        awarded_pub_key: фото лица, награждаемого ключ
        issuer_name: орган, выдавший документ
    Returns: объект json, закодированный как возвращенный поток байтов
    """
    # вернооткрытый ключ для кодировки base64
    meta_data: Dict[str, str] = {
        SUBJECT_KEY: subject,
        AWARDED_PUB_KEY: pub_key_base64_encode(awarded_pub_key),
        ISSUER_NAME_KEY: issuer_name,
        HASH_ALG_KEY: json.dumps({
            HASH_NAME_KEY: hash_alg.name,
            HASH_BLOCK_SIZE_KEY: hash_alg.block_size,
            HASH_DIGEST_SIZE_KEY: hash_alg.digest_size
        })
    }
    # print("cert raw meta data:{}".format(meta_data))
    meta_data_bytes = json.dumps(meta_data).encode(encoding = 'utf-8')
    return meta_data_bytes

def mock_deserialize_cert_content(raw_data: bytes) -> Dict[str, str]:
    raw_str = raw_data.decode(encoding = 'utf-8')  # Преобразовать в строку
    raw_dict: Dict[str, str] = json.loads(raw_str)  # Десериализовать в объект json
    return raw_dict

Отдельно следует пояснить, что касается кодирования открытого ключа эмитента, здесь мы определяем его как данные, в которых данные открытого ключа сериализуются в соответствии с форматом PEM, а затем кодируются в формате Base64. Его реализация может быть определена. как:

Язык кода:python
кодКоличество запусков:0
копировать
def pub_key_base64_encode(pub_key: RSAPublicKey) -> str:
    p_bytes = pub_key.public_bytes(encoding = serialization.Encoding.PEM,
                                   format = serialization.PublicFormat.SubjectPublicKeyInfo)
    b64_bytes = base64.b64encode(p_bytes)
    return b64_bytes.decode(encoding = 'utf-8')


def pub_key_base64_decode(pub_key_b64: str) -> RSAPublicKey:
    pub_key_raw_bytes = base64.b64decode(pub_key_b64)
    public_key = serialization.load_pem_public_key(
        pub_key_raw_bytes,
        backend = default_backend()
    )
    return public_key

Моделирование выдачи сертификата

Выдан Сертификат
Выдан Сертификат

Выдача сертификата — это процесс подписания на основе содержания сертификата.

Мы моделируем это как следующую реализацию:

Язык кода:python
кодКоличество запусков:0
копировать
def mock_create_cert(subject: str,
                     awarded_pub_key: RSAPublicKey,
                     issuer_pri_key: RSAPrivateKey,
                     issuer_name: str,
                     hash_alg: hashes.HashAlgorithm) -> bytes:
    """
    Имитация выдачи Сертификата. Сертификат здесь представлен в байтовой форме, которую позже можно закодировать в различных форматах.
    Args:
        hash_alg: Алгоритм хеширования, используемый подписью
        subject: Тема сертификата
        awarded_pub_key: фото лица, награждаемого ключ
        issuer_pri_key: Закрытый ключ эмитента
        issuer_name: орган, выдавший документ
    Returns: Информация о сертификате, содержание Сертификата + Фирменная композиция
    """
    meta_data_bytes = mock_serialize_cert_content(subject, awarded_pub_key, issuer_name, hash_alg)
    # print("meta data:{}".format(str(meta_data_bytes)))
    signature = rsa_sign.sign_raw_message(issuer_pri_key, meta_data_bytes, hash_alg)
    # print("signature:{}".format(signature))
    return meta_data_bytes + signature

Здесь вы можете увидеть окончательно сгенерированное содержимое сертификата, которое на самом деле представляет собой простую сборку исходного содержимого сертификата + значение подписи:

Имитированное содержание сертификата
Имитированное содержание сертификата

Моделирование внедрения центра сертификации

Язык кода:python
кодКоличество запусков:0
копировать
class MockIssuer(object):
    """
    Имитированный центр сертификации
    Используется для выдачи сертификата нижестоящим учреждениям.
    центр сертификация имеет собственную пару открытого и закрытого ключей.
    """
    
    def __init__(self, this_issuer_name: str, this_issuer_hash_alg: hashes.HashAlgorithm = hashes.SHA256()):
        self.__root_issuer_pub_key, self.__root_issuer_pri_key = rsa_base.generate_rsa_keypair()
        self.__issuer_name = this_issuer_name
        self.__issuer_hash = this_issuer_hash_alg
    
    @property
    def pub_key(self) -> RSAPublicKey:
        return self.__root_issuer_pub_key
    
    @property
    def issuer_name(self) -> str:
        return self.__issuer_name
    
    @property
    def issuer_hash(self) -> hashes.HashAlgorithm:
        return self.__issuer_hash
    
    def mock_issue_cert(self, subject: str, awarded_pub_key: RSAPublicKey) -> bytes:
        """
        Выдача Сертификата нижестоящим организациям
        Args:
            subject: Тема Сертификата может быть связана с выдающим лицом, и эмитент может заполнить его самостоятельно.
            awarded_pub_key: фото лица, награждаемого ключ
        Returns: Информация о сертификате, форма потока байтов, незакодированная
        """
        return mock_create_cert(subject, awarded_pub_key,
                                self.__root_issuer_pri_key,
                                self.__issuer_name,
                                self.__issuer_hash)

Олицетворение выдающего центра сертификации

Язык кода:python
кодКоличество запусков:0
копировать
class MockAwarded(object):
    """
    Имитировать субъекта, которому был выдан Сертификат
    Эта организация получит финансирование от центра сертификациииз Сертификатинформация    В то же время он подпишет данные для проверки сторонними проверяющими, тем самым доказывая, что он действительно владеет закрытым ключом.
    """
    
    def __init__(self, awarded_name: str):
        # # Выдается субъектом открытый ключ и закрытый ключ
        self.__awarded_pub_key, self.__awarded_pri_key = rsa_base.generate_rsa_keypair()
        self.__awarded_name = awarded_name  # Название выдаваемой организации
        self.__awarded_cert = bytes([0x00 for _ in range(256)])  # Зависит отцентр сертификациипроблемаиз Сертификат        self.__default_hash_alg = hashes.SHA256()
    
    @property
    def name(self):
        return self.__awarded_name
    
    @property
    def pub_key(self) -> RSAPublicKey:
        return self.__awarded_pub_key
    
    @property
    def awarded_cert(self) -> bytes:
        return self.__awarded_cert
    
    @awarded_cert.setter
    def awarded_cert(self, cert: bytes):
        self.__awarded_cert = cert
    
    def sign_data_for_verifier(self, data: bytes) -> Dict[str, Any]:
        """
        Подпишите данные для стороннего проверяющего. Эти подписанные данные будут проверены сторонним проверяющим.
        Args:
            data: Сторонняя проверка предоставленных случайных данных

        Returns: Возвращает проверенные данные в формате словарной структуры:
        {
            'signature': b'1234567890', # данные байтового потока
            'hash_alg': hashes.SHA256() # хэши. Тип HashAlgorithm
        }
        """
        signature = rsa_sign.sign_raw_message(self.__awarded_pri_key, data, self.__default_hash_alg)
        return {SIGNATURE_KEY: signature, HASH_ALG_KEY: self.__default_hash_alg}

Несколько ключевых проблем при проверке сертификатов

После завершения выдачи сертификата ключом к применению сертификата является проверка личности сертификата и владельца сертификата.

В предыдущей логике мы выполнили следующие шаги:

Подготовка перед проверкой Сертификата
Подготовка перед проверкой Сертификата
  • центр сертификациипредставьте себя публичноизоткрытый ключ
  • Учреждения, получившие Сертификатпредставьте себя публичноизоткрытый ключ
  • центр сертификации Кодеялоорган, выдавший документпроблема Сертификат

Ключевой вопрос: как проверить подлинность сертификата?

Проверка легальности сертификата
Проверка легальности сертификата

Является ли сертификат законным или нет, является самым основным и ключевым звеном во всей проверке сертификата.

Все мы знаем, что при подписании используется закрытый ключ, а для проверки подписи используется открытый ключ.

Ранее мы ясно дали понять, что центр сертификацииизоткрытый Ключ является общедоступным и может быть получен кем угодно. Таким образом, любой верификатор может получить центр. сертификацииизоткрытый ключ,Вы можете проверить подпись самого Сертификата,Было проверено, выдан ли данный Сертификат законной организацией.

Ключевой вопрос: как проверить правильность хранения сертификата?

Сертификат и проверка законности держателя
Сертификат и проверка законности держателя

После проверки того, что сертификат выдан законно, у нас остается еще один момент для подтверждения, а именно, был ли этот сертификат выдан лицу, владеющему сертификатом.

Потому что сертификаты могут быть украдены. Хотя сам сертификат выдан на законных основаниях, он может оказаться у кого-то незаконно.

К счастью, наш сертификат содержит открытый ключ человека, выдавшего его, а также некоторую другую информацию.

Поэтому при проверке сертификата нам необходимо проанализировать содержимое сертификата и проверить некоторые поля по отдельности с информацией, предоставленной владельцем.

В этой статье логику разделения и разбора содержимого сертификата можно реализовать следующим образом:

Язык кода:python
кодКоличество запусков:0
копировать
def mock_parse_cert(cert: bytes, key_len: int = 256) -> Tuple[Dict[str, Any], bytes]:
    """
    Разобрать Сертификат, проанализировать значение подписи Сертификата и содержимое Сертификата.
    Args:
        key_len: Длина закрытого ключа, используемого для подписи. Эта длина определяет длину значения подписи.
        cert:Сертификатданные    Returns: Вернуть содержимое и значение цифровой подписи Сертификата.
    """
    if len(cert) < key_len:
        raise ValueError("invalid cert data, length invalid")
    split_index = len(cert) - key_len
    signature = cert[split_index: len(cert)]
    raw_data = cert[:split_index]
    try:
        cert_dict = mock_deserialize_cert_content(raw_data)
    except BaseException as e:
        print(e)
    else:
        return cert_dict, signature

Ключевой вопрос: как проверить законность владельца сертификата?

Проверка законности личности владельца
Проверка законности личности владельца

Сертификаты могут быть украдены, как и открытые ключи.

Таким образом, после доказательства того, что сам сертификат является законным и что сертификат действительно выдан для определенного открытого ключа, нам все равно необходимо проверить, владеет ли проверяемое в данный момент лицо закрытым ключом, соответствующим открытому ключу.

Макет реализации стороннего валидатора

Язык кода:python
кодКоличество запусков:0
копировать
class MockVerifier(object):
    """
    Имитировать сторонние валидаторы,Когда он получает Сертификат определенного субъекта,проверю это Сертификатлииз确是Зависит оторган, выдавший документпроблемаиз
    После проверки подлинности Сертификата он также попросит получателя Сертификата подписать данные, а затем сторонний проверяющий проверит подпись.
    """
    
    def __init__(self,
                 awarded_pub_key: RSAPublicKey,
                 awarded_sign_func: Callable[[bytes], Dict[str, Any]],
                 issuer_name: str,
                 issuer_pub_key: RSAPublicKey,
                 issuer_hash_alg: hashes.HashAlgorithm):
        # Собственный открытый сторонний валидатор ключ и закрытый ключ
        self.__verifier_pub_key, self.__verifier_pri_key = rsa_base.generate_rsa_keypair()
        # третья сторонапроверять ВОЗ在实例化час Уже зарегистрированорган, выдавший документиз:открытый ключ, имя, алгоритм хеширования
        self.__issuer_pub_key = issuer_pub_key
        self.__issuer_name = issuer_name
        self.__issuer_hash_alg = issuer_hash_alg
        # Сторонний верификатор зарегистрировал открытый верификатор при создании экземпляра. ключ со подписанными указателями на функции
        self.__awarded_pub_key = awarded_pub_key
        self.__awarded_sign_func = awarded_sign_func
    
    def __verify_cert_signature(self, verified_cert_data: bytes, signature: bytes) -> bool:
        """
        Убедитесь, что Сертификат соответствует подписи.
        Если он соответствует, это означает только то, что сам Сертификат верен, но лицо, владеющее Сертификатом, не обязательно является правдивым.
        Args:
            verified_cert_data: Обычные текстовые данные, подлежащие проверке
            signature: Значение подписи, которое необходимо проверить
        Returns: Проверка подписи прошла успешно?
        """
        return rsa_sign.verify_raw_message(pub_key = self.__issuer_pub_key,
                                           message = verified_cert_data,
                                           signature = signature,
                                           hash_alg = self.__issuer_hash_alg)
    
    def __verify_cert_content(self, cert_dict: Dict[str, Any]) -> bool:
        """
        Убедитесь, что содержание Сертификата соответствует ожиданиям.
        еслицентр сертификациии Сертификатоткрытый ключ одинаковы, это может означать только то, что Сертификат такой же, как этот открытый привязанный к ключу
        Однако, придерживаясь этого открытого Ключ человека не обязательно имеет закрытый ключ, поэтому ему все равно необходимо подписать с помощью закрытого ключа, а затем проверяющий проверяет подпись.
        Args:
            cert_dict: Исходное содержание сертификата
        Returns: Соответствует ли содержание Сертификата ожиданиям?
        """
        if cert_dict[ISSUER_NAME_KEY] != self.__issuer_name:
            """
            проверять Сертификатсерединаизорган, выдавший документимяипроверять ВОЗ持有изорган, выдавший Последовательно ли документирование?
            """
            print("issuer name not match:{} vs {}".format(cert_dict[ISSUER_NAME_KEY], self.__issuer_name))
            return False
        
        if cert_dict[AWARDED_PUB_KEY] != pub_key_base64_encode(self.__awarded_pub_key):
            """
            Проверьте эмитента в Сертификатеоткрытый ключ и открытый получены проверяющим ключ Это соответствует?
            """
            print("awarded pub key not match")
            return False
        return True
    
    def verify_cert(self, cert_data: bytes) -> bool:
        """
        Убедитесь, что Сертификат выдан эмитентом.
        Убедитесь, что Сертификат был выдан эмитентом лицу, предоставившему право.
        """
        try:
            cert_dict, signature = mock_parse_cert(cert_data, self.__issuer_pub_key.key_size // 8)
        except ValueError as e:
            # Если Сертификат не удается проанализировать, об ошибке будет сообщено напрямую.
            print(e)
            return False
        else:
            # Если Сертификат проанализирован успешно, подпись будет проверена.
            # cert_dict[HASH_ALG_KEY] = json.loads(cert_dict[HASH_ALG_KEY])
            verified_cert_data = json.dumps(cert_dict).encode(encoding = 'utf-8')
            if not self.__verify_cert_signature(verified_cert_data = verified_cert_data,
                                                signature = signature):
                return False
            if not self.__verify_cert_content(cert_dict = cert_dict):
                return False
            return True
    
    def verify_awarded(self) -> bool:
        """
        Returns: Верификатор генерирует случайное число, просит его подписать, а затем использует проверенный зарегистрированный открытый код. ключ Проверка        """
        random_data: bytes = bytes([random.randint(1, 255) for _ in range(64)])
        sign_dict = self.__awarded_sign_func(random_data)
        signature: bytes = sign_dict[SIGNATURE_KEY]
        hash_alg: hashes.HashAlgorithm = sign_dict[HASH_ALG_KEY]
        return rsa_sign.verify_raw_message(self.__awarded_pub_key, random_data, signature, hash_alg)

Процесс проверки

Язык кода:python
кодКоличество запусков:0
копировать
if __name__ == '__main__':
    issuer = MockIssuer('test_issuer', hashes.SHA256())
    awarded = MockAwarded('test_awarded')
    awarded.awarded_cert = issuer.mock_issue_cert('cert for {}'.format(awarded.name), awarded.pub_key)
    verifier = MockVerifier(awarded.pub_key,
                            awarded.sign_data_for_verifier,
                            issuer.issuer_name,
                            issuer.pub_key,
                            issuer.issuer_hash)
    if verifier.verify_cert(awarded.awarded_cert) and verifier.verify_awarded():
        print("certification verified success!!!")
Проверка прошла успешно
Проверка прошла успешно

Сертификат подобен удостоверению личности, подтверждающему «привязку открытого ключа к определенной личности».

Идентификация на основе асимметричного ключа проверки — это основа безопасности всех наших сетевых приложений.

boy illustration
Углубленный анализ переполнения памяти CUDA: OutOfMemoryError: CUDA не хватает памяти. Попыталась выделить 3,21 Ги Б (GPU 0; всего 8,00 Ги Б).
boy illustration
[Решено] ошибка установки conda. Среда решения: не удалось выполнить первоначальное зависание. Повторная попытка с помощью файла (графическое руководство).
boy illustration
Прочитайте нейросетевую модель Трансформера в одной статье
boy illustration
.ART Теплые зимние предложения уже открыты
boy illustration
Сравнительная таблица описания кодов ошибок Amap
boy illustration
Уведомление о последних правилах Points Mall в декабре 2022 года.
boy illustration
Даже новички могут быстро приступить к работе с легким сервером приложений.
boy illustration
Взгляд на RSAC 2024|Защита конфиденциальности в эпоху больших моделей
boy illustration
Вы используете ИИ каждый день и до сих пор не знаете, как ИИ дает обратную связь? Одна статья для понимания реализации в коде Python общих функций потерь генеративных моделей + анализ принципов расчета.
boy illustration
Используйте (внутренний) почтовый ящик для образовательных учреждений, чтобы использовать Microsoft Family Bucket (1T дискового пространства на одном диске и версию Office 365 для образовательных учреждений)
boy illustration
Руководство по началу работы с оперативным проектом (7) Практическое сочетание оперативного письма — оперативного письма на основе интеллектуальной системы вопросов и ответов службы поддержки клиентов
boy illustration
[docker] Версия сервера «Чтение 3» — создайте свою собственную программу чтения веб-текста
boy illustration
Обзор Cloud-init и этапы создания в рамках PVE
boy illustration
Корпоративные пользователи используют пакет регистрационных ресурсов для регистрации ICP для веб-сайта и активации оплаты WeChat H5 (с кодом платежного узла версии API V3)
boy illustration
Подробное объяснение таких показателей производительности с высоким уровнем параллелизма, как QPS, TPS, RT и пропускная способность.
boy illustration
Удачи в конкурсе Python Essay Challenge, станьте первым, кто испытает новую функцию сообщества [Запускать блоки кода онлайн] и выиграйте множество изысканных подарков!
boy illustration
[Техническая посадка травы] Кровавая рвота и отделка позволяют вам необычным образом ощипывать гусиные перья! Не распространяйте информацию! ! !
boy illustration
[Официальное ограниченное по времени мероприятие] Сейчас ноябрь, напишите и получите приз
boy illustration
Прочтите это в одной статье: Учебник для няни по созданию сервера Huanshou Parlu на базе CVM-сервера.
boy illustration
Cloud Native | Что такое CRD (настраиваемые определения ресурсов) в K8s?
boy illustration
Как использовать Cloudflare CDN для настройки узла (CF самостоятельно выбирает IP) Гонконг, Китай/Азия узел/сводка и рекомендации внутреннего высокоскоростного IP-сегмента
boy illustration
Дополнительные правила вознаграждения амбассадоров акции в марте 2023 г.
boy illustration
Можно ли открыть частный сервер Phantom Beast Palu одним щелчком мыши? Супер простой урок для начинающих! (Прилагается метод обновления сервера)
boy illustration
[Играйте с Phantom Beast Palu] Обновите игровой сервер Phantom Beast Pallu одним щелчком мыши
boy illustration
Maotouhu делится: последний доступный внутри страны адрес склада исходного образа Docker 2024 года (обновлено 1 декабря)
boy illustration
Кодирование Base64 в MultipartFile
boy illustration
5 точек расширения SpringBoot, супер практично!
boy illustration
Глубокое понимание сопоставления индексов Elasticsearch.
boy illustration
15 рекомендуемых платформ разработки с нулевым кодом корпоративного уровня. Всегда найдется та, которая вам понравится.
boy illustration
Аннотация EasyExcel позволяет экспортировать с сохранением двух десятичных знаков.