Сделать данные из смарт-контрактов/событий видимыми только для определенных адресов/пользователей

У меня есть вариант использования, где мне нужно:

1- Мои данные не должны быть видны общественности.

2- Чтобы иметь возможность отозвать права моих клиентов/пользователей на просмотр указанных данных из моего смарт-контракта.

Как кто-нибудь делал это раньше?

Я думал о шифровании/дешифровании моей клиентской части данных, чтобы данные никогда не были видны в цепочке блоков в чистом виде, и это кажется достаточно надежным (клиент будет держать закрытый ключ)

Но тогда я не вижу, как запретить моим пользователям просматривать события для этого контракта, используя что-то вроде

contractInstance.EventName({x: y}, {fromBlock: 0, toBlock: 'latest'});

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

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

Есть ли какое-либо другое/лучшее решение этой проблемы?

Редактировать :

Еще немного о моем случае использования — это своего рода реестр. Я размещаю данные в блокчейне, я даю право добавлять/редактировать данные своим пользователям с базовыми правами (я являюсь владельцем контракта и есть список авторизованных пользователей, которые могут использовать функции добавления/редактирования). ,Пользователь может редактировать только свои данные, но может видеть весь набор, если подписался.

Я хочу, чтобы этот же список пользователей ТОЛЬКО мог читать данные (система на основе подписки), чтобы после окончания подписки они больше не могли читать данные.

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

Ответы (2)

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

Предполагая, что вы довольны тем, что люди, которые прекратили подписку, могут получить доступ к данным, которые уже были им доступны — что вы в принципе не можете предотвратить в любом случае — есть несколько способов добиться этого.

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

Небольшое изменение может упростить управление ключами: используйте один ключ для каждой «эпохи». Эпоха заканчивается каждый раз, когда пользователь заканчивает свою подписку. Всякий раз, когда вы вставляете сообщение, шифруйте его, используя текущий ключ эпохи (не забудьте также использовать IV, чтобы предотвратить атаки по словарю и по известному открытому тексту). Обеспечить хранилище ключей, которое позволяет пользователям получать доступ к ключам эпохи для каждой эпохи, на которую они подписаны; либо вне сети, либо путем шифрования этих ключей открытым ключом каждого пользователя, которому разрешено их использовать.

@jayD На основе вашего редактирования вы можете получить открытый ключ от каждого клиента и зашифровать данные с помощью ключа каждого активного пользователя при их публикации. Если пользователь прекращает подписку, вы можете удалить его ключ из активного набора; они смогут получить доступ к данным только до момента прекращения действия их подписки.
Но разве это не означает, что весь набор данных будет храниться n^activeuserkey раз? потому что я не могу представить, как пользователь сможет увидеть весь набор данных, если он зашифрован с использованием разных закрытых ключей? я что-то упускаю
@jayD Вы можете зашифровать каждое сообщение случайно сгенерированным ключом, а затем зашифровать ключ с помощью открытых ключей каждого пользователя. На самом деле именно так работает обычное шифрование с открытым ключом. И накладные расходы составляют n * activeUsers, а не n^activeUsers.
Я обновил свой ответ более подробно на этот счет.
Отлично это идеально! Не могли бы вы просто указать мне, как «зашифровать эти ключи с помощью открытого ключа каждого пользователя, которому разрешено их использовать». Я понимаю, как это можно сделать на стороне клиента, но я больше ищу решение On chain, если это возможно. Есть ли надежный способ зашифровать данные из параметра функции, используя список адресов, чтобы для каждых добавленных данных я мог зашифровать автоматически сгенерированный ключ для каждого пользователя/адреса?
@jayD Вы не можете сделать это в цепочке, потому что тогда аргументы вызова, содержащие незашифрованные данные, будут в цепочке блоков.
Вы можете запретить людям выполнять определенные части кода, завернув его в проверку для msg.sender, верно?
@NickJohnson, но как только активный пользователь расшифрует с помощью своего открытого ключа, он узнает о сгенерированном ключе и сможет раскрыть его публично - тогда каждый пользователь будет иметь доступ к ключу без подписки. Мне интересно, есть ли хороший способ управлять подпиской на зашифрованное содержимое.

Загляните в Кворум. Он работает «по» сети Ethereum и в основном делает то, о чем вы говорите.