diff --git a/examples/c-bindings/main.c b/examples/c-bindings/main.c index a17d28ae..d55b4146 100644 --- a/examples/c-bindings/main.c +++ b/examples/c-bindings/main.c @@ -135,7 +135,11 @@ int main(int argc, char *argv[]) sprintf(wakuMsg, "{\"payload\":\"%s\",\"contentTopic\":\"%s\",\"timestamp\":%"PRIu64"}", msgPayload, contentTopic, nowInNanosecs()); free(msgPayload); - WAKU_CALL(waku_relay_publish_enc_asymmetric(wakuMsg, NULL, bobPubKey, alicePrivKey, 0, handle_ok, handle_error)); // Broadcast via waku relay a message encrypting it with Bob's PubK, and signing it with Alice PrivK + + WAKU_CALL(waku_encode_asymmetric(wakuMsg, bobPubKey, alicePrivKey, handle_ok, handle_error)); + char *encodedMessage = strdup(result); + + WAKU_CALL(waku_relay_publish(encodedMessage, NULL, 0, handle_ok, handle_error)); // Broadcast via waku relay printf("C\n"); char *messageID = strdup(result); diff --git a/library/c/README.md b/library/c/README.md index d928ade7..6b837afd 100644 --- a/library/c/README.md +++ b/library/c/README.md @@ -766,62 +766,6 @@ A status code. Refer to the [`Status codes`](#status-codes) section for possible If the function is executed succesfully, `onOkCb` will receive the message ID. -### `extern int waku_relay_publish_enc_asymmetric(char* messageJson, char* pubsubTopic, char* publicKey, char* optionalSigningKey, int timeoutMs, WakuCallBack onOkCb, WakuCallBack onErrCb)` - -Optionally sign, -encrypt using asymmetric encryption -and publish a message using Waku Relay. - -**Parameters** - -1. `char* messageJson`: JSON string containing the [Waku Message](https://rfc.vac.dev/spec/14/) as [`JsonMessage`](#jsonmessage-type). -2. `char* pubsubTopic`: pubsub topic on which to publish the message. - If `NULL`, it uses the default pubsub topic. -3. `char* publicKey`: hex encoded public key to be used for encryption. -4. `char* optionalSigningKey`: hex encoded private key to be used to sign the message. -5. `int timeoutMs`: Timeout value in milliseconds to execute the call. - If the function execution takes longer than this value, - the execution will be canceled and an error returned. - Use `0` for no timeout. -6. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -7. `WakuCallBack onErrCb`: callback to be executed if the function fails - -Note: `messageJson.version` is overwritten to `1`. - -**Returns** - -A status code. Refer to the [`Status codes`](#status-codes) section for possible values. - -If the function is executed succesfully, `onOkCb` will receive the message ID. - -### `extern int waku_relay_publish_enc_symmetric(char* messageJson, char* pubsubTopic, char* symmetricKey, char* optionalSigningKey, int timeoutMs, WakuCallBack onOkCb, WakuCallBack onErrCb)` - -Optionally sign, -encrypt using symmetric encryption -and publish a message using Waku Relay. - -**Parameters** - -1. `char* messageJson`: JSON string containing the [Waku Message](https://rfc.vac.dev/spec/14/) as [`JsonMessage`](#jsonmessage-type). -2. `char* pubsubTopic`: pubsub topic on which to publish the message. - If `NULL`, it uses the default pubsub topic. -3. `char* symmetricKey`: hex encoded secret key to be used for encryption. -4. `char* optionalSigningKey`: hex encoded private key to be used to sign the message. -5. `int timeoutMs`: Timeout value in milliseconds to execute the call. - If the function execution takes longer than this value, - the execution will be canceled and an error returned. - Use `0` for no timeout. -6. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -7. `WakuCallBack onErrCb`: callback to be executed if the function fails - -Note: `messageJson.version` is overwritten to `1`. - -**Returns** - -A status code. Refer to the [`Status codes`](#status-codes) section for possible values. - -If the function is executed succesfully, `onOkCb` will receive the message ID. - ### `extern int waku_relay_enough_peers(char* pubsubTopic, WakuCallBack onOkCb, WakuCallBack onErrCb)` Determine if there are enough peers to publish a message on a given pubsub topic. @@ -1154,70 +1098,6 @@ A status code. Refer to the [`Status codes`](#status-codes) section for possible If the function is executed succesfully, `onOkCb` will receive the message ID. -### `extern int waku_lightpush_publish_enc_asymmetric(char* messageJson, char* pubsubTopic, char* peerID, char* publicKey, char* optionalSigningKey, int timeoutMs, WakuCallBack onOkCb, WakuCallBack onErrCb)` - -Optionally sign, -encrypt using asymmetric encryption -and publish a message using Waku Lightpush. - -**Parameters** - -1. `char* messageJson`: JSON string containing the [Waku Message](https://rfc.vac.dev/spec/14/) as [`JsonMessage`](#jsonmessage-type). -2. `char* pubsubTopic`: pubsub topic on which to publish the message. - If `NULL`, it uses the default pubsub topic. -3. `char* peerID`: Peer ID supporting the lightpush protocol. - The peer must be already known. - It must have been added before with [`waku_add_peer`](#extern-char-waku_add_peerchar-address-char-protocolid) - or previously dialed with [`waku_connect_peer`](#extern-char-waku_connect_peerchar-address-int-timeoutms). -4. `char* publicKey`: hex encoded public key to be used for encryption. -5. `char* optionalSigningKey`: hex encoded private key to be used to sign the message. -6. `int timeoutMs`: Timeout value in milliseconds to execute the call. - If the function execution takes longer than this value, - the execution will be canceled and an error returned. - Use `0` for no timeout. -7. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -8. `WakuCallBack onErrCb`: callback to be executed if the function fails - -Note: `messageJson.version` is overwritten to `1`. - -**Returns** - -A status code. Refer to the [`Status codes`](#status-codes) section for possible values. - -If the function is executed succesfully, `onOkCb` will receive the message ID. - -### `extern int waku_lightpush_publish_enc_symmetric(char* messageJson, char* pubsubTopic, char* peerID, char* symmetricKey, char* optionalSigningKey, int timeoutMs, WakuCallBack onOkCb, WakuCallBack onErrCb)` - -Optionally sign, -encrypt using symmetric encryption -and publish a message using Waku Lightpush. - -**Parameters** - -1. `char* messageJson`: JSON string containing the [Waku Message](https://rfc.vac.dev/spec/14/) as [`JsonMessage`](#jsonmessage-type). -2. `char* pubsubTopic`: pubsub topic on which to publish the message. - If `NULL`, it uses the default pubsub topic. -3. `char* peerID`: Peer ID supporting the lightpush protocol. - The peer must be already known. - It must have been added before with [`waku_add_peer`](#extern-char-waku_add_peerchar-address-char-protocolid) - or previously dialed with [`waku_connect_peer`](#extern-char-waku_connect_peerchar-address-int-timeoutms). -4. `char* symmetricKey`: hex encoded secret key to be used for encryption. -5. `char* optionalSigningKey`: hex encoded private key to be used to sign the message. -6. `int timeoutMs`: Timeout value in milliseconds to execute the call. - If the function execution takes longer than this value, - the execution will be canceled and an error returned. - Use `0` for no timeout. -7. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -8. `WakuCallBack onErrCb`: callback to be executed if the function fails - -Note: `messageJson.version` is overwritten to `1`. - -**Returns** - -A status code. Refer to the [`Status codes`](#status-codes) section for possible values. - -If the function is executed succesfully, `onOkCb` will receive the message ID. - ## Waku Store ### `extern int waku_store_query(char* queryJSON, char* peerID, int timeoutMs, WakuCallBack onOkCb, WakuCallBack onErrCb)` @@ -1270,6 +1150,49 @@ A status code. Refer to the [`Status codes`](#status-codes) section for possible If the function is executed succesfully, `onOkCb` will receive a [`StoreResponse`](#storeresponse-type). +## Encrypting messages + +### `extern int waku_encode_symmetric(char* messageJson, char* symmetricKey, char* optionalSigningKey, WakuCallBack onOkCb, WakuCallBack onErrCb)` + +Encrypt a message using symmetric encryption and optionally sign the message + +**Parameters** + +1. `char* messageJson`: JSON string containing the [Waku Message](https://rfc.vac.dev/spec/14/) as [`JsonMessage`](#jsonmessage-type). +2. `char* symmetricKey`: hex encoded secret key to be used for encryption. +3. `char* optionalSigningKey`: hex encoded private key to be used to sign the message. +4. `WakuCallBack onOkCb`: callback to be executed if the function is succesful +5. `WakuCallBack onErrCb`: callback to be executed if the function fails + +Note: `messageJson.version` is overwritten to `1`. + +**Returns** + +A status code. Refer to the [`Status codes`](#status-codes) section for possible values. + +If the function is executed succesfully, `onOkCb` will receive the encrypted waku message which can be broadcasted with relay or lightpush protocol publish functions + +### `extern int waku_encode_asymmetric(char* messageJson, char* publicKey, char* optionalSigningKey, WakuCallBack onOkCb, WakuCallBack onErrCb)` + +Encrypt a message using asymmetric encryption and optionally sign the message + +**Parameters** + +1. `char* messageJson`: JSON string containing the [Waku Message](https://rfc.vac.dev/spec/14/) as [`JsonMessage`](#jsonmessage-type). +2. `char* publicKey`: hex encoded public key to be used for encryption. +3. `char* optionalSigningKey`: hex encoded private key to be used to sign the message. +4. `WakuCallBack onOkCb`: callback to be executed if the function is succesful +5. `WakuCallBack onErrCb`: callback to be executed if the function fails + +Note: `messageJson.version` is overwritten to `1`. + +**Returns** + +A status code. Refer to the [`Status codes`](#status-codes) section for possible values. + +If the function is executed succesfully, `onOkCb` will receive the encrypted waku message which can be broadcasted with relay or lightpush protocol publish functions + + ## Decrypting messages ### `extern int waku_decode_symmetric(char* messageJson, char* symmetricKey, WakuCallBack onOkCb, WakuCallBack onErrCb)` diff --git a/library/c/api.go b/library/c/api.go index 93752eaa..aa311a65 100644 --- a/library/c/api.go +++ b/library/c/api.go @@ -235,21 +235,3 @@ func waku_peers(onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { return library.Peers() }, onOkCb, onErrCb) } - -// Decode a waku message using a 32 bytes symmetric key. The key must be a hex encoded string with "0x" prefix -// -//export waku_decode_symmetric -func waku_decode_symmetric(messageJSON *C.char, symmetricKey *C.char, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { - return singleFnExec(func() (string, error) { - return library.DecodeSymmetric(C.GoString(messageJSON), C.GoString(symmetricKey)) - }, onOkCb, onErrCb) -} - -// Decode a waku message using a secp256k1 private key. The key must be a hex encoded string with "0x" prefix -// -//export waku_decode_asymmetric -func waku_decode_asymmetric(messageJSON *C.char, privateKey *C.char, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { - return singleFnExec(func() (string, error) { - return library.DecodeAsymmetric(C.GoString(messageJSON), C.GoString(privateKey)) - }, onOkCb, onErrCb) -} diff --git a/library/c/api_encoding.go b/library/c/api_encoding.go new file mode 100644 index 00000000..6a9d03d2 --- /dev/null +++ b/library/c/api_encoding.go @@ -0,0 +1,49 @@ +package main + +/* +#include +*/ +import "C" +import "github.com/waku-org/go-waku/library" + +// Decode a waku message using a 32 bytes symmetric key. The key must be a hex encoded string with "0x" prefix +// +//export waku_decode_symmetric +func waku_decode_symmetric(messageJSON *C.char, symmetricKey *C.char, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { + return singleFnExec(func() (string, error) { + return library.DecodeSymmetric(C.GoString(messageJSON), C.GoString(symmetricKey)) + }, onOkCb, onErrCb) +} + +// Decode a waku message using a secp256k1 private key. The key must be a hex encoded string with "0x" prefix +// +//export waku_decode_asymmetric +func waku_decode_asymmetric(messageJSON *C.char, privateKey *C.char, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { + return singleFnExec(func() (string, error) { + return library.DecodeAsymmetric(C.GoString(messageJSON), C.GoString(privateKey)) + }, onOkCb, onErrCb) +} + +// Encrypt a message with a secp256k1 public key. +// publicKey must be a hex string prefixed with "0x" containing a valid secp256k1 public key. +// optionalSigningKey is an optional hex string prefixed with "0x" containing a valid secp256k1 private key for signing the message. Use NULL otherwise +// The message version will be set to 1 +// +//export waku_encode_asymmetric +func waku_encode_asymmetric(messageJSON *C.char, publicKey *C.char, optionalSigningKey *C.char, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { + return singleFnExec(func() (string, error) { + return library.EncodeAsymmetric(C.GoString(messageJSON), C.GoString(publicKey), C.GoString(optionalSigningKey)) + }, onOkCb, onErrCb) +} + +// Encrypt a message with a 32 bytes symmetric key +// symmetricKey must be a hex string prefixed with "0x" containing a 32 bytes symmetric key +// optionalSigningKey is an optional hex string prefixed with "0x" containing a valid secp256k1 private key for signing the message. Use NULL otherwise +// The message version will be set to 1 +// +//export waku_encode_symmetric +func waku_encode_symmetric(messageJSON *C.char, symmetricKey *C.char, optionalSigningKey *C.char, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { + return singleFnExec(func() (string, error) { + return library.EncodeSymmetric(C.GoString(messageJSON), C.GoString(symmetricKey), C.GoString(optionalSigningKey)) + }, onOkCb, onErrCb) +} diff --git a/library/c/api_lightpush.go b/library/c/api_lightpush.go index b7decc72..2243f4f1 100644 --- a/library/c/api_lightpush.go +++ b/library/c/api_lightpush.go @@ -17,31 +17,3 @@ func waku_lightpush_publish(messageJSON *C.char, topic *C.char, peerID *C.char, return library.LightpushPublish(C.GoString(messageJSON), C.GoString(topic), C.GoString(peerID), int(ms)) }, onOkCb, onErrCb) } - -// Publish a message encrypted with a secp256k1 public key using waku lightpush. Use NULL for topic to use the default pubsub topic. -// peerID should contain the ID of a peer supporting the lightpush protocol. Use NULL to automatically select a node -// publicKey must be a hex string prefixed with "0x" containing a valid secp256k1 public key. -// optionalSigningKey is an optional hex string prefixed with "0x" containing a valid secp256k1 private key for signing the message. Use NULL otherwise -// If ms is greater than 0, the broadcast of the message must happen before the timeout -// (in milliseconds) is reached, or an error will be returned. -// -//export waku_lightpush_publish_enc_asymmetric -func waku_lightpush_publish_enc_asymmetric(messageJSON *C.char, topic *C.char, peerID *C.char, publicKey *C.char, optionalSigningKey *C.char, ms C.int, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { - return singleFnExec(func() (string, error) { - return library.LightpushPublishEncodeAsymmetric(C.GoString(messageJSON), C.GoString(topic), C.GoString(peerID), C.GoString(publicKey), C.GoString(optionalSigningKey), int(ms)) - }, onOkCb, onErrCb) -} - -// Publish a message encrypted with a 32 bytes symmetric key using waku relay. Use NULL for topic to use the default pubsub topic. -// peerID should contain the ID of a peer supporting the lightpush protocol. Use NULL to automatically select a node -// symmetricKey must be a hex string prefixed with "0x" containing a 32 bytes symmetric key -// optionalSigningKey is an optional hex string prefixed with "0x" containing a valid secp256k1 private key for signing the message. Use NULL otherwise -// If ms is greater than 0, the broadcast of the message must happen before the timeout -// (in milliseconds) is reached, or an error will be returned. -// -//export waku_lightpush_publish_enc_symmetric -func waku_lightpush_publish_enc_symmetric(messageJSON *C.char, topic *C.char, peerID *C.char, symmetricKey *C.char, optionalSigningKey *C.char, ms C.int, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { - return singleFnExec(func() (string, error) { - return library.LightpushPublishEncodeSymmetric(C.GoString(messageJSON), C.GoString(topic), C.GoString(peerID), C.GoString(symmetricKey), C.GoString(optionalSigningKey), int(ms)) - }, onOkCb, onErrCb) -} diff --git a/library/c/api_relay.go b/library/c/api_relay.go index 2d217322..0f84c3ce 100644 --- a/library/c/api_relay.go +++ b/library/c/api_relay.go @@ -31,32 +31,6 @@ func waku_relay_publish(messageJSON *C.char, topic *C.char, ms C.int, onOkCb C.W }, onOkCb, onErrCb) } -// Publish a message encrypted with a secp256k1 public key using waku relay and returns the message ID. Use NULL for topic to use the default pubsub topic. -// publicKey must be a hex string prefixed with "0x" containing a valid secp256k1 public key. -// optionalSigningKey is an optional hex string prefixed with "0x" containing a valid secp256k1 private key for signing the message. Use NULL otherwise -// If ms is greater than 0, the broadcast of the message must happen before the timeout -// (in milliseconds) is reached, or an error will be returned. -// -//export waku_relay_publish_enc_asymmetric -func waku_relay_publish_enc_asymmetric(messageJSON *C.char, topic *C.char, publicKey *C.char, optionalSigningKey *C.char, ms C.int, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { - return singleFnExec(func() (string, error) { - return library.RelayPublishEncodeAsymmetric(C.GoString(messageJSON), C.GoString(topic), C.GoString(publicKey), C.GoString(optionalSigningKey), int(ms)) - }, onOkCb, onErrCb) -} - -// Publish a message encrypted with a 32 bytes symmetric key using waku relay and returns the message ID. Use NULL for topic to use the default pubsub topic. -// symmetricKey must be a hex string prefixed with "0x" containing a 32 bytes symmetric key -// optionalSigningKey is an optional hex string prefixed with "0x" containing a valid secp256k1 private key for signing the message. Use NULL otherwise -// If ms is greater than 0, the broadcast of the message must happen before the timeout -// (in milliseconds) is reached, or an error will be returned. -// -//export waku_relay_publish_enc_symmetric -func waku_relay_publish_enc_symmetric(messageJSON *C.char, topic *C.char, symmetricKey *C.char, optionalSigningKey *C.char, ms C.int, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { - return singleFnExec(func() (string, error) { - return library.RelayPublishEncodeSymmetric(C.GoString(messageJSON), C.GoString(topic), C.GoString(symmetricKey), C.GoString(optionalSigningKey), int(ms)) - }, onOkCb, onErrCb) -} - // Subscribe to a WakuRelay topic. Set the topic to NULL to subscribe // to the default topic. Returns a json response. When a message is received, // a "message" event is emitted containing the message and pubsub topic in which diff --git a/library/encoding.go b/library/encoding.go index 90318466..eefa54b4 100644 --- a/library/encoding.go +++ b/library/encoding.go @@ -1,9 +1,14 @@ package library import ( + "crypto/ecdsa" + "crypto/elliptic" "encoding/json" + "errors" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/crypto/secp256k1" "github.com/waku-org/go-waku/waku/v2/payload" "github.com/waku-org/go-waku/waku/v2/protocol/pb" "github.com/waku-org/go-waku/waku/v2/utils" @@ -12,14 +17,13 @@ import ( func wakuMessage(messageJSON string) (*pb.WakuMessage, error) { var msg *pb.WakuMessage err := json.Unmarshal([]byte(messageJSON), &msg) - msg.Version = 0 return msg, err } -func wakuMessageSymmetricEncoding(messageJSON string, symmetricKey string, optionalSigningKey string) (*pb.WakuMessage, error) { +func EncodeSymmetric(messageJSON string, symmetricKey string, optionalSigningKey string) (string, error) { msg, err := wakuMessage(messageJSON) if err != nil { - return msg, err + return "", err } payload := payload.Payload{ @@ -31,7 +35,7 @@ func wakuMessageSymmetricEncoding(messageJSON string, symmetricKey string, optio keyBytes, err := utils.DecodeHexString(symmetricKey) if err != nil { - return msg, err + return "", err } payload.Key.SymKey = keyBytes @@ -39,25 +43,33 @@ func wakuMessageSymmetricEncoding(messageJSON string, symmetricKey string, optio if optionalSigningKey != "" { signingKeyBytes, err := utils.DecodeHexString(optionalSigningKey) if err != nil { - return msg, err + return "", err } payload.Key.PrivKey, err = crypto.ToECDSA(signingKeyBytes) if err != nil { - return msg, err + return "", err } } msg.Version = 1 msg.Payload, err = payload.Encode(1) + if err != nil { + return "", err + } - return msg, err + encodedMsg, err := json.Marshal(msg) + if err != nil { + return "", err + } + + return string(encodedMsg), err } -func wakuMessageAsymmetricEncoding(messageJSON string, publicKey string, optionalSigningKey string) (*pb.WakuMessage, error) { +func EncodeAsymmetric(messageJSON string, publicKey string, optionalSigningKey string) (string, error) { msg, err := wakuMessage(messageJSON) if err != nil { - return msg, err + return "", err } payload := payload.Payload{ @@ -69,28 +81,152 @@ func wakuMessageAsymmetricEncoding(messageJSON string, publicKey string, optiona keyBytes, err := utils.DecodeHexString(publicKey) if err != nil { - return msg, err + return "", err } payload.Key.PubKey, err = unmarshalPubkey(keyBytes) if err != nil { - return msg, err + return "", err } if optionalSigningKey != "" { signingKeyBytes, err := utils.DecodeHexString(optionalSigningKey) if err != nil { - return msg, err + return "", err } payload.Key.PrivKey, err = crypto.ToECDSA(signingKeyBytes) if err != nil { - return msg, err + return "", err } } msg.Version = 1 msg.Payload, err = payload.Encode(1) + if err != nil { + return "", err + } - return msg, err + encodedMsg, err := json.Marshal(msg) + if err != nil { + return "", err + } + + return string(encodedMsg), err +} + +func extractPubKeyAndSignature(payload *payload.DecodedPayload) (pubkey string, signature string) { + pkBytes := crypto.FromECDSAPub(payload.PubKey) + if len(pkBytes) != 0 { + pubkey = hexutil.Encode(pkBytes) + } + + if len(payload.Signature) != 0 { + signature = hexutil.Encode(payload.Signature) + } + + return +} + +// DecodeSymmetric decodes a waku message using a 32 bytes symmetric key. The key must be a hex encoded string with "0x" prefix +func DecodeSymmetric(messageJSON string, symmetricKey string) (string, error) { + var msg pb.WakuMessage + err := json.Unmarshal([]byte(messageJSON), &msg) + if err != nil { + return "", err + } + + if msg.Version == 0 { + return marshalJSON(msg.Payload) + } else if msg.Version > 1 { + return "", errors.New("unsupported wakumessage version") + } + + keyInfo := &payload.KeyInfo{ + Kind: payload.Symmetric, + } + + keyInfo.SymKey, err = utils.DecodeHexString(symmetricKey) + if err != nil { + return "", err + } + + payload, err := payload.DecodePayload(&msg, keyInfo) + if err != nil { + return "", err + } + + pubkey, signature := extractPubKeyAndSignature(payload) + + response := struct { + PubKey string `json:"pubkey,omitempty"` + Signature string `json:"signature,omitempty"` + Data []byte `json:"data"` + Padding []byte `json:"padding"` + }{ + PubKey: pubkey, + Signature: signature, + Data: payload.Data, + Padding: payload.Padding, + } + + return marshalJSON(response) +} + +// DecodeAsymmetric decodes a waku message using a secp256k1 private key. The key must be a hex encoded string with "0x" prefix +func DecodeAsymmetric(messageJSON string, privateKey string) (string, error) { + var msg pb.WakuMessage + err := json.Unmarshal([]byte(messageJSON), &msg) + if err != nil { + return "", err + } + + if msg.Version == 0 { + return marshalJSON(msg.Payload) + } else if msg.Version > 1 { + return "", errors.New("unsupported wakumessage version") + } + + keyInfo := &payload.KeyInfo{ + Kind: payload.Asymmetric, + } + + keyBytes, err := utils.DecodeHexString(privateKey) + if err != nil { + return "", err + } + + keyInfo.PrivKey, err = crypto.ToECDSA(keyBytes) + if err != nil { + return "", err + } + + payload, err := payload.DecodePayload(&msg, keyInfo) + if err != nil { + return "", err + } + + pubkey, signature := extractPubKeyAndSignature(payload) + + response := struct { + PubKey string `json:"pubkey,omitempty"` + Signature string `json:"signature,omitempty"` + Data []byte `json:"data"` + Padding []byte `json:"padding"` + }{ + PubKey: pubkey, + Signature: signature, + Data: payload.Data, + Padding: payload.Padding, + } + + return marshalJSON(response) +} + +func unmarshalPubkey(pub []byte) (ecdsa.PublicKey, error) { + x, y := elliptic.Unmarshal(secp256k1.S256(), pub) + if x == nil { + return ecdsa.PublicKey{}, errors.New("invalid public key") + } + return ecdsa.PublicKey{Curve: secp256k1.S256(), X: x, Y: y}, nil } diff --git a/library/lightpush.go b/library/lightpush.go index 3713067e..633e6dc9 100644 --- a/library/lightpush.go +++ b/library/lightpush.go @@ -50,23 +50,3 @@ func LightpushPublish(messageJSON string, topic string, peerID string, ms int) ( return lightpushPublish(msg, getTopic(topic), peerID, ms) } - -// LightpushPublishEncodeAsymmetric is used to publish a WakuMessage in a pubsub topic using Lightpush protocol, and encrypting the message with some public key -func LightpushPublishEncodeAsymmetric(messageJSON string, topic string, peerID string, publicKey string, optionalSigningKey string, ms int) (string, error) { - msg, err := wakuMessageAsymmetricEncoding(messageJSON, publicKey, optionalSigningKey) - if err != nil { - return "", err - } - - return lightpushPublish(msg, getTopic(topic), peerID, ms) -} - -// LightpushPublishEncodeSymmetric is used to publish a WakuMessage in a pubsub topic using Lightpush protocol, and encrypting the message with a symmetric key -func LightpushPublishEncodeSymmetric(messageJSON string, topic string, peerID string, symmetricKey string, optionalSigningKey string, ms int) (string, error) { - msg, err := wakuMessageSymmetricEncoding(messageJSON, symmetricKey, optionalSigningKey) - if err != nil { - return "", err - } - - return lightpushPublish(msg, getTopic(topic), peerID, ms) -} diff --git a/library/mobile/api.go b/library/mobile/api.go index 28eb723c..5e4cacc6 100644 --- a/library/mobile/api.go +++ b/library/mobile/api.go @@ -92,15 +92,3 @@ func Peers() string { peers, err := library.Peers() return prepareJSONResponse(peers, err) } - -// DecodeSymmetric decodes a waku message using a 32 bytes symmetric key. The key must be a hex encoded string with "0x" prefix -func DecodeSymmetric(messageJSON string, symmetricKey string) string { - response, err := library.DecodeSymmetric(messageJSON, symmetricKey) - return prepareJSONResponse(response, err) -} - -// DecodeAsymmetric decodes a waku message using a secp256k1 private key. The key must be a hex encoded string with "0x" prefix -func DecodeAsymmetric(messageJSON string, privateKey string) string { - response, err := library.DecodeAsymmetric(messageJSON, privateKey) - return prepareJSONResponse(response, err) -} diff --git a/library/mobile/api_encoding.go b/library/mobile/api_encoding.go new file mode 100644 index 00000000..bd236f62 --- /dev/null +++ b/library/mobile/api_encoding.go @@ -0,0 +1,29 @@ +package gowaku + +import "github.com/waku-org/go-waku/library" + +// DecodeSymmetric decodes a waku message using a 32 bytes symmetric key. The key must be a hex encoded string with "0x" prefix +func DecodeSymmetric(messageJSON string, symmetricKey string) string { + response, err := library.DecodeSymmetric(messageJSON, symmetricKey) + return prepareJSONResponse(response, err) +} + +// DecodeAsymmetric decodes a waku message using a secp256k1 private key. The key must be a hex encoded string with "0x" prefix +func DecodeAsymmetric(messageJSON string, privateKey string) string { + response, err := library.DecodeAsymmetric(messageJSON, privateKey) + return prepareJSONResponse(response, err) +} + +// EncodeSymmetric encodes a waku message using a 32 bytes symmetric key. A secp256k1 private key can be used to optionally sign the message. +// The keys must be a hex encoded string with "0x" prefix +func EncodeSymmetric(messageJSON string, symmetricKey string, optionalSigningKey string) string { + response, err := library.EncodeSymmetric(messageJSON, symmetricKey, optionalSigningKey) + return prepareJSONResponse(response, err) +} + +// EncodeAsymmetric encodes a waku message using a secp256k1 public key. A secp256k1 private key can be used to optionally sign the message. +// The keys must be a hex encoded string with "0x" prefix +func EncodeAsymmetric(messageJSON string, publicKey string, optionalSigningKey string) string { + response, err := library.EncodeAsymmetric(messageJSON, publicKey, optionalSigningKey) + return prepareJSONResponse(response, err) +} diff --git a/library/mobile/api_lightpush.go b/library/mobile/api_lightpush.go index 4d5d2532..54c5b313 100644 --- a/library/mobile/api_lightpush.go +++ b/library/mobile/api_lightpush.go @@ -7,15 +7,3 @@ func LightpushPublish(messageJSON string, topic string, peerID string, ms int) s response, err := library.LightpushPublish(messageJSON, topic, peerID, ms) return prepareJSONResponse(response, err) } - -// LightpushPublishEncodeAsymmetric is used to publish a WakuMessage in a pubsub topic using Lightpush protocol, and encrypting the message with some public key -func LightpushPublishEncodeAsymmetric(messageJSON string, topic string, peerID string, publicKey string, optionalSigningKey string, ms int) string { - response, err := library.LightpushPublishEncodeAsymmetric(messageJSON, topic, peerID, publicKey, optionalSigningKey, ms) - return prepareJSONResponse(response, err) -} - -// LightpushPublishEncodeSymmetric is used to publish a WakuMessage in a pubsub topic using Lightpush protocol, and encrypting the message with a symmetric key -func LightpushPublishEncodeSymmetric(messageJSON string, topic string, peerID string, symmetricKey string, optionalSigningKey string, ms int) string { - response, err := library.LightpushPublishEncodeSymmetric(messageJSON, topic, peerID, symmetricKey, optionalSigningKey, ms) - return prepareJSONResponse(response, err) -} diff --git a/library/mobile/api_relay.go b/library/mobile/api_relay.go index 2050c7b7..9a127d7f 100644 --- a/library/mobile/api_relay.go +++ b/library/mobile/api_relay.go @@ -16,18 +16,6 @@ func RelayPublish(messageJSON string, topic string, ms int) string { return prepareJSONResponse(hash, err) } -// RelayPublishEncodeAsymmetric publish a message encrypted with a secp256k1 public key using waku relay and returns the message ID -func RelayPublishEncodeAsymmetric(messageJSON string, topic string, publicKey string, optionalSigningKey string, ms int) string { - hash, err := library.RelayPublishEncodeAsymmetric(messageJSON, topic, publicKey, optionalSigningKey, ms) - return prepareJSONResponse(hash, err) -} - -// RelayPublishEncodeSymmetric publishes a message encrypted with a 32 bytes symmetric key using waku relay and returns the message ID -func RelayPublishEncodeSymmetric(messageJSON string, topic string, symmetricKey string, optionalSigningKey string, ms int) string { - hash, err := library.RelayPublishEncodeSymmetric(messageJSON, topic, symmetricKey, optionalSigningKey, ms) - return prepareJSONResponse(hash, err) -} - // RelaySubscribe subscribes to a WakuRelay topic. func RelaySubscribe(topic string) string { err := library.RelaySubscribe(topic) diff --git a/library/node.go b/library/node.go index 74aef974..3d544e9e 100644 --- a/library/node.go +++ b/library/node.go @@ -3,11 +3,9 @@ package library import ( "context" "crypto/ecdsa" - "crypto/elliptic" "crypto/rand" "database/sql" "encoding/hex" - "encoding/json" "errors" "fmt" "net" @@ -17,7 +15,6 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/crypto/secp256k1" "github.com/ethereum/go-ethereum/p2p/enode" pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/libp2p/go-libp2p/core/peer" @@ -26,7 +23,6 @@ import ( "github.com/waku-org/go-waku/waku/persistence" dbutils "github.com/waku-org/go-waku/waku/persistence/utils" "github.com/waku-org/go-waku/waku/v2/node" - "github.com/waku-org/go-waku/waku/v2/payload" "github.com/waku-org/go-waku/waku/v2/peerstore" "github.com/waku-org/go-waku/waku/v2/protocol" "github.com/waku-org/go-waku/waku/v2/protocol/pb" @@ -385,119 +381,3 @@ func Peers() (string, error) { return marshalJSON(peers) } - -func unmarshalPubkey(pub []byte) (ecdsa.PublicKey, error) { - x, y := elliptic.Unmarshal(secp256k1.S256(), pub) - if x == nil { - return ecdsa.PublicKey{}, errors.New("invalid public key") - } - return ecdsa.PublicKey{Curve: secp256k1.S256(), X: x, Y: y}, nil -} - -func extractPubKeyAndSignature(payload *payload.DecodedPayload) (pubkey string, signature string) { - pkBytes := crypto.FromECDSAPub(payload.PubKey) - if len(pkBytes) != 0 { - pubkey = hexutil.Encode(pkBytes) - } - - if len(payload.Signature) != 0 { - signature = hexutil.Encode(payload.Signature) - } - - return -} - -// DecodeSymmetric decodes a waku message using a 32 bytes symmetric key. The key must be a hex encoded string with "0x" prefix -func DecodeSymmetric(messageJSON string, symmetricKey string) (string, error) { - var msg pb.WakuMessage - err := json.Unmarshal([]byte(messageJSON), &msg) - if err != nil { - return "", err - } - - if msg.Version == 0 { - return marshalJSON(msg.Payload) - } else if msg.Version > 1 { - return "", errors.New("unsupported wakumessage version") - } - - keyInfo := &payload.KeyInfo{ - Kind: payload.Symmetric, - } - - keyInfo.SymKey, err = utils.DecodeHexString(symmetricKey) - if err != nil { - return "", err - } - - payload, err := payload.DecodePayload(&msg, keyInfo) - if err != nil { - return "", err - } - - pubkey, signature := extractPubKeyAndSignature(payload) - - response := struct { - PubKey string `json:"pubkey,omitempty"` - Signature string `json:"signature,omitempty"` - Data []byte `json:"data"` - Padding []byte `json:"padding"` - }{ - PubKey: pubkey, - Signature: signature, - Data: payload.Data, - Padding: payload.Padding, - } - - return marshalJSON(response) -} - -// DecodeAsymmetric decodes a waku message using a secp256k1 private key. The key must be a hex encoded string with "0x" prefix -func DecodeAsymmetric(messageJSON string, privateKey string) (string, error) { - var msg pb.WakuMessage - err := json.Unmarshal([]byte(messageJSON), &msg) - if err != nil { - return "", err - } - - if msg.Version == 0 { - return marshalJSON(msg.Payload) - } else if msg.Version > 1 { - return "", errors.New("unsupported wakumessage version") - } - - keyInfo := &payload.KeyInfo{ - Kind: payload.Asymmetric, - } - - keyBytes, err := utils.DecodeHexString(privateKey) - if err != nil { - return "", err - } - - keyInfo.PrivKey, err = crypto.ToECDSA(keyBytes) - if err != nil { - return "", err - } - - payload, err := payload.DecodePayload(&msg, keyInfo) - if err != nil { - return "", err - } - - pubkey, signature := extractPubKeyAndSignature(payload) - - response := struct { - PubKey string `json:"pubkey,omitempty"` - Signature string `json:"signature,omitempty"` - Data []byte `json:"data"` - Padding []byte `json:"padding"` - }{ - PubKey: pubkey, - Signature: signature, - Data: payload.Data, - Padding: payload.Padding, - } - - return marshalJSON(response) -} diff --git a/library/relay.go b/library/relay.go index 54396489..83751443 100644 --- a/library/relay.go +++ b/library/relay.go @@ -58,26 +58,6 @@ func RelayPublish(messageJSON string, topic string, ms int) (string, error) { return relayPublish(msg, getTopic(topic), int(ms)) } -// RelayPublishEncodeAsymmetric publish a message encrypted with a secp256k1 public key using waku relay and returns the message ID -func RelayPublishEncodeAsymmetric(messageJSON string, topic string, publicKey string, optionalSigningKey string, ms int) (string, error) { - msg, err := wakuMessageAsymmetricEncoding(messageJSON, publicKey, optionalSigningKey) - if err != nil { - return "", err - } - - return relayPublish(msg, getTopic(topic), int(ms)) -} - -// RelayPublishEncodeSymmetric publishes a message encrypted with a 32 bytes symmetric key using waku relay and returns the message ID -func RelayPublishEncodeSymmetric(messageJSON string, topic string, symmetricKey string, optionalSigningKey string, ms int) (string, error) { - msg, err := wakuMessageSymmetricEncoding(messageJSON, symmetricKey, optionalSigningKey) - if err != nil { - return "", err - } - - return relayPublish(msg, getTopic(topic), int(ms)) -} - func relaySubscribe(topic string) error { topicToSubscribe := getTopic(topic)