Nano Hash - криптовалюты, майнинг, программирование

Получение производного ключа с помощью CCKeyDerivationPBKDF

У меня проблема с получением псевдослучайного производного ключа с использованием CCKeyDerivationPBKDF.

Вот код, который я использую @zaph:

//    password     password String
//    salt         salt Data
//    keyByteCount number of key bytes to generate
//    rounds       Iteration rounds
//    
//    returns      Derived key


func pbkdf2SHA1(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? {
    return pbkdf2(hash:CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds)
}

func pbkdf2SHA256(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? {
    return pbkdf2(hash:CCPBKDFAlgorithm(kCCPRFHmacAlgSHA256), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds)
}

func pbkdf2SHA512(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? {
    return pbkdf2(hash:CCPBKDFAlgorithm(kCCPRFHmacAlgSHA512), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds)
}

func pbkdf2(hash :CCPBKDFAlgorithm, password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? {
    let passwordData = password.data(using:String.Encoding.utf8)!
    var derivedKeyData = Data(repeating:0, count:keyByteCount)

    let derivationStatus = derivedKeyData.withUnsafeMutableBytes {derivedKeyBytes in
        salt.withUnsafeBytes { saltBytes in

            CCKeyDerivationPBKDF(
                CCPBKDFAlgorithm(kCCPBKDF2),
                password, passwordData.count,
                saltBytes, salt.count,
                hash,
                UInt32(rounds),
                derivedKeyBytes, derivedKeyData.count)
        }
    }

    if (derivationStatus != 0) {
        print("Error: \(derivationStatus)")
        return nil;
    }



    return derivedKeyData
}

Моя проблема в том, что он продолжает генерировать одни и те же производные ключи для каждого вызова. Я пытаюсь расшифровать данные, которые были зашифрованы на стороне .Net с помощью Rfc2898DeriveBytes:

var saltBytes = Encoding.ASCII.GetBytes(salt);
var key = new Rfc2898DeriveBytes(Inputkey, saltBytes);

var aesAlg = new RijndaelManaged();
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);   // default keySize 256
aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);  // default blockSize 128

На стороне .Net Rfc2898DeriveBytes возвращает новый случайный набор байтов, но мой код Swift только генерирует для каждого вызова одну и ту же последовательность. Что не так с генерацией последовательности на стороне Swift?

Edit1: когда я использовал последовательности байтов Key и IV, сгенерированные Rfc2898DeriveBytes из .net в Swift, пытаясь расшифровать данные, зашифрованные в .net, тогда он работал нормально.

Edit2: Хорошо, я обнаружил, что первый раз, когда Rfc2898DeriveBytes работает с методом GetBytes, дает тот же результат, что и результат Swift PBKDF2. Второй вызов GetBytes дает совершенно другой результат. Это почему? Если я найду решение для этого, то моя расшифровка должна работать.

aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);   // (1) - the same result as in Swift implementation
aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);  // (2) - completly different result

Я неправильно инициализирую IV в Swift?

26.06.2017

  • Каждый раз при производстве необходимо использовать другую соль. Тот же самый IV должен использоваться при шифровании и дешифровании, один из распространенных методов для достижения этого - tp префикс зашифрованных данных с IV, он не должен быть секретным. В случае с aesAlg.IV функция была инициализирована один раз и к ней были сделаны два вызова. Использование одного и того же IV с одним и тем же ключом более одного раза является проблемой безопасности. 26.06.2017
  • @zaph Большое спасибо за ответ. Простите, я все еще не понимаю. Всегда ли IV имеет длину 16 байт для AES256? Вы имеете в виду, что метод GetBytes не должен вызываться дважды в одном и том же экземпляре? Я могу задавать глупые вопросы, потому что я новичок в этой теме. 26.06.2017
  • AES IV всегда 16-байтовый. Он должен быть разным для каждого использования одного и того же ключа шифрования. Лучше всего передавать его для дешифрования как часть зашифрованных данных, часто добавляемую к зашифрованным данным. Не имеет значения, что такое IV, если он случайный. Если используется метод, который генерирует тот же IV для того же ключа, это небезопасно. 26.06.2017
  • @zaph спасибо за ваше время и объяснения. Думаю, теперь я понимаю, как это работает. Моя проблема теперь в том, как сгенерировать IV так же, как он создается на C # с Rfc2898DeriveBytes в Swift. Другой способ - передать IV как добавленный к зашифрованным данным, как вы упомянули. 26.06.2017

Ответы:


1

Реализация .NET фактически представляет собой поток. Чтобы получить эквивалентный ответ от версии Apple, вы должны запросить общее количество байтов, которое вам нужно, за один вызов, а затем разделить его на те части, которые вам нужны.

28.06.2017
  • Спасибо за ответ, я это проверю. 28.06.2017
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

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

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..