Страницы

Поиск по вопросам

Показаны сообщения с ярлыком криптография. Показать все сообщения
Показаны сообщения с ярлыком криптография. Показать все сообщения

среда, 4 марта 2020 г.

Как восстановить или заменить ключ от android приложения в google play?

#android #android_studio #google #google_play #криптография


Я потерял свой ключ jks и из-за этого не могу обновить приложение в google play. 

Можно ли его как-то заменить или восстановить?
    


Ответы

Ответ 1



Ничего сделать нельзя. Создавайте новый ключ и выкладывайте новое приложение с новым пакетом. Про приложение с утерянным ключом можно забыть навсегда. У Гугла вашего ключа нет и получить его никак нельзя

среда, 26 февраля 2020 г.

RSA криптография между Java и C# приложениями

#java #c_sharp #криптография #rsa


Почему при генерации RSA ключа длиной 512 бит в C# и в Java разная длина в байтах
публичного ключа?

Пример кода C#:

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(512);
XDocument xdocPub = XDocument.Parse(rsa.ToXmlString(false));
string publicKey = xdocPub.Element("RSAKeyValue").Element("Modulus").Value;

byte[] publicArray = Convert.FromBase64String(publicKey);
Console.WriteLine("Public Key Byte Array Length: " + publicArray.Length);
Console.WriteLine("Public Key Base64 Length: " + publicKey.Length);
Console.WriteLine("Public Key Text: " + publicKey);


Результат:

Public Key Byte Array Length: 64
Public Key Base64 Length: 88
Public Key Text: uELcIjgR6GpiayZ1wHruHOtO8dpg+xmg85VAvunWUEL+aifoyk9+CA/dez4UmuIwLEgRlpVoIIOD0e5i9v8lrQ==


Пример кода Java:

final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(new RSAKeyGenParameterSpec(512, RSAKeyGenParameterSpec.F4));
KeyPair pair = keyGen.genKeyPair();

final byte[] arrayPublic = ((RSAPublicKey) pair.getPublic()).getModulus().toByteArray();

System.out.println("Public Key [origin] lenght: " + arrayPublic.length);

String publicBase64 = Base64.getEncoder().encodeToString(arrayPublic);

System.out.println("Public Key [base64] lenght : " + publicBase64.length());
System.out.println("Public Key [base64]: " + publicBase64);


Результат:

Public Key [origin] lenght: 65
Public Key [base64] lenght : 88
Public Key [base64]: ANuun1/CnOmk2ghsydz4cKvPCd7q0YqqeyjzLqtKx7QHqv1tFjJYsXquYGcY8zkaPsPBrRlCAJov7+J88GaFDKc=


Заметил, что в байт массиве ключа сгенерированного в Java присутствует нулевой байт
в начале массива ключа.

Самое интересное, что если я отправляю ключ из C# приложения длиной 64 байта, то
в Java приложении получаю ошибку "exponent is larger than modulus" в следующем коде:

try
{
    final KeyFactory kfac = KeyFactory.getInstance("RSA");
    final BigInteger modulus = new BigInteger("здесь вставляется byte[] массив публичного
ключа от C#");
    final RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);

    RSAPublicKey publicKey = (RSAPublicKey) kfac.generatePublic(kspec1);
}
catch (GeneralSecurityException e)
{
    e.printStackTrace();
}


При этом, если я добавлю нулевой байт в начало ключа перед отправкой из C# приложения
в Java приложение, то со стороны Java приложения нет никаких проблем с инициализацией
криптографии и шифровкой отправляемых данных. Но в этом случае я не могу декодировать
входящие данные в C# приложении этим же экземпляром криптографии. Получаю ошибку "Плохие
данные".

Подскажите, что я делаю не так и почему длина ключей разная?


  UPD 1: добавлен тест в Java


PublicKey взят из первого примера сгенерированного в C#.

public class Test
{
    public static void main(String[] args)
    {
        final String base64key = "uELcIjgR6GpiayZ1wHruHOtO8dpg+xmg85VAvunWUEL+aifoyk9+CA/dez4UmuIwLEgRlpVoIIOD0e5i9v8lrQ==";

        try
        {
            byte[] publicKeyArray = Base64.getDecoder().decode(base64key);
            final KeyFactory kfac = KeyFactory.getInstance("RSA");
            final BigInteger modulus = new BigInteger(1, publicKeyArray);
            final RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);

            RSAPublicKey publicKey = (RSAPublicKey) kfac.generatePublic(kspec1);

            byte[] array = publicKey.getModulus().toByteArray();

            System.out.println("Public Key [Array] lenght : " + array.length);

            String publicBase64 = Base64.getEncoder().encodeToString(array);

            System.out.println("Public Key [base64] lenght : " + publicBase64.length());
            System.out.println("Public Key [base64]: " + publicBase64);
        }
        catch (GeneralSecurityException e)
        {
            e.printStackTrace();
        }
    }
}


В результате инициализации RSAPublicKey в Java Base64 ключ не соответствует входному.
Хотя по длине 65 байт. Но это работает только с signum = 1.

Public Key [Array] lenght : 65
Public Key [base64] lenght : 88
Public Key [base64]: ALhC3CI4EehqYmsmdcB67hzrTvHaYPsZoPOVQL7p1lBC/mon6MpPfggP3Xs+FJriMCxIEZaVaCCDg9HuYvb/Ja0=



  UPD 2: проблему C# генерации ключей RSA решила библиотека Bouncy
  Castle. У библиотеки есть
  исходники поэтому я взял только RSA часть и внедрил в свой проект.

    


Ответы

Ответ 1



Лишний байт BigInteger.toByteArray включает в результат знаковый бит числа: ... The array will contain the minimum number of bytes required to represent this BigInteger, including at least one sign bit, which is (ceil((this.bitLength() + 1)/8)) ... Т.ч. да, нулевой байт в начале можно отрезать по необходимости. Сделать это можно с помощью System.arraycopy: byte[] array = publicKey.getModulus().toByteArray(); //убираем лишний нолик final byte[] keyBytes = new byte[64]; System.arraycopy(array, 1, keyBytes, 0, 64); Посмотрите ответ @Maarten Bodewes на близкий вопрос на английском (How insert bits into block in java cryptography?), там приводится готовый метод для «нормализации» массива байтов с учетом ведущего нуля, также учитывается случай, когда массив короче 64 (вроде возникает только для приватных ключей). Плохие данные Конструктор BigInteger​(byte[] val) также ожидает получить знаковое представление числа и пытается считать у ключа знаковый бит. Попробуйте использовать конструктор, который принимает знаковый бит отдельно BigInteger​(int signum, byte\[\] magnitude): new BigInteger(1, /*байты ключа*/) Похожие вопросы на en.SO: how to build a rsa key with a modulus of 64 bytes in java How insert bits into block in java cryptography?

понедельник, 24 февраля 2020 г.

Что такое криптоядро? [закрыт]

#криптография #терминология


        
             
                
                    
                        
                            Закрыт. На этот вопрос невозможно дать объективный ответ.
Ответы на него в данный момент не принимаются.
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            Хотите улучшить этот вопрос? Переформулируйте вопрос,
чтобы на него можно было дать ответ, основанный на фактах и цитатах, отредактировав его.
                        
                        Закрыт 3 года назад.
                                                                                
           
                
        
Не могу найти, что такое "криптоядро"?
    


Ответы

Ответ 1



Некий "черный ящик", на вход которого подаются исходные данные (и ключ), а на выходе получаются зашифрованные данные (и наоборот). Используется, насколько я знаю, для сертификации криптосистем, чтобы не сертифицировать весь программный комплекс - можно купить готовое, сертифицированное КЯ и использовать его для шифрования данных.

пятница, 14 февраля 2020 г.

Дешифровка текста (частотный анализ)

#криптография #шифрование


Есть зашифрованный текст:
щ ьфьъзеэ кщвъязфхъзкд нэок амфопф адеа нзъч. аф-амътзъьс ф нъхсогъ зъ иупф хъщеъч.
нфь бэчхфмфзщгфбф афбмсякпщд х емэсм – аъмщфзэп амкекй, эзбъпкзэ йфнкпэ ипънзэд к щ
яэапэгэззуьк бпэяэьк, хкзкпэ щъид. йфядкз яэаъмщд х гэикзъеъ к амэгеквъщгк фееснэ зъ
хуйфнкп. яэимфщкп мэифес, фе ъну фегэяухэпщд, фщсзспщд, щаэп щ пкцэ.
– эмесм, еу иу афъп веф-зкисна? – сьфпдшыъ афамфщкпэ эзбъпкзэ. – к амъгмэек гсмкеа,
щгфпагф ьфтзф! нхъ аэвгк хущьфпкп! – фзэ хумхэпэ с зъбф кя аэпацъх щкбэмъес, яэесокпэ
х аъаъпазкцъ, мэщаэйзспэ оефму к фегмупэ фгзф х гэикзъеъ, хасщекх х гфьзэес щфпзцъ
к аъзкъ аекц.
бэчхфмфзщгкч сбмшьф афщьфемъп зэ бсхъмзэзегс, нфщеэп кя аэвгк нмсбсш щкбэмъес, амкгсмкп
к щзфхэ соъп х щъид.
– эмесм, хфяаьк щъид х мсгк, въме хфяаьк! х ифпазкцэй к ьфмбэй нэок зъе. еу тъ щэь
бфхфмкп, веф нэогэ иъбсзад. фзэ хъмзъещд, фидяэеъпазф хъмзъещд! – эзбъпкзэ физдпэ ьствкзс
щяэнк яэ апъвк к амктэпэща ыъгфч г ъбф яэеупгс.
х гэикзъе яэбпдзспэ бфмзквзэд к нфпфткпэ:
– г хэь кхэз эмгэнаъхкв.
бэчхфмфзщгкч хдпф гкхзсп.
хэмпэьфх хфоъп х гфьзэес ифнмфч афйфнгфч.
– зъ афзкьэш д хэоъ сафмзфъ зътъпэзкъ фимэекеащд х ькпкцкш, – щгэяэп фз. – ъщпк иу
нэмаш афйкекпк щ цъпаш хугсаэ, еф нэхзф иу афяхфзкпк к сщпфхкд хущеэхкпк. афмэ афнгпшвкеа
амэхффймэзкеъпазуъ фмбэзу.
– зъзэхктс ьъзефх. ьфд щпстиэ иъяфаэщзфщек нъпэъе хщъ хфяьфтзфъ.
– асщеа амфнфптэъе х ефь тъ нсйъ. хэщ зкгеф к зъ амфщке пшикеа ьъзефх, афнсьэчеъ
ф нфвъмк – афмэ афнгпшвэеа нфафпзкеъпазуъ мъяъмху, к д язэш въпфхъгэ, гфефмуч щьфтъе
зэь афьфва. щфикмэчеъща, иснс тнэеа хэщ х ьэокзъ. нфхфпазф нсмэгэ хэпдеа!
хэмпэьфх хуоъп яэ нхъма. бэчхфмфзщгкч мэянэхкп фгсмфг х аъаъпазкцъ к ьънпъззф афнздпщд.

Провел его частотный анализ в Excel-е, получил частоты букв. Стоит упомянуть, что
знаки препинания и пробелы не кодировались. Слева частоты в текущем тексте, справа
данные с Википедии


Прямая замена символов по приблизительным частотам ничего не дает, видимо, текст
слишком маленький, получается что-то непонятное. В то же время почти уверен, что Ф
-> О. Если кто-то сможет подсказать, то буду очень благодарен.
    


Ответы

Ответ 1



С момента исчезновения Даши прошло пять дней. По-прежнему о девушке не было вестей. Дом Гайворонского погрузился в траур – персонал притих, Ангелина ходила бледная и с заплаканными глазами, винила себя. Хозяин заперся в кабинете и практически оттуда не выходил. Забросил работу, от еды отказывался, осунулся, спал с лица. – Артур, ты бы поел что-нибудь? – умоляюще попросила Ангелина. – И прекрати курить, сколько можно! Две пачки высмолил! – Она вырвала у него из пальцев сигарету, затушила в пепельнице, распахнула шторы и открыла окно в кабинете, впустив в комнату солнце и пение птиц. Гайворонский угрюмо посмотрел на гувернантку, достал из пачки другую сигарету, прикурил и снова ушел в себя. – Артур, возьми себя в руки, черт возьми! В больницах и моргах Даши нет. Ты же сам говорил, что Дашка бегунья. Она вернется, обязательно вернется! – Ангелина обняла мужчину сзади за плечи и прижалась щекой к его затылку. В кабинет заглянула горничная и доложила: – К вам Иван Аркадьевич. Гайворонский вяло кивнул. Варламов вошел в комнату бодрой походкой. – Не понимаю я ваше упорное нежелание обратиться в милицию, – сказал он. – Если бы Дарью похитили с целью выкупа, то давно бы позвонили и условия выставили. Пора подключить правоохранительные органы. – Ненавижу ментов. Моя служба безопасности делает все возможное. – Пусть продолжает в том же духе. Вас никто и не просит любить ментов, подумайте о дочери – пора подключать дополнительные резервы, и я знаю человека, который сможет нам помочь. Собирайтесь, буду ждать вас в машине. Довольно дурака валять! Варламов вышел за дверь. Гайворонский раздавил окурок в пепельнице и медленно поднялся. Все расшифровывается, как и писали в комментариях: 1) Проводим частотный анализ, находим самую часто встречающуюся букву 2) Заменяем эту букву на "О" 3) Ищем слова: "он, она, они, кто, что, то" и находим остальные буквы.

четверг, 13 февраля 2020 г.

Доказательство с нулевым разглашением

#математика #криптография


Классическим примером протокола доказательства с нулевым разглашением является протокол
доказательства знания пароля к двери внутри круговой пещеры. Пусть Алиса (Alice) знает
этот пароль и хочет доказать его знание Бобу (Bob) без разглашения самого пароля. Используется
следующий протокол:
Алиса заходит в пещеру и подходит к двери с произвольной стороны так чтобы Боб не
знал с какой стороны находится Алиса.
Боб заходит в пещеру и просит выйти Алису с какой либо из сторон пещеры (слева или
справа).
Алиса зная пароль к двери всегда сможет выполнить пожелание Боба, появившись с любой
стороны.
После каждой итерации уверенность Боба в том что Алиса знает секрет увеличивается
вдвое. Таким образом после $k$ успешно выполненных операций вероятность того что Алиса
на самом деле обманывает Боба равна $1/2^k$.
Вопрос: почему важно, чтобы Боб не знал с какой стороны входит Алиса? Ведь это знание
не связано с секретом, а зная, например, что Алиса входит справа, Боб может попросить
ее выйти слева и точно убедиться в том, что у нее есть ключ.     


Ответы

Ответ 1



В оригинале немного не так. В начале квеста оба находятся в точке A. Далее Алиса проходит внутрь пещеры и поворачивает либо налево, либо направо, так что Боб не знает куда она повернула (выступ между A и B скрывает ее движение). Далее Боб проходит к точке B и кричит Алисе выйди с левой или с правой стороны Алиса по необходимости открывает дверь паролем и выходит либо слева либо справа. Суть в том, что Боб не знает с какой стороны находится Алиса и наугад кричит выйди слева или справа. То есть вероятность того, что Алиса применила пароль для открытия двери составляет как раз 50%. После N итераций уверенность Боба растет как (1 - 1/2^N)

воскресенье, 9 февраля 2020 г.

Где происходит шифрование данных, и где находится ключ tls/ssl?

#безопасность #ssl #https #криптография #tls


Интересует вопрос безопасности https соединения.


Не могу понять, где именно происходит шифрование данных, когда запрашивается какой-нибудь
сайт по https? - В браузере, в операционной системе клиента или вообще на сервере? 
Каким образом передается ключ браузеру, чтобы расшифровать сообщение?  Просто в ответном
сообщении или как-то еще, его же могут перехватить? 
Знает ли браузер алгоритм шифрования? - это открытая информация? Если так, то почему
не используются закрытые алгоритмы (о которых никто не знает), или постоянно меняющиеся,
чтобы злоумышленнику было сложнее разгадать? 

    


Ответы

Ответ 1



Шифрование происходит с обеих сторон. Ведь если шифровать будет только одна сторона (например только сервер), значит трафик от другой стороны (от клиента) будет не зашифрован. Его можно будет подслушать или даже изменить. Формально никто не передает никому ключ. В протоколе TLS клиент и сервер должны сгенерировать общий секрет (shared secret), набор из 48 байт. Потом клиент и сервер на основании общего секрета вычисляют ключи: ключ шифрования клиента и ключ шифрования сервера. Процедура вычисления ключей из общего секрета стандартная, и задана в описании протокола TLS. Сервер и клиент знают 2 ключа шифрования, одним шифруют, вторым дешифруют. А теперь самое интересное - как клиент и сервер вычисляют общий секрет. Это зависит от выбранного набора шифров: TLS_RSA_WITH_: В данном случае клиент сам создает общий секрет генерируя 48 случайных байт. Затем он шифрует их при помощи публичного RSA ключа, который находится в сертификате сервера. Сервер получает зашифрованные данные, и расшифровывает их при помощи приватного RSA ключа. Данная схема используется редко. TLS_DHE_RSA_/TLS_ECDHE_RSA_/TLS_ECDHE_ECDSA_: Здесь используется криптографическая схема Диффи-Хеллмана (DHE) или ее версия на эллиптических кривих (ECDHE). Суть схемы такая: сервер и клиент генерируют случайные большие числа (приватные ключи), вычисляют на их основе другие числа (публичные ключи), и пересылают друг другу. Имея свой приватный ключ и публичный ключ другой стороны, они вычисляют общий секрет. Третья сторона, которая прослушивает канал, видит только 2 публичных ключа, и она не может вычислить общий секрет. После этого все данные, которыми обменивались клиент и сервер для получение этого ключа подписываются сертификатом сервера (RSA или ECDSA подписи). Если клиент доверяет сертификату сервера, он проверяет эту подпись, и если она правильная, начинается уже обмен данными. Это наиболее часто используемая схема. Есть еще несколько схем, но они используются очень редко или не используются вообще. Про перехват. Как я выше описал, перехватывать сообщения здесь бесполезно, так как в первом случае его может расшифровать только сервер, а во втором используется хитрая криптографическая схема. Алгоритмы шифрования знает и сервер, и клиент. Ведь если клиент не знает, какой алгоритм шифрования, как он будет шифровать данные для отправки? В современной криптографии никто не использует закрытые алгоритмы. Открытые алгоритмы постоянно изучаются лучшими криптографами мира, ищутся уязвимости, и предлагаются решения для их обхода. В TLS мы условно можем сказать, что алгоритмы меняются, так как каждый раз генерируются другие ключи шифрования. А потом, если вы хотите использовать закрытый алгоритм, например для просмотра веб-страницы, каким образом этот алгоритм может быть закрытый, если ваш компьютер/устройство производит шифрование/дешифрование? Я упустил/упростил некоторые детали, что бы описать только основные идеи.

Ответ 2



Работает это так: У сервера и у клиента имеются т.н. сертификаты. Грубо говоря - сертификаты это набор: публичный ключ (PubKey)+секретный ключ (PrivKey) В момент установления соединения происходит т.н. handshake-рукопожатие, опять же грубо говоря в этот момент клиент и сервер обмениваются информацией какие у них сертификаты и какие алгоритмы шифрования они поддерживают и могут ли они доверять сертификатам противной стороны. Handshake проходит успешно, если клиент и сервер имеют корневые сертификаты, которые доверяют сертификатам респондентов. Если handshake проходит успешно они обмениваются публичными ключами и на их основе вычисляют сессионный ключ, который вычисляется как sessionKey=sharedKey(PubKeyClient, PrivKeyServer)==sharedKey(PubKeyServer, PrivKeyClient) - здесь фигурирует функция sharedKey() - это некий мат.алгоритм, который вычисляет сессионный ключ на основе публичного ключа респондента и секретного ключа получателя, причем он тождественно равен сессионному ключу полученному в результате вычисления на основе публичного ключа получателя и приватного ключа респондента - собственно на этом вся эта математика и строится - иначе ничего не взлетит После этапа 3. обе партии имеют одинаковый ключ, который используется для симметричного шифрования выбранным алгоритмом, который устанавливается во время handshake Далее каждая сторона шифрует свои запросы сессионным ключом, принимающая сторона дешифрует его и вуаля. В реале все намного сложнее - можете почитать хотя бы Википедии Update его же могут перехватить Посколько сервер и клиент обмениваются только публичными ключами, то атакующий может перехватить только публичные ключи, знание публичного ключа без знания секретного ключа бесполезно. Знает ли браузер алгоритм шифрования? - это открытая информация? Да, это открытая информация. В криптографии защита на основе незнания алгоритма шифрования не считается надежной защитой. Скорее даже наоборот, знание алгоритма - это наоборот способ защиты - как некая гарантия надежности алгоритма. Существует определенная процедура как бы сертификации алгоритмов, которая и подтверждает его надежность - то есть устойчивость к разнообразным атакам. В случае SSL/TLS для обмена ключами используются RSA и DH, а для обмена в пределах сессии используются симметричные алгоритмы IDEA и AES.

суббота, 1 февраля 2020 г.

Протокол Диффи-Хеллмана не работает при некоторых значениях

#cpp #криптография


Почему при 


  p = 23, g = 5, a = 6, b = 15


ba равен ab, но при


  p = 23, g = 5, a = 116, b = 15


уже нет?

Какие типы, числа и диапазоны чисел должны быть для этого протокола?

#include  
#include  

int main() {
  unsigned long long int p = 23;
  unsigned long long int g = 5;
  unsigned long long int a = 6;
  unsigned long long int b = 15;
  unsigned long long int A = std::fmod(pow(g, a), p);
  unsigned long long int B = std::fmod(pow(g, b), p);
  unsigned long long int ba = std::fmod(pow(B, a), p);
  unsigned long long int ab = std::fmod(pow(A, b), p);
  return 1;
} 

    


Ответы

Ответ 1



Во-первых, в криптографических алгоритмах нужны точные целочисленные вычисления. Вы же используете приближенные вычисления с плавающей точкой. Ни о каком точном вычислении 5116 в вашем варианте речи идти не будет - это слишком большое число. Во-вторых, ваша последовательность действий описывает процесс формирования общего ключа после выбора секретных ключей a и b. В протоколе Диффи-Хеллмана секретные ключи a и b выбираются из мультипликативной группы по модулю p, то есть в вашем примере для p = 23 это должны быть значения в диапазоне [1, 22]. При чем здесь ваше 116, откуда вы его взяли и чего от него ожидали - не ясно. (Как правильно заметил @Zergatul в комментариях, при p = 23 протокол будет правильно работать и для a = 116. Но нет никакого смысла в том, чтобы выбирать число за пределами диапазона [1, 22]. В вашем случае это лишь привело к потере точности.)

Ответ 2



Никто так не считает остаток от деления после возведения в степень. Самая простая оптимизация выглядит так: int modpow(int a, int b, int m) // a^b % m { int result = 1; // 31 - для упрощения кода, на самом деле нужно брать длину числа в битах for (int i = 31; i >= 0; i--) { result = result * result % m; if (b & (1 << i)) result = result * a % m; } return result; } В реальных библиотеках для длинных чисел и криптографии дополнительно используют алгоритм Монтгомери.

пятница, 24 января 2020 г.

Атака на многоалфавитный шифр простой замены

#криптография #дискретная_математика #криптоаналитика


Как расшифровать текст, зашифрованный с использованием многоалфавитного шифра простой
замены? Вкратце о том что это за шифр: ключ состоит из n алфавитов, каждая i-ая буква
открытого текста заменяется по (i-1)%keyLenght + 1 алфавиту. Шифр по сути представляет
из себя обобщенный шифр Виженера.
Длину ключа я определил. А вот как теперь подобрать ключ я не знаю.
    


Ответы

Ответ 1



Я пока не нашел полного решения, но нащупал некое направление, по которому можно пробовать идти. И так, с начала определяем длину ключа например по методу, предложенному автором вопроса (@Asem) в комментариях, т.е. методом индекса совпадений После этого определяем частоты букв в каждом словаре шифрования отдельно. Для предложенного примера шифротекста я получил следующую картину: 0: t=>14.268, h=>9.348, d=>8.364, u=>8.364, l=>8.364, s=>7.38, j=>6.396, a=>4.92, z=>4.428, x=>3.936, e=>3.444, r=>2.952, k=>2.952, w=>2.46, y=>2.46, m=>2.46, c=>2.46, n=>1.968, p=>1.476, f=>0.492, i=>0.492, b=>0.492, o=>0.492, 1: s=>13.776, a=>8.364, n=>8.364, j=>7.38, g=>7.38, t=>7.38, y=>6.888, h=>6.396, p=>4.92, k=>4.428, v=>4.428, e=>3.444, q=>3.444, i=>2.952, c=>2.46, w=>1.968, f=>1.476, m=>1.476, l=>0.984, z=>0.984, o=>0.984, 2: t=>12.3, n=>10.332, c=>9.84, w=>9.348, q=>7.872, k=>6.396, y=>5.904, a=>4.428, h=>4.428, v=>4.428, s=>4.428, f=>3.936, r=>2.952, l=>2.952, x=>2.46, g=>1.968, m=>1.968, j=>1.476, b=>0.984, d=>0.492, i=>0.492, p=>0.492, 3: t=>9.84, m=>9.348, g=>8.856, p=>8.364, q=>8.364, i=>7.872, r=>6.396, k=>6.396, x=>4.428, s=>4.428, f=>3.444, z=>3.444, j=>2.952, n=>2.952, w=>2.46, e=>2.46, c=>2.46, d=>1.968, l=>1.476, u=>0.984, v=>0.492, o=>0.492, Далее нам надо как то сопоставить эти частоты с частотами английского текста. К сожалению к реальных текстах небольшого размера частоты могут сильно отличаться. Я посчитал минимальные и максимальные частоты на большом наборе блоков текста по 814 байт (размер шифротекста) и получил следующую картину: Минимум Максимум Минимум 4 Максимум 4 A: 4.545 11.916 A: 0.982 16.216 B: 0.368 4.176 B: 0.491 5.405 C: 0.614 5.651 C: 0.491 8.353 D: 1.474 7.739 D: 0.491 11.302 E: 6.756 16.461 E: 5.405 21.621 F: 0.368 4.545 F: 0.491 6.879 G: 0.491 4.668 G: 0.491 5.896 H: 1.719 10.319 H: 0.491 13.267 I: 3.316 9.828 I: 1.474 13.759 J: 0.122 1.228 J: 0.491 1.965 K: 0.122 3.439 K: 0.491 4.422 L: 1.105 7.739 L: 0.491 9.828 M: 0.737 5.159 M: 0.491 8.353 N: 3.808 10.81 N: 1.965 12.285 O: 4.299 12.407 O: 2.457 15.724 P: 0.122 5.282 P: 0.491 5.405 Q: 0.122 1.474 Q: 0.491 1.474 R: 2.702 8.845 R: 1.474 12.776 S: 3.194 10.073 S: 0.982 12.285 T: 4.299 13.022 T: 0.982 16.216 U: 0.737 6.019 U: 0.491 8.845 V: 0.122 3.316 V: 0.491 3.931 W: 0.491 5.282 W: 0.491 7.371 X: 0.122 1.105 X: 0.491 2.457 Y: 0.245 6.388 Y: 0.491 7.371 Z: 0.122 1.597 Z: 0.491 1.965 В колонках "Минимум/Максимум 4" я посчитал частоты, если брать каждую 4ю букву блока. К сожалению они имеют еще большие отклонения от реальности и в некоторых случаях возможно придется ориентироваться на них. Далее подстановкой самых частых по нашему разумению букв замечаем места в шифротексте, где близко расположено несколько букв с повторами. А так же повторяющиеся комбинации символов. Для выбранного участка готовим регулярное выражение, которое учитывает во первых повтор букв, во вторых на месте букв перечисляем класс символов из всех букв, которые могли бы подойти по частоте. Например буква t из третьего (последнего, при нумерации с 0) словаря, с частотой 9.84 может быть представлена [ETAONIHS]. Таким образом для участка шифротекста tzzstmtgtmt (первая буква в позиции 2го словаря) у меня получилась следующая регулярка (в ней нарочно оставлены маленькие буквы шифротекста, что бы можно было быстро увидеть правильность выбора участка). Большими буквами обозначаем ожидаемые символы в открытом тексте, так потом удобнее для замены. (?[tETAO]) [zONIHSRDLUWCMGFYPBK] (?[zTAONIHSRDLUWCMGFYPBK]) (?[sET]) \g{t2} (?[mETAONIHS]) (?[tE]) [gTAONIHSRDL] \g{t2} \g{m3} \g{t0} Имена групп захвата и соответствующие ссылки идут по букве шифротекста и номеру словаря. К сожалению регулярка упрощенная и не контролирует, что одна буква алфавита в пределах одного словаря, соответствует строго одной букве словаря. Этот контроль я реализовывал позже в скрипте. Прогоняем полученную регулярку по реальному тексту большого объема (я использовал 2Mb склеенных в один текст только из букв английских рассказов) и находим попадающие под нее места: TBUTTHENTHE THATTHEOTHE TIMETHENTHE TOGETHERTHE TSATTHEOTHE TWHETHERTHE Собственно когда я писал эту регулярку я как раз хотел понять, на сколько жизнеспособна моя идея расшифровки tmt как THE. Просто эта комбинация с одной стороны часто встречалась, с другой, в данном месте два раза THE стоят слишком близко и мне было интересно на сколько это реально. Далее по шифротексту есть еще одно место с нагромождением тех же букв, его я проверял скрипте по другой регулярке с подстановкой букв найденных первой. В итоге для второй точки нашлись предположения только для случая если в первом случае была комбинация TWHETHERTHE. Если бы набор текстов был больше, возможно нашлось бы что то еще. Вот результат подстановок реальных примеров из текстов. Видно, что начинают вырисовываться другие участки текста. Аналитик с очень хорошим знанием английского языка (к которым я явно не отношусь), вполне мог бы их заполнить. На самом деле я боле менее уверен только в тех THE и еще в нескольких буквах, остальное может варироваться и надо проверять каждый вариант просматривая поведение новых букв в нескольких точках шафротекста.

Почему AES расшифровывается именно таким образом?

#java #криптография #шифрование #aes


Использую шифрование AES с разными режимами (далее в примере режим "CBC"). Зашифровываю
следующий файл с текстом.

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

При дешифровке получается следующий текст.


Собственно вопрос: почему неправильно расшифровывается именно этот отрезок текста,
ведь как я понял из документации AES (и как мне объяснял преподаватель) неправильно
расшифровываться должен весь текст, содержащийся после внесенной ошибки? Как сделать,
чтобы работало именно так?

Код класса (в "mode" передаю режим):

public class AesCipher {

    private static final String INIT_VECTOR = "ItIsOurBigSecret";

    // зашифрование
    static byte[] encrypt(byte[] secretKey, byte[] plainText, String mode) {

        try {
            if (!isKeyLengthValid(secretKey)) {
                throw new Exception("Длина ключа должна быть 128, 192 или 256 бит!");
            }

            IvParameterSpec ivParameterSpec = new IvParameterSpec(INIT_VECTOR.getBytes());
            SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "AES");

            Cipher cipher = Cipher.getInstance("AES/" + mode + "/PKCS5Padding");
            if (mode.equals("ECB"))
                cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            else
                cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);

            return cipher.doFinal(plainText);
        } catch (Throwable cause) {
            System.out.print(cause.getMessage());
        }

        return null;
    }


    // дешифрование
    static byte[] decrypt(byte[] secretKey, byte[] cipherText, String mode) {

        try {
            if (!isKeyLengthValid(secretKey)) {
                throw new Exception("Длина ключа должна быть 128, 192 или 256 бит!");
            }

            IvParameterSpec ivParameterSpec = new IvParameterSpec(INIT_VECTOR.getBytes());
            SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "AES");

            Cipher cipher = Cipher.getInstance("AES/" + mode + "/PKCS5Padding");
            if (mode.equals("ECB"))
                cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
            else
                cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);

            return cipher.doFinal(cipherText);
        } catch (Throwable cause) {
            System.out.print(cause.getMessage());
            Controller.ShowMessage(cause.getMessage());
        }

        return null;
    }


    // проверка длины ключа
    private static boolean isKeyLengthValid(byte[] key) {
        return key.length == 16 || key.length == 24 || key.length == 32;
    }

    


Ответы

Ответ 1



Все правильно. AES обрабатывает данные блоками. В режиме CBC для расшифровки одного блока используется 2 блока шифротекста. Выглядит это приблизительно так: расшифрованый_блок = aes_decrypt(зашифрованый_блок) xor (предыдущий_зашифр_блок) По-этому ошибка в 1 байте шифротекста приведет к неправильной расшифровке только одного блока. Плюс один байт в другом блоке (из-за операции xor). Если вам нужно, что бы ломались все блоки после ошибки, можете использовать другой режим шифрования, например PCBC обладает таким свойством.

среда, 22 января 2020 г.

Генерация обратного элемента в поле Галуа

#python #алгоритм #криптография


Имеем поле Галуа GF(2409), и неприводимый полином над полем :

f(x) = x409 + x15 + x6 + x + 1
//Коэффициенты при степенях только 0 или 1

Пускай у меня есть какой-то полином a(x) в этом поле.
Вопрос: Как мне найти обратный к "а(x)",относительно f(x) элемент , используя именно
алгоритм Евклида, а не возведение элемента "а(x)" в степень 2409-2.

//Алгоритм поиска обратного элемента пишу на Python используя полиномиальный базис,
а на нём возведение в степень работает слишком долго
//Проблемы возникают при введении операции деления на полиномах
    


Ответы

Ответ 1



2409-2 - это число, содержащее 409 установленных битов и один сброшенный (предпоследний). Это значит, что для быстрого возведения в эту степень элемента a(x) требуется 408 операций возведения в квадрат и 408 операций умножения над полиномами 409-го порядка по модулю f(x). Для умножения полиномов нужно 409 * 410 / 2 умножений, порядок произведения будет 818. Для приведения его к модулю f(x) по методу деления "уголком" требуется 409*4 вычитаний, что практически не влияет на производительность. Итого: 2 * 408 * 409 * 410 / 2 = 68 417 520 умножений. Реальная проблема - в разрядности данных, поскольку при каждом возведении полинома в квадрат сумма его коэффициентов (равная значению полинома при x = 1) также возводится в квадрат, что увеличивает исходную разрядность на 409 log2 a(1) бит и в итоге "утяжеляет" алгоритм, как минимум, на 2 порядка. Остальное - детали реализации.

КриптоПро.NET SDK работа с ЭЦП

#c_sharp #net #криптография


Как подписать и зашифровать файл используя библиотеку КриптоПро.NET SDK имея USB токен?
Алг. подписи ГОСТ 34.10-2001(512 bits)
Алг. хэша    ГОСТ 34-11-94

Я имею файл в формате p7s.p7m. Его содержимое разделено тегами 

----- BEGIN PKCS7 ENCRYPTED ----- --- END PKCS7 ENCRYPTED ----- 

    


Ответы

Ответ 1



Пример подписи для Алгоритма ГОСТ 34-10. Источник namespace Samples.MySamples class Gost3410CSPSample { [STAThread] static void Main(string[] args) { try { //Создаем новый Гост-34.10 CSP. Gost3410CryptoServiceProvider Gost = new Gost3410CryptoServiceProvider(); //32-х битное значение хэш для подписи. byte[] HashValue = { 59, 4, 248, 102, 77, 97, 142, 201, 210, 12, 224, 93, 25, 41, 100, 197, 213, 134,130, 135, 0, 0, 0, 0, 0,0,0,0,0,0,0,0}; //Подписываем значение хэш. byte[] SignedHashValue = GostSignHash(HashValue, Gost, "Gost3411"); //Проверяем правильность подписи и выводим результат. bool b = GostVerifyHash(HashValue, SignedHashValue, Gost, "Gost3411"); if (b) { Console.WriteLine("Подпись вычислена верно."); } else { Console.WriteLine("Подпись вычислена неверно."); } } catch (ArgumentNullException e) { Console.WriteLine(e.Message); } } static byte[] GostSignHash(byte[] HashToSign, Gost3410CryptoServiceProvider key, string HashAlg) { try { //Создаем форматтер подписи с закрытым ключом из переданного //функции криптопровайдера. GostSignatureFormatter Formatter = new GostSignatureFormatter((Gost3410CryptoServiceProvider)key); //Устанавливаем хэш-алгоритм. Formatter.SetHashAlgorithm(HashAlg); //Создаем подпись для HashValue и возвращаем ее. return Formatter.CreateSignature(HashToSign); } catch (CryptographicException e) { Console.WriteLine(e.Message); return null; } } static bool GostVerifyHash(byte[] HashValue, byte[] SignedHashValue, AsymmetricAlgorithm key, string HashAlg) { try { //Создаем форматтер подписи с закрытым ключом из переданного //функции криптопровайдера. GostSignatureDeformatter Deformatter = new GostSignatureDeformatter(key); //Устанавливаем хэш-алгоритм. Deformatter.SetHashAlgorithm(HashAlg); //Проверяем подпись и возвращаем результат. return Deformatter.VerifySignature(HashValue, SignedHashValue); } catch (CryptographicException e) { Console.WriteLine(e.Message); return false; } } } Задать контейнер можно таким способом: CspParameters cspParameters = new CspParameters(75); cspParameters.KeyContainerName = "MCPUEpOv";

Ответ 2



Я решил идти по пути наименьшего сопротивления и использовать консольную утилиту Cyptcp компании КриптоПро. Для работы утилиты нужен криптопровайдер КриптоПро CSP. КриптоПро CSP на одну машине стоит около 2 000 руб, а Cyptcp около 700 руб. Cyptcp и АРМ КриптоПро совместимы между собой. Формирую команды: /// /// Формирование команд для утилиты Cyptcp /// public static class Command { /// /// Команда на запуск дешифрования /// /// Имя сертификата /// Путь к защифрованному файлу /// Путь к дешифрованному файлу /// public static string Decript(string nameCertificate, string pathEncryptedFile, string pathSave) { return "-decr -dn \"" + nameCertificate + "\" " +"\""+ pathEncryptedFile + "\" \"" + pathSave+"\""; } /// /// Проверка подписи. Сертификат выбирается из хранилища сертификатов /// /// Путь к подписанному файлу /// Путь к очищенному от подписи файлу /// public static string VerificationSignature(string pathSignFile, string pathFile) { return "-verify -verall " + "\"" + pathSignFile + "\" \"" + pathFile + "\""; } public static string Sign(string nameCertificate, string pathFile, string pathSignedFile) { return "-sign -dn \"" + nameCertificate + "\" " + "\"" + pathFile + "\" \"" + pathSignedFile + "\""; } public static string Encrypt(string nameRecipientCertificate, string pathSigFile, string pathSave) { return "-encr -dn \"" + nameRecipientCertificate + "\" " + "\"" + pathSigFile + "\" \"" + pathSave + "\""; } } Запуск утилиты на выполнение команды: private void RunCommand(string command, string pathApplication) { using (Process process = new Process()) { //Имя файла. process.StartInfo.FileName = pathApplication; //Директория. process.StartInfo.WorkingDirectory = Path.GetDirectoryName(pathApplication); //Команда. process.StartInfo.Arguments = command; //Не показывать окно приложения. process.StartInfo.CreateNoWindow = true; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardInput = true; process.StartInfo.StandardOutputEncoding = Encoding.Default; process.Start(); //Ответ на диалог выбора сертификата process.StandardInput.WriteLine("y"); } }

суббота, 11 января 2020 г.

Регистрация пользователя по ЭЦП

#android #криптография #аутентификация #цифровая_подпись


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

Пока исследуем первый вариант решения задачи: у каждого предприятия есть свои ЭЦП
- для сдачи отчетностей, для ДБО и т.д. Они уникальны и никому не передаются (по понятным
причинам). Мысль такая: раз пользователь идентифицирует себя представителем предприятия
путем ввода ключа этого предприятия, то он на это уполномочен (если не считать криминальных
ситуаций воровства ключей злоумышлинниками).

Вопрос: возможно ли как-нибудь использовать эти имеющиеся у предприятия сертификаты
ЭЦП для идентификации пользователя в качестве представителя этого предприятия при регистрации
в базе данных через мобильное приложение?? 

Понятно, что не путем вставки токен-флешки в несуществующий USB-порт устройства;
может быть вводом какой-то информации?

Понимаю, что специалисту по ЭЦП вопрос может показаться смешным и абсурдным, но я
обязан исследовать все варианты. Пожалуйста, не скупитесь на свои предложения.
    


Ответы

Ответ 1



Ничего смешного и абсурдного в этом вопросе нет. Российский стандарт ЭЦП "слегка" отличается от западных стандартов digital signature. Стандарт описан в ГОСТ Р 34.10-2012 По идее все российские ЭЦП должны соответствовать указанному стандарту, но, как говорится - в жизни бывает всякое. ЭЦП на уровне данных, это по сути 2 набора данных: публичный ключ и приватный ключ. Приватный ключ никому не передается и хранится у обладателя. Публичный ключ рассылается всем желающим, то есть в рамках вашего сценария - предприятие высылает вам свой публичный ключ, чтобы получить доступ к вашему бесценному приложению. Теперь внимание, вы должны понять, что публичный ключ принадлежит тому кто вам его выдал. Для этого существуют сертификаты публичных ключей. Вся фишка именно в этом. Если бы дело касалось западных digital signature, то в любом легальном Android устройстве хранятся корневые сертификаты крупнейших удостоверяющих центров (типа VeriSign, Thawte и проч.), с помощью которых легко можно понять кому принадлежит полученный ЭЦП. Российские корневые (квалифицированные) сертификаты надо получать в соответствующем удостоверяющем центре, в котором получен ЭЦП. Этих центров у нас прямо скажем много... При этом большинство из них не идентифицируют друг друга. На всякий случай корневой сертификат налоговой здесь, а Сбербанковский здесь - в общем понятно надеюсь. Ближе к программированию. Упомянутый выше ГОСТ реализован в Bouncy Castle - для тех кто в танке - это один самых известных публичных API реализующих почти все мыслимые и немыслимые криптографические алгоритмы. И что особенно приятно, Bouncy Castle реализует алгоритмы в качестве стандартного Java Cryptography Extension провайдера. Для Андроида есть специальный порт Bouncy Castle - называется Spongy Castle Проверка юзера должна сводиться к: Получить корневой сертификат удостоверяющего центра Получить сертификат публичного ключа юзера Сверить его на валидность с корневым сертификатом удостоверяющего центра Все это можно сделать программно (хотя и не просто...) Далее уж гуглите сами на тему validate+certificate+java

Использование RSA для “Ментального покера”

#криптография #rsa


В книге "Прикладная криптография" Шнайера, в разделе посвященном "Ментальному покеру"
предлагается использовать для шифрования RSA с идентичными модулями. В этом случае
процедура становится коммутативной, это в данном случае важно:


  Т.е. для расшифровки карт последовательно зашифрованных двумя ключами, можно применять
эти ключи в произвольном порядке. 


А я вот что-то не могу сообразить - как у двух игроков могут быть ключи с идентичными
модулями? Если модуль в RSA это произведение двух простых чисел - то существует единственный
вариант его разложения на эти числа. И идентичными модули могут быть только если у
обоих одинаковые пары ключей - а это лишает всю процедуру шифрования смысла.

Или тут имеется в виду что-то другое?

    


Ответы

Ответ 1



И идентичными модули могут быть только если у обоих одинаковые пары ключей - а это лишает всю процедуру шифрования смысла. Здесь вы неправы, для одного модуля существует очень много разных пар ключей. Обратите внимание на процедуру генерации ключей RSA: публичная экспонента e выбирается случайным образом (на практике всегда берут 65537). Мы можем выбрать любое e, и получим уникальную пару ключей. В описанной в книге схеме не совсем тот RSA, который привычно видеть в других криптосхемах. Стороны генерируют разные ключи для одного модуля, и обе стороны знают его разложение на простые числа. Факторизация дает возможность вычислить приватный ключ с публичного ключа, но в приведенной схеме они не знают даже публичные ключи друг друга. Только на шаге 7 они раскрывают свои ключи, что бы убедится в отсутствии мошенничества.

пятница, 10 января 2020 г.

Длина соли и длина выходной стройки алгоритма blowfish

#blowfish #php #криптография #шифрование


Здравствуйте. В мануале php сказано, что Blowfish-шифрование использует соль след.
формата: "$2a$", весовой параметр из двух цифр, "$" и 22 цифры из алфавита "./0-9A-Za-z"
. Но на деле вместо 22 у меня почему-то используется только 21 символ.
$var = "1111111111111111111112";//22-й символ помечен двойкой

echo strlen($var);//выводит 22

echo crypt("12345", "$2a$11$".$var);// выводит $2a$11$111111111111111111111uDWduZDJM79lPV0duPxKCR2XEmS5ly2q

Как видно 22-й символ обрезался и не попал в соль.
Вопрос1: Как объяснить выше описанное поведение?
Вопрос2: У меня на php длина выходной строки (хэша с солью) всегда равна 60 байт
(ну или 60 символов латинского алфавита). Это общий стандарт? стандарт php? Если да,
то где описан?
Спасибо.    


Ответы

Ответ 1



Соль задается из алфавита "./0-9A-Za-z" (64 символа), т.е. каждый символ представляет из себя 6 бит. Это напоминает кодировку BASE64. Вы задаете 22 символа это 22*6 = 132 бита. Для Blowfish соль используется 128 бит из-за этого последние 4 бита не используется. Когда выводится результат, то 128 бит также дополняются 4 нулевыми битами, т.е. от последнего символа остается только 2 старших бита. В вашем примере: 2 (111000) -> u(110000), т.е. последний символ Вы можете задавать любой с точность до 2-х старших битов и это не будет влиять на хэш.

четверг, 9 января 2020 г.

Хеши целых чисел в Python

#python #криптография #хеширование #структуры_данных


Добрый день.

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

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

В чём же дело? Я что-то неправильно понимаю о концепции хорошей хеш-функции? Или
в питоновских словарях и множествах не используется напрямую результат функции hash(),
а как-то дополнительно обрабатывается?
    


Ответы

Ответ 1



Встроенная хеш-функция имеет совсем другие задачи, не связанные с криптографией. Она используется для быстрого и удобного сравнения ключей словарей. Hash values are integers. They are used to quickly compare dictionary keys during a dictionary lookup. Numeric values that compare equal have the same hash value (even if they are of different types, as is the case for 1 and 1.0). По поводу идущих подряд ключей: In [37]: hash('aaaa') Out[37]: 5927745366728125705 In [38]: hash('aaab') Out[38]: 3762861188151674483 In [39]: hash('aaac') Out[39]: -5197229166136799781 Для "криптографических" целей стоит обратить внимание на модуль hashlib: In [35]: hashlib.sha512(b'aaa').hexdigest() Out[35]: 'd6f644b19812e97b5d871658d6d3400ecd4787faeb9b8990c1e7608288664be77257104a58d033bcf1a0e0945ff06468ebe53e2dff36e248424c7273117dac09' In [36]: hashlib.sha512(b'123').hexdigest() Out[36]: '3c9909afec25354d551dae21590bb26e38d53f2173b8d3dc3eee4c047e7ab1c1eb8b85103e3be7ba613b31bb5c9c36214dc9f14a42fd7a2fdb84856bca5c44c2' Пример из доки с использованием "соли": >>> import os >>> from hashlib import blake2b >>> msg = b'some message' >>> # Calculate the first hash with a random salt. >>> salt1 = os.urandom(blake2b.SALT_SIZE) >>> h1 = blake2b(salt=salt1) >>> h1.update(msg) >>> # Calculate the second hash with a different random salt. >>> salt2 = os.urandom(blake2b.SALT_SIZE) >>> h2 = blake2b(salt=salt2) >>> h2.update(msg) >>> # The digests are different. >>> h1.digest() != h2.digest() True

понедельник, 6 января 2020 г.

Сертификат для KeyStore

#java #android #безопасность #криптография


Создаю хранилище для PrivateKey. В строке     KeyStore.PrivateKeyEntry skEntry =
new KeyStore.PrivateKeyEntry() в функцию PrivateKeyEntry() необходимо передать 2 параметра
один из которых сам приватный ключ, а второй параметр это сертификат. Я не совсем понимаю
как этот сертификат получить имея открытый и закрытый ключ.
Весь кусок кода(строку в которой проблема выделил):

final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(4096, new SecureRandom());
final KeyPair key = keyGen.generateKeyPair();
KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection(password.getText().toString().toCharArray());

KeyStore.PrivateKeyEntry skEntry = new KeyStore.PrivateKeyEntry(?????????)

store.setEntry(nickname.getText().toString(), skEntry, protParam);

    


Ответы

Ответ 1



Судя по вопросу вы не совсем понимаете основную проблему публичной криптографии. Главная ее проблема состоит в том, чтобы удостовериться, что публичный ключ принадлежит тому кто ее предъявляет. Это аналогично тому, что человек приходит с ключом от квартиры, где бабки лежат и надо теперь удостовериться что это его квартира. В обычной жизни с такого человека затребуют документ подтверждающий что квартира принадлежит ему или по крайней мере он имеет какое-то отношение к ней (например договор аренды). Точно такую же роль этого удостоверяющего документа в публичной криптографии имеет цифровой сертификат. В реале цифровые сертификаты генерируют доверенные центры, типа VeriSign, Thawte и проч. Их подписи распознаются нормальными браузерами и устройствами, поскольку они могут сверить слепок подписи (fingerprint) со слепками, которые хранятся в устройствах. Для интереса зайдите в своем Android устройстве в раздел Сертификаты безопасности - в настройках девайса или в любом настольном браузере в настройках, типа: . Вообще-то сертификация ключа стоит и денег и времени. В вашем случае, вы сами генерируете на лету пару ключей и поэтому не сможете предъявить нормальный сертификат. На этот случай предусмотрена генерация т.н. Self Signed Certificate, то есть сертификата, который вы сами же и подписали своим же ключом. Возвращаясь к нашему примеру с квартирой, это аналог того, что - предъявитель ключа пишет расписку, типа: да, я имярек, мамой клянусь, что это моя квартира :) Теперь ближе к делу. Вам надо cгенерировать т.н. SelfSigned сертификат стандарта X.509. Но здесь начинаются проблемы. Реализация класса X509Certificate из коробки подразумевает его создания только из битового массива или из InputStream, Selfsign реализован, но почему-то скрыт от широкой общественности. Подробнее об этом здесь К счастью есть такая либа как Bouncy Castle, в котором это можно относительно легко сделать. Но опять же к несчастью, напрямую использовать Bouncy Castle в Android нельзя так как Google по неизвестным причинам его уже использует в коде Android, но в каком то урезанном виде, так что 90% Bouncy Castle неработоспособны. То есть при попытке включить библиотеку Bouncy Castle в ваш код, будет выдана ошибка о задвоении. Опять же к счастью (мир не без добрых людей) - умные люди написали Spongy Castle - специальный порт Bouncy Castle для Android'а который избавлен от конфликта имен. Ну вот теперь: Импортируем Spongy Castle через Gradle Читаем как генерировать сертификат P.S. Уффф... зачем я так много написал? Наверное в честь пятницы

четверг, 2 января 2020 г.

Сохранение данных Android

#криптография #android


[Совет][Теория] 
Доброй ночи, хэшкодовцы =)
Мне стало интересно как лучше сохранять данные, которые вводит пользователь. В моем
случае это пароль & логин.
Что я под этим имею:
Записывать данные в базу SQLite / на память телефона в файл и тому подобное.
Примером для понимания моего вопроса можно взять любое социальное приложение. Одноклассники,
Вконтакте, Mail.Ru Agent, WeChat и другие.    


Ответы

Ответ 1



Теория В теории нельзя хранить пароли. Хранятся только пары логин и хэш пароля, лучше всего хранить хэш и отдельно от хэша соль к паролю, так чтобы: хэш строка=хэш(пароль+соль) //хэш функция например MD5 или SHA1 Проверка пароля осуществляется в этом случае так: Юзер вводит логин и пароль По логину находим хэш строку (из БД) По логину находим соль (в идеале в другом файле/бд) Вычисляем хэш как хэш(введенный пароль+соль) Сравниваем полученное значение с хранящимс в БД хэшем В случае успеха пускаем, в случае неуспеха отражаем Совет Для логин/хэш создаем таблицу SQLite с индексом по логину Для вычисления хэша чаще всего используется MD5 или SHA1, правда некоторые православные криптографы считают их слабыми и рекомендуют другие. Обзор криптографических хэш функций здесь Соль генерируем случайно и храним в преференсах

Ответ 2



Для этого давным давно создан AccountManager и в приложениях которые вы перечислили в целом используется именно он. Как пример, могу порекомендовать это Главное не забыть, что шифровать данные все равно нужно! :)

Ruby. Взаимодействие с yandex kassa [закрыт]

#ruby_on_rails #ruby #криптография #яндекс #openssl


        
             
                
                    
                        
                            Закрыт. Этот вопрос не по теме. Ответы на него в данный
момент не принимаются.
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            Хотите улучшить этот вопрос? Update the question so it's
on-topic for Stack Overflow на русском.
                        
                        Закрыт 3 года назад.
                                                                                
           
                
        
Не знаю, насколько по теме задавать такие вопросы на подобном ресурсе, но я уже отчаялся.

Никак не получается сформировать верный запрос к серверу яндекс денег (3-й шаг) https://tech.yandex.ru/money/doc/payment-solution/payout/format-docpage/ 

Техподдержка ничего толкового не говорит, отмахиваясь ссылками на библиотеки для
работы с вводом, а не выводом средств.

Может быть кто-то уже работал с этой системой и может поделиться примером кода?
    


Ответы

Ответ 1



На всякий случай пишу здесь решение. Проблема не в коде, проблема не в программистах. Проблема в менеджерах Яндекса. Запомните, помимо того, что менеджер ОБЯЗАН выдать вам два сертификата, один для шифрования ваших запросов, один для расшифровки ответов Яндекса, обязательно убедись что для расшифровки на стадии тестирования они выдали вам сертификат для ТЕСТОВОГО сервера, а не продакшен варианта. Если они этого не сделали, пинайте их(звонками, именно звонками, email сообщения для этого не годятся) до тех пор пока они всё вам не передадут, продолжайте пинать, даже если они пытаются говорить, что всё необходимо вам передали.

Ответ 2



Посмотрите материал по ссылке, быть может это поможет (если еще актуально) - https://gist.github.com/kryzhovnik/5b73c1c0637e47b01eaa

понедельник, 30 декабря 2019 г.

Подбор части пароля перебором (brute force attack) по маске и sha-256

#python #python_3x #криптография #хеширование


У меня есть кусок пароля *elp** (вместо звездочек должны быть символы, которые надо
подобрать), но я знаю от него sha256 хеш: 

fda23a72c73c92a1ad61cd18c58961b90c2c127028c8b87fd1a65c5e1f55d17e


Мне надо подобрать из всей этой информации к нему пароль
(если что, пароль helpMe)

я написала кусок программы и не знаю как сделать дальше 

import hashlib
mas = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","1","2","3","4","5","6","7","8","9","0"]

a = b'Hello'
sha = hashlib.sha256(a).hexdigest()

print(sha) 

    


Ответы

Ответ 1



Попробуйте так: import string import hashlib from itertools import product def brute_force(mask, hsh, alphabet=string.ascii_letters+string.digits, verbose=False): # экранируем фигурные скобки # и заменяем '*' на '{}' для последующей подстановки в 'str.format()' pwd_pat = mask.replace('{', '{{').replace('}','}}').replace('*', '{}') # число звездочек - будем использовать в качестве `product(.., repeat)` N = mask.count('*') i = 0 for chars in product(alphabet, repeat=N): if verbose: i += 1 if i % 10000 == 0: print('Iterations: {}'.format(i)) if hsh == hashlib.sha256(pwd_pat.format(*chars).encode()).hexdigest(): return pwd_pat.format(*chars) return None Тест: hsh = 'fda23a72c73c92a1ad61cd18c58961b90c2c127028c8b87fd1a65c5e1f55d17e' In [245]: brute_force('*elp**', hsh, verbose=True) Iterations: 10000 Iterations: 20000 Out[245]: 'helpMe'

Ответ 2



Вариант, который работает с байтами и использует все доступные CPU: #!/usr/bin/env python3 import hashlib import itertools import multiprocessing import string from functools import partial alphabet = string.ascii_lowercase.encode() def sha256(data): return hashlib.sha256(data).digest() def check_sha256(repls_parent, bytes_format, n, target_sha256): for repls in itertools.product(alphabet, repeat=n): data = bytes_format % (repls_parent + repls) if sha256(data) == target_sha256: return data def brute_force(mask, target_sha256, n_cutoff=4): """ n_cutoff -- number of `*` to process in a worker process """ bytes_format = mask.replace(b'%', b'%%').replace(b'*', b'%c') mp_check = partial(check_sha256, bytes_format=bytes_format, n=min(n_cutoff, mask.count(b'*')), target_sha256=target_sha256) n = max(0, mask.count(b'*') - n_cutoff) all_repls_parent = itertools.product(alphabet, repeat=n) with multiprocessing.Pool() as pool: for data in pool.imap_unordered(mp_check, all_repls_parent): if data is not None: return data Пример: import binascii sha256_hex = b'c4bbcb1fbec99d65bf59d85c8cb62ee2db963f0fe106f483d9afa73bd4e39a8a' passw_bytes = brute_force(b'******t horse battery staple', binascii.unhexlify(sha256_hex)) print(passw_bytes.decode()) Задача распараллеливается, делегированием генерации n_cutoff замен в дочерние процессы. Задача подходит для вычисления на GPU. Из-за связи sha256 с Bitcoin mining существуют ASIC, заточенные под вычисление хэшей. Чтобы отслеживать прогресс, можно tqdm модуль использовать: from tqdm import tqdm #... all_repls_parent = itertools.product(alphabet, repeat=n) with multiprocessing.Pool() as pool: for data in tqdm(pool.imap_unordered(mp_check, all_repls_parent), total=len(alphabet)**n): if data is not None: return data

воскресенье, 29 декабря 2019 г.

Насколько безопасен алгоритм

#криптография


Допустим я хочу зашифровать число 100. Выбираю случайное большое число (наш ключ),
допустим
10^27+126737912 и умножаю на 100.

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

Насколько безопасно использовать такой метод шифрования, если ключ передаётся не
по интернету, а лично, допустим на бумажке? :)

P.S Я думаю нереально, т.к если я умножу 10 на 15 (150) и передам другому человеку
по открытому каналу, хакер никак не сможет восстановить 10 из 150 без ключа.
    


Ответы

Ответ 1



Вот простой пример Функция на python, шифрующая несколько сообщений def encrypt(data, key): return [key * x for x in data] Функция расшифровывающая сообщения def decrypt(data, key): return [x // key for x in data] С помощью нее зашифруем несколько чисел: key = 977240797922194023705 print('key ', key) plain = [7, 18, 113] print('plain ', plain) encrypted = encrypt(plain, key) print('encrypted', encrypted) decrypted = decrypt(encrypted, key) print('decrypted', decrypted) Вывод key 977240797922194023705 plain [7, 18, 113] encrypted [6840685585455358165935, 17590334362599492426690, 110428210165207924678665] decrypted [7, 18, 113] А вот функция, с помощью которой хоть и неоднозначно, но с каждым новым сообщением все более точно можно получить ключ import functools import math def hackkey(data): return functools.reduce(math.gcd, data) hackedkey = hackkey(encrypted) print('hacked ', hackedkey) print(hackedkey == key) Вывод hacked 977240797922194023705 True

Ответ 2



Нет, небезопасен. Даже для передачи 1 числа это опасно. Для числа в примере мы имеем всего Поэтому останется всего порядка сотни вариантов а что мы собственно передавали. Если мы передадим ещё одно число, например 9, то у нас останется всего 16 вариантов ключа. Такая защита не имеет смысла. В общем советую почитать что-то о ассиметричном шифровании, например RSA.