mirror of
https://github.com/vishalxl/nostr_console.git
synced 2025-04-01 00:18:21 +02:00
fixed keys less than 64 bytes, and encrypted channel improvements
made so that live updation/decryption of messages can happen when user is added using 141 event. to be tested.
This commit is contained in:
parent
5e7ed002bf
commit
644740ad25
@ -672,7 +672,7 @@ Future<void> createEncryptedChannel(Store node) async {
|
||||
|
||||
String newPriKey = getRandomPrivKey();
|
||||
//print("Created and going to use new random privake key: $newPriKey");
|
||||
String channelPriKey = newPriKey, channelPubKey = getPublicKey(newPriKey);
|
||||
String channelPriKey = newPriKey, channelPubKey = myGetPublicKey(newPriKey);
|
||||
|
||||
// now send password as direct message to yourself and to all the people you tagged
|
||||
String messageToSend = "App Encrypted Channels: inviting you to encrypted channel $newEncryptedChannelId encrypted using private public keys $channelPriKey $channelPubKey";
|
||||
@ -696,7 +696,7 @@ Future<void> updateEncryptedChannel(Store node, String channelId,
|
||||
//print("updated encrypted channel $channelId with new 141 event with id: $newEncryptedChannelId");
|
||||
//print("tags: $tags");
|
||||
|
||||
List<String> keys = getEncryptedChannelKeys(node, channelId);
|
||||
List<String> keys = getEncryptedChannelKeys(node.directRooms, node.allChildEventsMap, channelId);
|
||||
if( keys.length == 2) {
|
||||
String channelPriKey = keys[0], channelPubKey = keys[1];
|
||||
|
||||
@ -718,7 +718,7 @@ Future<void> updateEncryptedChannel(Store node, String channelId,
|
||||
String encryptChannelMessage(Store node, String channelId, String messageToSend) {
|
||||
String encryptedMessage = '';
|
||||
|
||||
List<String> keys = getEncryptedChannelKeys(node, channelId);
|
||||
List<String> keys = getEncryptedChannelKeys(node.directRooms, node.allChildEventsMap, channelId);
|
||||
if( keys.length != 2) {
|
||||
return '';
|
||||
}
|
||||
@ -810,6 +810,7 @@ Future<void> encryptedChannelMenuUI(Store node) async {
|
||||
String? $tempUserInput = stdin.readLineSync();
|
||||
String channelId = $tempUserInput??"";
|
||||
|
||||
|
||||
if( channelId == "x") {
|
||||
showChannelOption = false;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'dart:io';
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
import 'package:bip340/bip340.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:nostr_console/tree_ds.dart';
|
||||
import 'package:translator/translator.dart';
|
||||
@ -196,7 +197,7 @@ class EventData {
|
||||
}
|
||||
|
||||
// is called only once for each event received ( or read from file)
|
||||
void translateAndExpandMentions(Store? node) {
|
||||
void translateAndExpandMentions(List<DirectMessageRoom> directRooms, Map<String, Tree> tempChildEventsMap) {
|
||||
if( id == gCheckEventId) {
|
||||
printInColor("in translateAndExpandMensitons: decoding ee810ea73072af056cceaa6d051b4fcce60739247f7bcc752e72fa5defb64f09\n", redColor);
|
||||
}
|
||||
@ -256,16 +257,38 @@ class EventData {
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
} // end switch
|
||||
} // end translateAndExpandMentions
|
||||
|
||||
|
||||
// is called only once for each event received ( or read from file)
|
||||
void translateAndExpand14x(List<DirectMessageRoom> directRooms, List<Channel> encryptedChannels, Map<String, Tree> tempChildEventsMap) {
|
||||
if( id == gCheckEventId) {
|
||||
printInColor("in translateAndExpandMensitons: decoding ee810ea73072af056cceaa6d051b4fcce60739247f7bcc752e72fa5defb64f09\n", redColor);
|
||||
}
|
||||
|
||||
if (content == "" || evaluatedContent != "") {
|
||||
if( id == gCheckEventId) {
|
||||
printInColor("in translateAndExpandMensitons: returning \n", redColor);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch(kind) {
|
||||
case 142:
|
||||
String? decrypted = decryptEncryptedChannelMessage(node);
|
||||
String? decrypted = decryptEncryptedChannelMessage(directRooms, encryptedChannels, tempChildEventsMap);
|
||||
if( decrypted != null) {
|
||||
evaluatedContent = decrypted;
|
||||
evaluatedContent = expandMentions(evaluatedContent);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
} // end switch
|
||||
} // end translateAndExpandMentions
|
||||
} // end translateAndExpand14x
|
||||
|
||||
|
||||
String? decryptDirectMessage() {
|
||||
int ivIndex = content.indexOf("?iv=");
|
||||
@ -307,8 +330,8 @@ class EventData {
|
||||
}
|
||||
|
||||
|
||||
String? decryptEncryptedChannelMessage(Store? node) {
|
||||
Channel? channel = getChannelForMessage( (node?.encryptedChannels)??null, id);
|
||||
String? decryptEncryptedChannelMessage(List<DirectMessageRoom> directRooms, List<Channel> encryptedChannels,Map<String, Tree> tempChildEventsMap) {
|
||||
Channel? channel = getChannelForMessage( encryptedChannels, id);
|
||||
if( channel == null) {
|
||||
print("could not find channel");
|
||||
return null;
|
||||
@ -318,6 +341,17 @@ class EventData {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(!channel.participants.contains(pubkey)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if( id == "b1ab66ac50f00f3c3bbc91e5b9e03fc8e79e3fdb9f6d5c9ae9777aa6ca3020a2") {
|
||||
print("\n\ngoing to decrypt b1ab66ac50f00f3c3bbc91e5b9e03fc8e79e3fdb9f6d5c9ae9777aa6ca3020a2");
|
||||
print(channel.participants);
|
||||
}
|
||||
|
||||
//print("Going to decrypt event id: $id");
|
||||
|
||||
//print("In decryptEncryptedChannelMessage: for event of kind 142 with event id = $id");
|
||||
int ivIndex = content.indexOf("?iv=");
|
||||
var iv = content.substring( ivIndex + 4, content.length);
|
||||
@ -326,7 +360,7 @@ class EventData {
|
||||
String channelId = getChannelIdForMessage();
|
||||
//print("In decryptEncryptedChannelMessage: got channel id $channelId");
|
||||
List<String> keys = [];
|
||||
keys = getEncryptedChannelKeys(node, channelId);
|
||||
keys = getEncryptedChannelKeys(directRooms, tempChildEventsMap, channelId);
|
||||
|
||||
if( keys.length != 2) {
|
||||
printInColor("Could not get keys for event id: $id and channelId: $channelId", redColor);
|
||||
@ -1147,6 +1181,12 @@ String getRandomPrivKey() {
|
||||
|
||||
BigInt randomNumber = fr.nextBigInteger(256);
|
||||
String strKey = randomNumber.toRadixString(16);
|
||||
if( strKey.length < 64) {
|
||||
int numZeros = 64 - strKey.length;
|
||||
for(int i = 0; i < numZeros; i++) {
|
||||
strKey = "0" + strKey;
|
||||
}
|
||||
}
|
||||
return strKey;
|
||||
}
|
||||
|
||||
@ -1301,17 +1341,13 @@ bool isValidPubkey(String pubkey) {
|
||||
}
|
||||
|
||||
|
||||
List<String> getEncryptedChannelKeys(Store? node, String channelId) {
|
||||
if( node == null) {
|
||||
//print("node is null");
|
||||
return [];
|
||||
}
|
||||
Event? e = node.allChildEventsMap[channelId]?.event;
|
||||
List<String> getEncryptedChannelKeys(List<DirectMessageRoom> directRooms, Map<String, Tree> tempChildEventsMap, String channelId) {
|
||||
Event? e = tempChildEventsMap[channelId]?.event;
|
||||
if( e != null) {
|
||||
//print("\n----------------\nIn getEncryptedChannelKeys for encrypted channel $channelId");
|
||||
String creatorPubKey = e.eventData.pubkey;
|
||||
for( int i = 0; i < node.directRooms.length; i++) {
|
||||
DirectMessageRoom room = node.directRooms[i];
|
||||
for( int i = 0; i < directRooms.length; i++) {
|
||||
DirectMessageRoom room = directRooms[i];
|
||||
if( room.otherPubkey == creatorPubKey) {
|
||||
//print("got other pubkey $creatorPubKey");
|
||||
for( int j = 0; j < room.messageIds.length; j++) {
|
||||
@ -1320,7 +1356,7 @@ List<String> getEncryptedChannelKeys(Store? node, String channelId) {
|
||||
//printInColor( "j = $j messageId = ${messageId}\n", redColor);
|
||||
}
|
||||
|
||||
Event? messageEvent = node.allChildEventsMap[messageId]?.event;
|
||||
Event? messageEvent = tempChildEventsMap[messageId]?.event;
|
||||
if( messageEvent != null) {
|
||||
//print("got a message which is: ${messageEvent.eventData.evaluatedContent}");
|
||||
//print(messageEvent.eventData.getStrForChannel(0));
|
||||
@ -1332,8 +1368,9 @@ List<String> getEncryptedChannelKeys(Store? node, String channelId) {
|
||||
//print("num messages: ${room.messageIds.length}");
|
||||
}
|
||||
|
||||
if( evaluatedContent.contains(channelId)) {
|
||||
//print(" success: got password in pvt message: $evaluatedContent");
|
||||
if( evaluatedContent.contains(channelId) && evaluatedContent.length == 288) {
|
||||
//print("in getEncryptedChannelKeys: success: got password in pvt message: $evaluatedContent");
|
||||
//print("len of evaluated content: ${evaluatedContent.length} ");
|
||||
String priKey = evaluatedContent.substring(159, 159 + 64);
|
||||
String pubKey = evaluatedContent.substring(224, 224 + 64);
|
||||
return [priKey, pubKey];
|
||||
@ -1348,3 +1385,15 @@ List<String> getEncryptedChannelKeys(Store? node, String channelId) {
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
String myGetPublicKey(String prikey) {
|
||||
String pubkey = getPublicKey(prikey);
|
||||
|
||||
if( pubkey.length < 64) {
|
||||
int numZeros = 64 - pubkey.length;
|
||||
for(int i = 0; i < numZeros; i++) {
|
||||
pubkey = "0" + pubkey;
|
||||
}
|
||||
}
|
||||
return pubkey;
|
||||
}
|
||||
|
@ -584,7 +584,7 @@ class Store {
|
||||
} // end switch
|
||||
}
|
||||
|
||||
static void handleEncryptedChannelEvents( List<Channel> encryptedChannels, Map<String, Tree> tempChildEventsMap, Event ce) {
|
||||
static void handleEncryptedChannelEvents( List<DirectMessageRoom> directRooms, List<Channel> encryptedChannels, Map<String, Tree> tempChildEventsMap, Event ce) {
|
||||
String eId = ce.eventData.id;
|
||||
int eKind = ce.eventData.kind;
|
||||
|
||||
@ -613,9 +613,11 @@ class Store {
|
||||
{
|
||||
Set<String> participants = {};
|
||||
ce.eventData.pTags.forEach((element) { participants.add(element);});
|
||||
//print("In handleEncryptedChannelEvents: processing kind 141 with participants = $participants");
|
||||
|
||||
|
||||
String chatRoomId = ce.eventData.getChannelIdForMessage();
|
||||
print("--------\nIn handleEncryptedChannelEvents: processing kind 141 id with ${ce.eventData.id} with participants = $participants");
|
||||
print("for original channel id: $chatRoomId");
|
||||
try {
|
||||
dynamic json = jsonDecode(ce.eventData.content);
|
||||
Channel? channel = getChannel(encryptedChannels, chatRoomId);
|
||||
@ -628,8 +630,16 @@ class Store {
|
||||
}
|
||||
channel.participants = participants;
|
||||
|
||||
for(int i = 0; i < channel.messageIds.length; i++) {
|
||||
Event ?e = tempChildEventsMap[channel.messageIds[i]]?.event;
|
||||
if( e != null) {
|
||||
//print("num directRooms = ${directRooms.length}");
|
||||
e.eventData.translateAndExpand14x(directRooms, encryptedChannels, tempChildEventsMap);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
//print("In handleEncryptedChannelEvents: warning: should not happen. got 141 when 140 is not yet found");
|
||||
print("In handleEncryptedChannelEvents: got 141 when 140 is not yet found");
|
||||
String roomName = "", roomAbout = "";
|
||||
if( json.containsKey('name') ) {
|
||||
roomName = json['name']??"";
|
||||
@ -640,7 +650,7 @@ class Store {
|
||||
}
|
||||
List<String> emptyMessageList = [];
|
||||
Channel room = Channel(chatRoomId, roomName, roomAbout, "", emptyMessageList, participants);
|
||||
//print("created encrypted room with id $chatRoomId and name $roomName");
|
||||
print("created encrypted room with id $chatRoomId and name $roomName");
|
||||
encryptedChannels.add( room);
|
||||
}
|
||||
} on Exception catch(e) {
|
||||
@ -734,6 +744,7 @@ class Store {
|
||||
directRooms.add( newDirectRoom);
|
||||
if( ce.eventData.id == gCheckEventId && gDebug >= 0) print("Adding new message ${ce.eventData.id} to NEW direct room $directRoomId. sender pubkey = ${ce.eventData.pubkey}.");
|
||||
}
|
||||
ce.eventData.translateAndExpandMentions(directRooms, tempChildEventsMap);
|
||||
} else {
|
||||
if( gDebug > 0) print("Could not get chat room id for event ${ce.eventData.id} sender pubkey = ${ce.eventData.pubkey}.");
|
||||
}
|
||||
@ -781,14 +792,17 @@ class Store {
|
||||
|
||||
tempChildEventsMap.forEach((newEventId, tree) {
|
||||
int eKind = tree.event.eventData.kind;
|
||||
|
||||
// these are handled in another iteration ( cause first private messages need to be populated)
|
||||
if( eKind == 142 || eKind == 140 || eKind == 141) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if( eKind == 42 || eKind == 40) {
|
||||
handleChannelEvents(channels, tempChildEventsMap, tree.event);
|
||||
}
|
||||
|
||||
if( eKind == 142 || eKind == 140 || eKind == 141) {
|
||||
//print("In fromEvents: kind $eKind");
|
||||
handleEncryptedChannelEvents(encryptedChannels, tempChildEventsMap, tree.event);
|
||||
}
|
||||
|
||||
|
||||
if( eKind == 4) {
|
||||
@ -857,6 +871,13 @@ class Store {
|
||||
}
|
||||
}); // going over tempChildEventsMap and adding children to their parent's .children list
|
||||
|
||||
tempChildEventsMap.forEach((newEventId, tree) {
|
||||
int eKind = tree.event.eventData.kind;
|
||||
if( eKind == 142 || eKind == 140 || eKind == 141) {
|
||||
handleEncryptedChannelEvents(tempDirectRooms, encryptedChannels, tempChildEventsMap, tree.event);
|
||||
}
|
||||
});
|
||||
|
||||
// add parent trees as top level child trees of this tree
|
||||
for( var tree in tempChildEventsMap.values) {
|
||||
if( tree.event.eventData.kind == 1 && tree.event.eventData.eTags.isEmpty) { // only posts which are parents
|
||||
@ -926,7 +947,7 @@ class Store {
|
||||
|
||||
// expand mentions ( and translate if flag is set) and then add event to main event map
|
||||
if( newEvent.eventData.kind != 142)
|
||||
newEvent.eventData.translateAndExpandMentions(gStore); // this also handles dm decryption for kind 4 messages, for kind 1 will do translation/expansion;
|
||||
newEvent.eventData.translateAndExpandMentions(directRooms, allChildEventsMap); // this also handles dm decryption for kind 4 messages, for kind 1 will do translation/expansion;
|
||||
|
||||
// add them to the main store of the Tree object, but after checking that its not one of the dummy/missing events.
|
||||
// In that case, replace the older dummy event, and only then add it to store-map
|
||||
@ -1030,7 +1051,7 @@ class Store {
|
||||
case 140:
|
||||
case 141:
|
||||
//print("calling handleEncryptedChannelEvents for kind ${newTree.event.eventData.kind} from processIncoming");
|
||||
handleEncryptedChannelEvents(encryptedChannels, allChildEventsMap, newTree.event);
|
||||
handleEncryptedChannelEvents(directRooms, encryptedChannels, allChildEventsMap, newTree.event);
|
||||
break;
|
||||
|
||||
case 142:
|
||||
@ -1043,7 +1064,7 @@ class Store {
|
||||
if( channel != null) {
|
||||
if( gDebug > 0) print("added event to encrypted chat room in insert event");
|
||||
channel.addMessageToRoom(newTree.event.eventData.id, allChildEventsMap); // adds in order
|
||||
newTree.event.eventData.translateAndExpandMentions(this);
|
||||
newTree.event.eventData.translateAndExpand14x(directRooms, encryptedChannels, allChildEventsMap);
|
||||
break;
|
||||
} else {
|
||||
Set<String> participants = {};
|
||||
@ -1051,7 +1072,7 @@ class Store {
|
||||
Channel newChannel = Channel(channelId, "", "", "", [], participants);
|
||||
newChannel.addMessageToRoom(newTree.event.eventData.id, allChildEventsMap);
|
||||
encryptedChannels.add(newChannel);
|
||||
newTree.event.eventData.translateAndExpandMentions(this);
|
||||
newTree.event.eventData.translateAndExpand14x(directRooms, encryptedChannels, allChildEventsMap);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1344,6 +1365,7 @@ class Store {
|
||||
if( channelId.length > 64 ) {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
// first check channelsId's, in case user has sent a channelId itself
|
||||
Set<String> fullChannelId = {};
|
||||
@ -1371,6 +1393,11 @@ class Store {
|
||||
if( room != null) {
|
||||
|
||||
if( room.participants.length > 0) {
|
||||
// enforce the participants-only rule
|
||||
if( !room.participants.contains(userPublicKey)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
stdout.write("\n\nEncrypted channel participants list: ");
|
||||
|
||||
room.participants.forEach((participant) {
|
||||
@ -1950,8 +1977,8 @@ Store getTree(Set<Event> events) {
|
||||
Store node = Store.fromEvents(events);
|
||||
|
||||
// translate and expand mentions for all
|
||||
events.where((element) => element.eventData.kind != 142).forEach( (event) => event.eventData.translateAndExpandMentions(node));;
|
||||
events.where((element) => element.eventData.kind == 142).forEach( (event) => event.eventData.translateAndExpandMentions(node));;
|
||||
events.where((element) => element.eventData.kind != 142).forEach( (event) => event.eventData.translateAndExpandMentions(node.directRooms, node.allChildEventsMap));;
|
||||
events.where((element) => element.eventData.kind == 142).forEach( (event) => event.eventData.translateAndExpand14x(node.directRooms, node.encryptedChannels, node.allChildEventsMap));;
|
||||
if( gDebug > 0) log.info("expand mentions finished.");
|
||||
|
||||
if(gDebug > 0) print("total number of posts/replies in main tree = ${node.count()}");
|
||||
|
@ -3,7 +3,7 @@ description: A multi-platform nostr client built for terminal/console.
|
||||
version: 0.0.9-beta
|
||||
homepage: https://github.com/vishalxl/nostr_console
|
||||
|
||||
# Release 0.0.9 - encrypted channels
|
||||
# Release 0.0.9 - encrypted channels; fixes
|
||||
|
||||
environment:
|
||||
sdk: '>=2.17.3 <3.0.0'
|
||||
|
Loading…
x
Reference in New Issue
Block a user