Private KeeperPrivate Keeper
in-Line Kit/Функции in-Line Kit

Шифрование

AES, AES-GCM, RSA, Salsa20, ChaCha20 и Blowfish с точными ключами, векторами, тегами и обратимыми примерами.

Шифрование скрывает содержимое, но только AES-GCM на этой странице одновременно проверяет, что шифротекст и связанные данные не были изменены. Все вызовы используют общую форму функций in-Line.

Что выбрать

Новые данные

Выбирайте AESGCMENCRYPT и AESGCMDECRYPT: вместе с шифротекстом они создают и проверяют тег подлинности.

Точный внешний договор AES

AESENCRYPT и AESDECRYPT нужны, когда другая сторона требует AES-CBC, AES-ECB, производный ключ PBKDF2 или форму cryptojs-json.

Короткий секрет для получателя

RSAENCRYPT шифрует открытым ключом, а RSADECRYPT расшифровывает закрытым. Для длинного сообщения шифруйте RSA только ключ AES-GCM.

Совместимость со старым протоколом

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

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

Общие границы безопасности

Ключ не должен ехать рядом с шифротекстом

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

Объект JSON сначала проходит подстановки in-Line. Значение из переменной может содержать кавычку, обратную косую черту или перевод строки, поэтому перед вставкой внутрь строки JSON применяйте ESCJSON. Ключ, вектор и соль измеряются в байтах после декодирования, а не в видимых символах.

AESENCRYPT и AESDECRYPT

Для новой записи используйте вложенный объект. Он отделяет исходный текст, ключ, режим, начальный вектор и результат, поэтому одна кодировка больше не применяется сразу ко всем значениям.

AESENCRYPT

Принимает открытые байты в text, шифрует их по key и cipher, затем возвращает шифротекст либо конверт согласно output.

AESDECRYPT

Принимает шифротекст либо конверт в text, требует тот же ключ и параметры шифра, затем возвращает открытые байты согласно output.

Обратимая пара со случайным вектором

#beginScript
|DV|[AesPackage]=(|AESENCRYPT|{
  "text":{"value":"hello","encoding":"utf8"},
  "key":{"source":"raw","value":"000102030405060708090a0b0c0d0e0f","encoding":"hex"},
  "cipher":{"mode":"CBC","padding":"PKCS7","keyBits":128,"iv":{"source":"random"}},
  "output":{"encoding":"base64","envelope":"json"}
}|AESENCRYPT|)

|DV|[Plain]=(|AESDECRYPT|{
  "text":{"value":"(|ESCJSON||DV|[AesPackage]|ESCJSON|)","encoding":"json"},
  "key":{"source":"raw","value":"000102030405060708090a0b0c0d0e0f","encoding":"hex"},
  "cipher":{"mode":"CBC","padding":"PKCS7","keyBits":128,"iv":{"source":"envelope"}},
  "output":{"encoding":"utf8","envelope":"none"}
}|AESDECRYPT|)
#endScript

|DV|[AesPackage] получает объект вида {"ct":"...","iv":"..."}, а |DV|[Plain]hello. Случайный вектор не является секретом, но без него расшифровка невозможна, поэтому он сохраняется в конверте.

Строгий объект AES

text

Объект с обязательными строками value и encoding. При шифровании доступны utf8, plaintext, hex, hexa, base64; при расшифровке также json и cryptojs-json для конверта.

key

source:"raw" принимает value и encoding; source:"password" дополнительно требует объект derivation. Кодировки ключа: utf8, plaintext, hex, hexa, base64.

cipher

Обязательны mode, padding, keyBits и объект iv. В строгой форме доступны только CBC или ECB, только PKCS7, а ключ — 128, 192 или 256 бит.

output

Обязательны encoding и envelope. Без конверта шифротекст возвращается как hex, hexa или base64; расшифрованные байты также можно получить как utf8 или plaintext.

При CBC вектор всегда равен 16 байтам. Для шифрования его источник — provided с value и encoding либо random; для расшифровки — provided либо envelope. При ECB объект iv всё равно обязателен, но должен быть ровно {"source":"none"}.

Ключ raw после декодирования должен точно совпасть с keyBits: 16, 24 или 32 байта. envelope:"none" запрещён вместе со случайным вектором или случайной солью, потому что исполнитель не разрешает потерять данные, необходимые для расшифровки. envelope:"json" требует output.encoding:"base64" и возвращает ct, iv, а при производном ключе ещё s; значения iv и s внутри конверта записаны строчными шестнадцатеричными знаками.

AES-CBC и AES-ECB не подтверждают целостность

Подмена шифротекста может остаться незамеченной. ECB дополнительно раскрывает повторяющиеся блоки. Если внешний договор не требует эти режимы, используйте AES-GCM.

Неизвестное или повторяющееся поле строгого объекта возвращает Error: .... Плоская форма со строковыми text и key ещё выполняется для существующих проектов, но смешивать плоский и вложенный договор нельзя.

Ключ AES из пароля

Пароль превращается в ключ выбранной длины через PBKDF2. Соль должна быть новой для каждого шифрования; конверт сохраняет её вместе с вектором.

(|AESENCRYPT|{
  "text":{"value":"hello","encoding":"utf8"},
  "key":{"source":"password","value":"correct horse battery staple","encoding":"utf8","derivation":{"algorithm":"pbkdf2","hash":"sha256","iterations":200000,"salt":{"source":"random","bytes":16}}},
  "cipher":{"mode":"CBC","padding":"PKCS7","keyBits":256,"iv":{"source":"random"}},
  "output":{"encoding":"base64","envelope":"json"}
}|AESENCRYPT|)

Для обратной операции повторите hash, iterations, keyBits, режим и пароль, а источники соли и вектора замените на {"source":"envelope"}. Точные значения hash: sha1 или sha-1; sha224, sha256, sha384, sha512 либо те же имена с дефисом после sha; sha3-224, sha3-256, sha3-384, sha3-512. Число итераций — от 1 до 10000000; явная соль — от 1 до 1024 байт, случайная — от 8 до 64 байт.

AESGCMENCRYPT и AESGCMDECRYPT

AES-GCM создаёт случайный начальный вектор и тег подлинности. Тег проверяет шифротекст и дополнительные подтверждаемые данные associatedData; изменение любого из них завершает расшифровку ошибкой. Этот режим определён в NIST SP 800-38D.

AESGCMENCRYPT

Принимает text и ключ в шестнадцатеричной записи, самостоятельно создаёт iv и возвращает объект с шифротекстом и tag.

AESGCMDECRYPT

Требует encryptedText, iv, tag и ключ; возвращает исходный текст только после успешной проверки тега.

Обратимая пара AES-GCM

#beginScript
|DV|[Gcm]=(|AESGCMENCRYPT|{
  "text":"hello",
  "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
  "associatedData":"686561646572",
  "keyLength":256,
  "outputFormat":"base64"
}|AESGCMENCRYPT|)

|DV|[Plain]=(|AESGCMDECRYPT|{
  "encryptedText":"|DV|[Gcm]["encryptedText"]",
  "iv":"|DV|[Gcm]["iv"]",
  "tag":"|DV|[Gcm]["tag"]",
  "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
  "associatedData":"686561646572",
  "keyLength":256,
  "outputFormat":"base64"
}|AESGCMDECRYPT|)
#endScript

После выполнения |DV|[Plain] равно hello. associatedData здесь содержит шестнадцатеричную запись слова header; эти данные не шифруются, но при расшифровке должны совпасть побайтно.

text / encryptedText

text — обязательная строка UTF-8 для шифрования. encryptedText — обязательный шифротекст в представлении outputFormat для расшифровки.

key / keyLength

key всегда задаётся шестнадцатеричной строкой. keyLength равен 128, 192 или 256, по умолчанию 256; ключ должен содержать соответственно 16, 24 или 32 байта.

iv / tag

Шифрование создаёт их само. Расшифрование требует оба значения в том же outputFormat, что и шифротекст.

outputFormat принимает hex, base64, base64url или base32; используйте hex, а не исторический вариант hexa, чтобы одно имя одинаково применялось к шифротексту, вектору и тегу. Необязательный associatedData всегда задаётся шестнадцатеричной строкой.

Поля tagSizeBits у функции нет

Старая страница обещала tagSizeBits, но исполнитель это поле не читает. Добавление поля не меняет размер тега, поэтому не стройте на нём внешний договор.

Результат AESGCMENCRYPT — объект с полями iv, tag, encryptedText, key и outputFormat. Поле key повторяет входной секрет: не отправляйте и не сохраняйте весь объект как готовый пакет, выберите из него только iv, tag, encryptedText и outputFormat. Ошибка обеих функций возвращается объектом {"error":"..."}, а не строкой с началом Error: .

Генерация пары RSA: RSAGENKEY

Правильное имя команды — RSAGENKEY. Запись RSAKEYGEN из старого HTML не существует в исполнителе.

(|RSAGENKEY|2048|RSAGENKEY|)

Аргумент — обычное целое число битов, не объект JSON. Пустая или нечисловая строка выбирает 2048, поэтому ошибочный вызов {"keySize":4096} молча создаст 2048-битную пару. Используемая библиотека принимает размеры от 512 до 8192 бит; создание большого ключа выполняется синхронно и может занять заметное время.

Успешный результат — объект со следующими полями:

  • privateKeyPem — незашифрованный закрытый ключ PKCS#1 с заголовком BEGIN RSA PRIVATE KEY;
  • publicKeyPem — открытый ключ с заголовком BEGIN PUBLIC KEY;
  • privateKeymodulus, d, p, q, dp, dq, inverseQ в Base64;
  • publicKeymodulus и exponent в Base64;
  • keySize — запрошенный размер в битах.

Результат содержит закрытый ключ

Не выводите весь объект в журнал и не передавайте его вместе с открытым ключом. Строка privateKeyPem даёт возможность расшифровать все данные для этой пары.

При ошибке RSAGENKEY возвращает обычный текст сообщения без единого обязательного начала.

RSAENCRYPT и RSADECRYPT

Следующий сценарий создаёт пару, переводит открытые составные части из Base64 в шестнадцатеричную запись, шифрует короткую строку и расшифровывает её закрытым ключом:

RSAENCRYPT

Шифрует короткую строку открытым ключом и возвращает шифротекст Base64.

RSADECRYPT

Расшифровывает строку Base64 соответствующим закрытым ключом и возвращает открытый текст.

#beginScript
|DV|[Keys]=(|RSAGENKEY|2048|RSAGENKEY|)
|DV|[ModulusHex]=(|BASE64TOHEX||DV|[Keys]["publicKey"]["modulus"]|BASE64TOHEX|)
|DV|[ExponentHex]=(|BASE64TOHEX||DV|[Keys]["publicKey"]["exponent"]|BASE64TOHEX|)

|DV|[Cipher]=(|RSAENCRYPT|{
  "text":"session-key-001",
  "modulus":"|DV|[ModulusHex]",
  "publicExponent":"|DV|[ExponentHex]",
  "encType":"oaep",
  "oaepHash":"sha256",
  "oaepMgfHash":"sha256",
  "littleEndian":false
}|RSAENCRYPT|)

|DV|[Plain]=(|RSADECRYPT|{
  "encryptedText":"|DV|[Cipher]",
  "privateKeyPem":"(|ESCJSON||DV|[Keys]["privateKeyPem"]|ESCJSON|)",
  "encType":"oaep",
  "oaepHash":"sha256",
  "oaepMgfHash":"sha256",
  "littleEndian":false
}|RSADECRYPT|)
#endScript

|DV|[Plain] получает session-key-001. RSAENCRYPT возвращает Base64, а RSADECRYPT ожидает шифротекст в том же представлении.

Точный договор RSA

RSAENCRYPT

Обязательны строки text, modulus и publicExponent. modulus принимает полный открытый ключ PEM либо модуль в шестнадцатеричной записи. publicExponent всегда обязателен и проверяется как шестнадцатеричная строка даже при ключе PEM; для 65537 пишите 010001, а не 10001.

RSADECRYPT

Обязательны encryptedText и privateKeyPem. Закрытый ключ принимается как PEM либо как запись DER PKCS#1 в шестнадцатеричной форме; имя поля остаётся privateKeyPem в обоих случаях.

encType равен oaep по умолчанию или v1.5. Для OAEP явно задавайте одинаковые oaepHash и oaepMgfHash на обеих операциях; без них текущая библиотека выбирает SHA-1. Необязательная oaepLabel является шестнадцатеричной строкой и также должна совпасть. littleEndian по умолчанию false; меняйте его только ради внешнего договора и одинаково с обеих сторон.

RSA предназначен для коротких данных. При OAEP предельное число байтов равно размер_ключа_в_байтах − 2 × размер_хеша_в_байтах − 2: для RSA-2048 и SHA-256 это 190 байт. Точные схемы OAEP и PKCS#1 v1.5 определены в RFC 8017.

Некириллический пример выбран намеренно

Исполнитель не задаёт RSA-кодировку символов явно, поэтому библиотека использует системную ANSI-кодовую страницу. Для совместимости между программами шифруйте короткие данные из ASCII, например ключ в Base64, а не произвольный русский текст.

Неверный объект, ключ, заполнение или слишком длинное сообщение возвращают обычный текст ошибки. Проверяйте, что результат шифрования соответствует ожидаемой Base64-строке, а не просто является непустым.

SALSA20ENCRYPT и CHACHA20ENCRYPT

Обе функции принимают key, nonce и message как обычные строки, превращают их в UTF-8 и возвращают шифротекст Base64. Шестнадцатерично выглядящий ключ здесь остаётся текстом: строка 0011 даёт четыре байта символов, а не два байта 00 11.

SALSA20ENCRYPT

(|SALSA20ENCRYPT|{"key":"1234567890abcdef","nonce":"12345678","message":"hello","keyLength":128,"rounds":20}|SALSA20ENCRYPT|)

Результат — oymXuqc=. Ключ содержит ровно 16 байт UTF-8, а одноразовое число — ровно 8.

Фактический ключ должен содержать ровно 16 или 32 байта, а nonce — ровно 8 байт. Поле keyLength принимает 128 или 256 и по умолчанию равно 256, но оно не изменяет ключ и не сверяет указанное число с его фактической длиной. rounds принимает только 8, 12 или 20, по умолчанию 20. Эти требования следуют из используемых исполнителей CryptoLib4Pascal.

Повтор одноразового числа раскрывает данные

Никогда не используйте одну пару ключа и nonce для двух сообщений. Функции не создают одноразовое число сами и не добавляют тег подлинности, поэтому приложение обязано обеспечить уникальность и отдельно проверять целостность.

Публичных SALSA20DECRYPT и CHACHA20DECRYPT нет. Хотя сам потоковый шифр симметричен, эти обёртки всегда читают message как UTF-8 и возвращают Base64, поэтому надёжно подать их двоичный результат обратно нельзя. Для новой обратимой схемы используйте AES-GCM. Этот вариант CHACHA20ENCRYPT также не совпадает с IETF ChaCha20, где применяется 12-байтовое одноразовое число. Ошибки возвращаются как Error: ....

BLOWFISHENCRYPT и BLOWFISHDECRYPT

Blowfish оставлен для совместимости. У него блок всего 8 байт и нет встроенного тега подлинности, поэтому для новых данных выбирайте AES-GCM.

BLOWFISHENCRYPT

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

BLOWFISHDECRYPT

Требует те же параметры и возвращает расшифрованные байты в выбранном представлении.

Обратимая пара Blowfish-CBC

#beginScript
|DV|[Cipher]=(|BLOWFISHENCRYPT|{
  "text":"hello",
  "key":"0123456789abcdef",
  "mode":"CBC",
  "padding":"PKCS7",
  "keyLength":128,
  "blockSize":64,
  "iv":"0001020304050607",
  "includeIV":false,
  "inputFormat":"plaintext",
  "outputFormat":"base64"
}|BLOWFISHENCRYPT|)

|DV|[Plain]=(|BLOWFISHDECRYPT|{
  "text":"|DV|[Cipher]",
  "key":"0123456789abcdef",
  "mode":"CBC",
  "padding":"PKCS7",
  "keyLength":128,
  "blockSize":64,
  "iv":"0001020304050607",
  "includeIV":false,
  "inputFormat":"base64",
  "outputFormat":"plaintext"
}|BLOWFISHDECRYPT|)
#endScript

|DV|[Plain] получает hello. Начальный вектор содержит ровно 8 байт, то есть 16 шестнадцатеричных знаков.

Ключ

От 32 до 448 бит с шагом 8 бит. Ключ должен содержать ровно keyLength / 8 байт. При расшифровке он всегда читается как UTF-8, поэтому для обратимой пары используйте текстовый ключ.

Режим и заполнение

Исполнитель передаёт библиотеке ECB, CBC, CFB, CTR, CTS, OFB или SIC. padding:"NONE" превращается в Zero; для обычного текста используйте одинаковый PKCS7 с обеих сторон.

Представление

Шифрование принимает plaintext, hexa или base64 и применяет выбор одновременно к тексту и ключу. Результат: hexa, base64 или plaintext. Шифротекст безопаснее хранить как Base64 или шестнадцатеричную строку.

Значения по умолчанию не образуют пару: шифрование возвращает hexa, а расшифрование ожидает base64; обе операции выбирают ECB и 448-битный ключ. Поэтому указывайте режим, длину ключа и оба представления явно.

Не полагайтесь на includeIV

Текущая ветвь автоматического добавления случайного вектора формирует длину результата неверно, а при явно заданном iv не добавляет его вообще. Для обратимой операции используйте includeIV:false, явно задавайте 8-байтовый iv шестнадцатеричной строкой и передавайте то же значение при расшифровке.

Для режима кроме ECB отсутствие явного или извлекаемого вектора завершает расшифровку ошибкой. Неверный JSON, размер ключа, вектора, режим, заполнение или шифротекст возвращают строку с началом Error: .