Шифрование форм SagePay с использованием ColdFusion
Я пытаюсь следовать спецификации для зашифрованного поля в SagePay 3.00 с использованием ColdFusion 10.
Требуется зашифровать строку как AES(размер блока 128 бит) в режиме CBC с заполнением PKCS#5, используя предоставленный пароль в качестве ключа и вектора инициализации, и кодировать результат в шестнадцатеричном виде.
Именно "использование предоставленного пароля" вызывает проблему.
На данный момент у меня есть
myStr = 'assortednamevaluepairsetc';
providedPassword = 'abcdefghijklmnop';
myCrypt = Encrypt(myStr,providedPassword,'AES/CBC/PKCS5Padding','HEX',providedPassword,1);
но это не сработает, потому что значение, которое я дал SagePay, вызывает ошибку - "указанный ключ не является допустимым ключом для этого шифрования: недопустимая длина ключа AES", так как его длина всего 16 символов
В соответствии с документами CF вы должны использовать generateSecretKey, чтобы гарантировать длину ключа для AES, поэтому я попробовал это, но хотя это дает результат, это не правильный результат с точки зрения шифрования
myStr = 'assortednamevaluepairsetc';
providedPassword = 'abcdefghijklmnop';
mySecret = GenerateSecretKey('AES');
myCrypt = Encrypt(myStr,mySecret,'AES/CBC/PKCS5Padding','HEX',providedPassword,1);
Любая помощь по этому поводу с благодарностью получена.
1 ответ
используйте generateSecretKey, чтобы гарантировать длину ключа для AES
Эта функция используется только тогда, когда вам нужно сгенерировать совершенно новый ключ шифрования. У вас уже есть один. Основная цель generateSecretKey
чтобы вы генерировали надежный ключ шифрования, достаточно случайный.
не будет работать, потому что значение, которое я дал SagePay, вызывает ошибку - "указанный ключ не является допустимым ключом для этого шифрования: неверная длина ключа AES", поскольку его длина составляет всего 16 символов
Длина ключа 16 байтов (то есть 128 бит) является приемлемой для AES. Проблема заключается в том, что encrypt() ожидает, что "ключом" будет строка в кодировке base64, что примерно на тридцать три процента длиннее простой строки. Когда вы вызываете encrypt(..), CF декодирует предоставленную строку "ключа" в байты, т.е. по сути дела это:
<cfset keyBytes = binaryDecode(yourPassword, "base64")>
<cfoutput>length = #arrayLen(keyBytes)# bytes</cfoutput>
Поскольку ваша строка пароля не закодирована в base64, полученная длина ключа слишком мала, то есть (12) вместо (16) байтов. Отсюда и сообщение об ошибке.
Решение состоит в том, чтобы base64 закодировал это сначала. Как вы это сделаете, зависит от кодировки строки. Похоже, это просто текстовая строка (надеюсь, достаточно случайная...). Если это так, используйте charsetDecode для декодирования строки из соответствующего набора символов (т. Е. Utf -8, и так далее), а затем двоично закодируйте его в base64:
<cfset keyIVBytes = charsetDecode(yourKeyString, "utf-8")>
<cfset base64Key = binaryEncode(keyIVBytes, "base64")>
Так же iv
Параметр должен быть двоичным. поскольку key
а также iv
один и тот же, просто используйте байтовый массив из предыдущего шага. Кроме того, бросьте iterations
параметр, так как он не применяется. С этими изменениями все должно работать как положено:
encrypt(myStr, base64Key,"AES/CBC/PKCS5Padding", "hex", keyIVBytes)
NB: Я не эксперт по шифрованию, но... использование ключа в качестве iv не является хорошей идеей... Возможно, стоит проверить их, чтобы узнать, есть ли другие варианты.