Привет сообщество Stackoverflow,
У меня есть трудности с электронной подписью и особенно с тем, как применять законодательство Сингапура с точки зрения технических требований.
По закону Сингапур принимает электронные подписи, если подпись:
Мы можем сделать электронную подпись через холст HTML5, а затем сохранить ее в виде строки base64. Это означает, что пункты 1., 2. и 3. в порядке.
Проблема возникает в пункте 4. Однако мы действительно можем объединить подпись и данные в зашифрованную строку, так как у нас есть и подпись, и данные, и мы сможем отредактировать данные и создать новую строку:
|id|name|price|signature|final_hash|
------------------------------------
|12|test|40000|data:base|3edcde4642|
Поэтому мы подумали о другом способе, который заключается в том, чтобы смешать какой-то неизвестный нам параметр в final_hash, такой как IP-адрес подписавшего, его / ее пользовательского агента … однако, поскольку мы не сохраняем эти значения, это означает, что позже мы не сможем проверить, были ли изменены некоторые значения.
Вот где мы застряли, у вас есть идеи, как это сделать? Мне кажется невозможным удовлетворить как возможность проверить, не были ли изменены данные, так и невозможность изменить данные позже, но я, конечно, могу ошибаться.
Большое спасибо за вашу помощь!
Примечание: я использую термин «документ» для обозначения того, что вы хотите подписать.
Прежде всего, то, что вы получаете от использования HTML5 canvas или подобных подходов, это не подпись, а отпечаток пальца. Под этим я подразумеваю, что он идентифицирует клиента, но не может подписать документ (по крайней мере, не один). Два предостережения:
Вы не должны подписывать, соединяя отпечаток пальца с данными. Это не подпись, это поваренная соль, и не лучший подход к соли тоже.
Кстати, ClientJS хороший инструмент для создания отпечатков браузера
- уникален для человека, использующего его;
- способен идентифицировать такого человека;
Эти требования означают «Идентификация». Это означает, что вам нужно удостоверение личности человека.
- созданные каким-либо образом или с использованием средств, находящихся под исключительным контролем
человек, использующий это; а также
Это требование заклинания «Аутентификация». Это означает, что вам нужно убедиться, что люди являются теми, кем они себя называют. Вы, вероятно, видели теорию, вы делаете это с помощью: является (то есть биометрические) б) что-то, что человек знает (то есть пароль) или в) что-то, что у человека есть (то есть доступ к учетной записи электронной почты, мобильному телефону и т. д.).
Меня беспокоит, что вы, кажется, используете отпечатки пальцев браузера для идентификации и аутентификации. Это может сделать слишком легким фальсификацию запросов, чтобы казаться другим пользователем.
Обычно в этой ситуации вы должны выполнить традиционный процесс аутентификации с использованием имени пользователя и пароля, а затем создать файл cookie. Почему вы этого избегаете?
- связаны с электронной записью, к которой она относится, таким образом, что в случае изменения записи электронная подпись будет признана недействительной.
Это требование заклинания «Подпись». Это, вероятно, означает, что электронная запись будет общедоступной, и мы хотим иметь защиту от подделок.
кажется невозможным удовлетворить как возможность проверить, не были ли изменены данные, так и невозможность изменить данные позже
Основная идея заключается в том, чтобы подпись стала недействительной при изменении документа. Если вы хотите сделать официальную модификацию, вам нужно создать новую подпись.
Чтобы третьи лица не могли создать подпись из измененного сообщения, вам нужно добавить какой-нибудь секретный ключ. Теперь возникает два вопроса:
Должны ли третьи лица иметь возможность проверить подпись? Если они должны, вам нужен асимметричный алгоритм.
Должны ли документы быть защищены от вас (или людей с жестким доступом к серверу)? Если они должны быть защищены, это предполагает, что вам нужен секрет для каждого пользователя. Самое простое решение — это иметь пароль.
Для реализации асимметричного решения в PHP предлагаю использовать phpseclib.
Следуйте их пример создания пары ключей:
include('Crypt/RSA.php');
$rsa = new Crypt_RSA();
$pair = $rsa->createKey();
$privatekey = $pair['privatekey'];
$publickey = $pair['publickey'];
Код будет использовать энтропию, собранную с сервера, для генерации пары ключей.
Тогда вы можете использовать это, чтобы сделать простой RSA подпись и проверка.
include('Crypt/RSA.php');
$rsa = new Crypt_RSA();
$rsa->loadKey('...'); // private key
$plaintext = '...';
$signature = $rsa->sign($plaintext);
$rsa->loadKey('...'); // public key
echo $rsa->verify($plaintext, $signature) ? 'verified' : 'unverified';
Если вам нужно проверить подписи на клиенте, вы можете использовать jsrsasign.
Для вашего случая использования вам нужна только одна пара ключей для сервера. Концепция здесь заключается в том, что сервер подписывает документ. Если подпись совпадает, это означает, что отпечаток правильный.
В любом случае вы должны хранить секретные ключи в секрете (никогда не отправляйте их клиенту), и вы можете поделиться открытым ключом с кем угодно, чтобы иметь возможность проверить подписи.
Используя это, сервер может подписать документ, который идентифицирует пользователя / клиента (например, отпечаток пальца) и опубликовать документ плюс подпись. Документ будет отлично читаем (он не зашифрован), но если кто-то его изменит, подпись больше не будет действительной.
Для проверки подписи им нужен открытый ключ. Однако открытый ключ бесполезен для создания поддельной подписи, для этого им потребуется получить закрытый ключ.
Основным преимуществом симметричного алгоритма является производительность. Недостаток симметричного алгоритма в том, что вам нужен ключ для его проверки.
Поэтому, если вам нужны третьи стороны, чтобы иметь возможность проверить подпись (или даже если вам нужно, чтобы проверка выполнялась на стороне клиента), вы должны предоставить ключ, используемый для создания подписей.
В этом случае подпись проще реализовать. Подписать использование hash_hmac
с ключом. Чтобы проверить подпись, повторите процедуру и сравните ее с полученной подписью.
Я не уверен, что вы пытаетесь защитить данные от себя. То есть, если ваша цель состоит в том, чтобы помешать вам (или вашей команде / или тому, кто управляет серверами) подделывать данные.
Если это то, что вы хотите, вы можете защитить паролем свои ключи. Для асимметричного решения phpseclib позволяет вам установить пароль, используемый для шифрования закрытого ключа (и, следовательно, должен иметь возможность подписи). Для симметричного решения вы можете использовать пароль непосредственно в качестве ключа.
Если вы хотите сгенерировать этот пароль из отпечатка пальца, вы можете сделать это с помощью функции получения ключа … но помните, что будет столкновения отпечатков пальцев, и что наличие уникального отпечатка браузера может считаться проблемой конфиденциальности.
Вы можете получить криптографический ключ от внешнего ввода (отпечаток браузера, пароль пользователя и т. Д.), Используя ключевая деривационная функция.
От худшего к лучшему варианту:
hash_hmac
. Для меня это первый вменяемый вариант. Практически ничего не стоит менять хеш конкатенации на вызов hash_hmac
, Кроме того, он защитит вас от частичной уязвимости прообраза алгоритма хеширования (известного или подлежащего обнаружению).hash_hkdf
или же hash_pbkdf2
.Примечание: иногда люди (в том числе и я из прошлого) называют эти ключевые производные функции хеш-функциями. Причина в том, что когда вы используете их, вы не вызываете свою обычную хеш-функцию (напрямую), а то, что они вам дают, технически является хешем. Однако в действительности они не являются алгоритмами хеширования; они представляют собой алгоритмы, построенные на основе хеширования… фактически, один из параметров для их использования — это какая хеш-функция используется внутри.
Других решений пока нет …