Giter Site home page Giter Site logo

jedisct1 / piknik Goto Github PK

View Code? Open in Web Editor NEW
2.4K 46.0 103.0 10.32 MB

Copy/paste anything over the network.

License: BSD 2-Clause "Simplified" License

Go 92.87% Shell 7.13%
clipboard transit crypto copy paste security security-protocol staging-server

piknik's Introduction

Latest release Build status CodeQL scan

Piknik

Copy/paste anything over the network!

[watch a demo on Asciinema] - [download the source code / binaries]

Piknik

Ever needed a copy/paste clipboard that works over the network?

Piknik seamlessly and securely transfers URLs, code snippets, documents, virtually anything between arbitrary hosts.

No SSH needed, and hosts can sit behind NAT gateways, on different networks.

Fill in the clipboard ("copy") with whatever comes in to the standard input:

$ pkc
clipboard content

Magically retrieve that content from any other host having Piknik installed with the same configuration:

$ pkp
clipboard content

Boom.

Obviously, it can be used to transfer files as well:

$ pkc < kitten.gif
$ pkp > kittencopy.gif
$ tar cvf - *.txt | pkc
$ pkp | tar xvf -

In order to work around firewalls/NAT gatways, the clipboard content transits over TCP via a staging server.

Nothing transits without end-to-end encryption; the server cannot learn much about what the clipboard actually contains.

Data can be shared between different operating systems, including MacOS, Linux and Windows.

Installation

Option 1: use precompiled binaries

Precompiled binaries for MacOS, Linux (i386, x86_64, ARM), Win32, Win64, DragonflyBSD, NetBSD and FreeBSD can be downloaded here: https://github.com/jedisct1/piknik/releases/latest

Option 2 (on MacOS): use Homebrew

$ brew install piknik

Option 3: compile the source code

This project is written in Go.

Go >= 1.11 is required, as well as the following incantation:

$ go build

The piknik executable file should then be available in current path.

Setup

Piknik requires a bunch of keys. Generate them all with

$ piknik -genkeys

This generates random keys (highly recommended).

You will need to copy parts (not all!) of that command's output to a piknik.toml configuration file.

A temporary alternative is to derive the keys from a password. The same password will always generate the same set of keys, on all platforms. In order to do so, add the -password switch:

$ piknik -genkeys -password

The output of the -genkeys command is all you need to build a configuration file.

Only copy the section for servers on the staging server. Only copy the section for clients on the clients.

Is a host gonna act both as a staging server and as a client? Ponder on it before copying the "hybrid" section, but it's there, just in case.

The default location for the configuration file is ~/.piknik.toml. With the exception of Windows, where dot-files are not so common. On that platform, the file is simply called piknik.toml.

Sample configuration file for a staging server:

Listen = "0.0.0.0:8075"         # Edit appropriately
Psk    = "bf82bab384697243fbf616d3428477a563e33268f0f2307dd14e7245dd8c995d"
SignPk = "0c41ca9b0a1b5fe4daae789534e72329a93a352a6ad73d6f1d368d8eff37271c"

Sample configuration file for clients:

Connect   = "127.0.0.1:8075"    # Edit appropriately
Psk       = "bf82bab384697243fbf616d3428477a563e33268f0f2307dd14e7245dd8c995d"
SignPk    = "0c41ca9b0a1b5fe4daae789534e72329a93a352a6ad73d6f1d368d8eff37271c"
SignSk    = "cecf1d92052f7ba87da36ac3e4a745b64ade8f9e908e52b4f7cd41235dfe7481"
EncryptSk = "2f530eb85e59c1977fce726df9f87345206f2a3d40bf91f9e0e9eeec2c59a3e4"

Do not use these, uh? Get your very own keys with the piknik -genkeys command. Edit the Connect and Listen properties to reflect the staging server IP and port. And chmod 600 ~/.piknik.toml might not be a bad idea.

Don't like the default config file location? Use the -config switch.

Usage (staging server)

Run the following command on the staging server (or use runit, openrc, systemd, whatever to run it as a background service):

$ piknik -server

The staging server has to be publicly accessible. At the very least, it must be reachable by the clients over TCP with the port you specify in the configuration.

Commands without a valid API key (present in the client configuration file) will be rejected by the server.

Usage (clients)

$ piknik -copy

Copy the standard input to the clipboard.

$ piknik -paste

Retrieve the content of the clipboard and spit it to the standard output. -paste is actually a no-op. This is the default action if -copy was not specified.

$ piknik -move

Retrieve the content of the clipboard, spit it to the standard output and clear the clipboard. Not necessarily in this order. Only one lucky client will have the privilege to see the content.

That's it.

Feed it anything. Text, binary data, whatever. As long as it fits in memory.

Suggested shell aliases

Wait. Where are the pkc and pkp commands mentioned earlier?

Sample shell aliases:

# pko <content> : copy <content> to the clipboard
pko() {
    echo "$*" | piknik -copy
}

# pkf <file> : copy the content of <file> to the clipboard
pkf() {
    piknik -copy < $1
}

# pkc : read the content to copy to the clipboard from STDIN
alias pkc='piknik -copy'

# pkp : paste the clipboard content
alias pkp='piknik -paste'

# pkm : move the clipboard content
alias pkm='piknik -move'

# pkz : delete the clipboard content
alias pkz='piknik -copy < /dev/null'

# pkfr [<dir>] : send a whole directory to the clipboard, as a tar archive
pkfr() {
    tar czpvf - ${1:-.} | piknik -copy
}

# pkpr : extract clipboard content sent using the pkfr command
alias pkpr='piknik -paste | tar xzpvf -'

Piknik integration in third-party packages

Use cases

Use it to:

  • Securely send passwords, API keys, URLs from one host to another
  • Share a clipboard with your teammates (which can be a lot of fun)
  • Copy data from/to isolated VMs, without the VMWare tools or shared volumes (great for unsupported operating systems and malware sandboxes)
  • Copy files from/to a Windows machine, without Samba or SSH
  • Transfer data between hosts sitting behind firewalls/NAT gateways
  • Easily copy configuration files to multiple hosts
  • Start a slow download at the office, retrieve it later at home
  • Quickly backup a file to the cloud before messing with it
  • ...and more!

Protocol

Common definitions:

k: API key
ek: 256-bit symmetric encryption key
ekid: encryption key id encoded as a 64-bit little endian integer
m: plaintext
ct: XChaCha20 ek,n (m)
Hk,s: BLAKE2b(domain="SK", key=k, salt=s, size=32)
Len(x): x encoded as a 64-bit little endian unsigned integer
n: random 192-bit nonce
r: random 256-bit client nonce
r': random 256-bit server nonce
ts: Unix timestamp as a 64-bit little endian integer
Sig: Ed25519
v: 6

Copy:

-> v || r || h0
h0 := Hk,0(v || r)

<- v || r' || h1
h1 := Hk,1(v || r' || h0)

-> 'S' || h2 || Len(ekid || n || ct) || ts || s || ekid || n || ct
s := Sig(ekid || n || ct)
h2 := Hk,2(h1 || 'S' || ts || s)

<- Hk,3(h2)

Move/Paste:

Move:  opcode := 'M'
Paste: opcode := 'G'

-> v || r || h0
h0 := Hk,0(v || r)

<- v || r' || h1
h1 := Hk,1(v || r' || H0)

-> opcode || h2
h2 := Hk,2(h1 || opcode)

<- Hk,3(h2 || ts || s) || Len(ekid || n || ct) || ts || s || ekid || n || ct
s := Sig(ekid || n || ct)

License

ISC.

Credits

Piknik diagram by EasyPi.

piknik's People

Contributors

deckar01 avatar dmerrick avatar jedisct1 avatar jonasberge avatar muesli avatar prohtmeyhet avatar testwill avatar vshih avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

piknik's Issues

Multiple clipboard (slot) feature?

Hello,

I was wondering if there are any plans for multiple clipboard feature, e.g: setting a slot for a copy, which defaults to zero for backward compatibility.

That way I believe It'll be more usable, at least will be for me.

Thanks for maintaining such a great app (and DNSCrypt, too!)

Cheers,

piknik on mobile (iOS, Android)?

Now that I'm addicted to piknik: is there any chance of getting this for mobile (Android, and in particular iOS)? This would be a great way to transport passwords/passphrases etc. without cloud usage.

Consider this a feature request. ๐Ÿ˜ƒ

IMO the UI could be very "primitive": a -copy would literally copy from clipboard and a -paste to clipboard.

piknik not work in Ubuntu keyboard shortcuts

Hi,
Thank you for create this useful tool.

But I want to use this which one shortcuts in Ubuntu 18.04
I drop commands below in the shortcuts settings.

sh -c " sleep 0.5 && xdotool key Control_L+Insert && xclip -sel c -o > /tmp/t && xclip -sel c -o | piknik -copy"

2021-09-09_19-32

By press super+C with select some text in chrome, I can find the xclip -sel c -o > /tmp/t put the selection to the file. But piknik seems not be trigger.

Any ideas?

Does piknik -genkeys omit something for the server?

Thank you for creating piknik: this is a grand idea!

piknik 0.3 precompiles binaries from releases/. I run

piknik -genkeys

and copy the section marked for a server to the server, and the section marked client to a client. If I then launch the server (piknik -server) and use pkc on the client, the client says:

echo hello | pkc
2016/07/23 16:37:06 EOF

pkp
2016/07/23 16:37:22 unexpected EOF

If, however, I use the "hybrid configuration" from -genkeys on the server, it works.

The following contains my ~/.piknik.toml on the server (no worries: I'll throw this away later :-)

# Hybrid configuration

#Connect   = "192.168.1.81:8075"    # Edit appropriately
#Listen    = "0.0.0.0:8075" # Edit appropriately
#Psk       = "0f51549a6c18c18a48695939f75e231de755543e18d08c2b5698d74515eb40c1"
#SignPk    = "670ab3a47bc63ca4c55f0e507fab249576ec5fc2ab9af4ddfdad96a417feb932"
#SignSk    = "b6dea70cdd36b28b2dbe9bfb24844fa1a7e534f30af7231c6dbdd0c40b5a3f64"
#EncryptSk = "b8a1a03b73906c0afdc7036c902d604fecd3e866cac05cb55e649a1d6cc33343"

# Configuration for a server

Listen = "0.0.0.0:8075" # Edit appropriately
Psk    = "0f51549a6c18c18a48695939f75e231de755543e18d08c2b5698d74515eb40c1"
SignPk = "670ab3a47bc63ca4c55f0e507fab249576ec5fc2ab9af4ddfdad96a417feb932"

Leaving just bottom part: fails
Using just top part: succeeds

Consider 5-digit default port

Windows aggressively reserves 4-digit ports unless you use a command like:

netsh int ipv4 add excludedportrange protocol=tcp startport=8075 numberofports=1

And, this command only works if the port hasn't already been reserved (so it's best ran after startup).

Changing the default port to something like 18075 would prevent Windows users from running into unexpected difficulty hosting or connecting with piknik.

Can this error message be improved on?

I had a 0.4 piknik -server running and ran piknik to make sure the version (0.5) I downloaded matched my architecture before copying over the binary:

piknik
panic: runtime error: index out of range

goroutine 1 [running]:
panic(0x8201960, 0x1850a010)
    /home/travis/.gimme/versions/go1.6.3.linux.amd64/src/runtime/panic.go:481 +0x326
main.(*Client).pasteOperation(0x18531cc0, 0x1854e251, 0x20, 0x20, 0x0)
    /home/travis/gopath/src/github.com/jedisct1/piknik/client.go:100 +0x143f
main.RunClient(0x8237100, 0xe, 0x1850e410, 0xc, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
    /home/travis/gopath/src/github.com/jedisct1/piknik/client.go:170 +0xd68
main.main()
    /home/travis/gopath/src/github.com/jedisct1/piknik/piknik.go:167 +0xf15

It then dawned on me that this is probably due to a running server ...

Hex Error

Isn't working for me, getting an error on the client while I'm trying to copy something:

~/linux-x86_64$ echo "test_copy" | /usr/local/bin/piknik -copy
encoding/hex: invalid byte: U+005E '^'

~/linux-x86_64$ /usr/local/bin/piknik -version
Piknik v0.10.1 (protocol version: 6)

Ubuntu 21.04

is a piknik server running on that host?

hello! I come from china ,and have a local MAC and a remote Linux server.
1 on my MAC,
run: brew install piknik,
run : piknik-genkeys,
copy client part to ~ /.piknik.toml such as

Configuration for a client

Connect = "127.0.0.1:8075" # Edit appropriately
Psk = "7fd5aff6e7b473d3b0d8699923b7133261afff2b635cd20e9624b79eb0a93479"
SignPk = "f2076dc18a1c24e50d85b95c558d5800079e2c56ac4099bd84c5d26a6933129a"
SignSk = "a1eee78ef0c77abbcc255376f275afbbc680138d57936122323842e0a6e62073"
EncryptSk = "556ad73c49bc73cd06a3faf18be65ac85f902ed34522438cb7be0c9d73b97c76"


Configuration for a server

Listen = "0.0.0.0:8075" # Edit appropriately
Psk = "7fd5aff6e7b473d3b0d8699923b7133261afff2b635cd20e9624b79eb0a93479"
SignPk = "f2076dc18a1c24e50d85b95c558d5800079e2c56ac4099bd84c5d26a6933129a"

2 on a Linux server,
run :
wget https://github.com/jedisct1/piknik/releases/download/0.9.1/piknik-linux_x86_64-0.9.1.tar.gz,
put the server configuration part on linuxserver: ~ /. piknil. toml,
run : piknik -server

3 but i get an error:
"is a piknik server running on that host?"!

4 My English is not very good and I don't quite understand the confitgure of READ.md between mac and linux or windows.

5 May you release piknik for Android ?i hope that .

[protocol] ekid should be authenticated

I am currently learning Tamarin, and as a case study I was looking at the Piknik protocol. There's seems to be a small gap in the security of the protocol.

Consider the very rare case that a network has a compromised encryptKey and a malicious server.

If a client receives a clipboard state from the server, then it should be authenticated by another (or the same) client. However, this is not the case, because the encryptKeyID corresponding to a ciphertext in the clipboard is malleable by the server. This way the server can force decryption under an old key (if the client hasn't updated its key yet), resulting in a garbled plaintext.

This is fixable by having the clients also sign the ekid, during a Copy operation. I.e. s := Sig(n || ct, ekid).

Obviously this is a very rare case, and will probably not really happen in practice.


Tamarin file: https://gist.github.com/dsprenkels/0e858ea6fc1b8500571f3b91f8badd2d (disclaimer: very ugly non-public amateur code)

EOF every time i use.

Hi !

I get EOF every time i use it.

The server is Debian 9.3 (4.9)
Client is Windows 10/Arch Linux (4.14)

Any idea ? thanks

Large file transfer hangs

Server: Xubuntu 17.10 (i7-860 16GB)
Client: MacOS 10.12.6 (i7-4750 8GB)
Piknik: v0.9.1 (protocol version: 5)

Copying a 5.3GB file from the client spawns a piknik process on the client that consumes about 10GB and hangs. The server memory usage seems to only grow the expected ~5.3GB. Copying on the server produces the content that was previously on the clipboard (not the 5.3GB file).

streaming paste to stdout

Hi! I'm trying to use piknik in tandem with wl-clipboard to be able to sycn my clipboard between my laptop and my linux phone. Everything works smooth and dandy, but piknik -paste does not seem to have a way to stream the data to stdout (so I can pipe them to wl-copy). Am I missing something obvious or is this a missing feature you would like to consider?

improve error message

Hi Frank,

Could you improve this error message ?
Error is normal, due to server is not running.

$ piknik
2016/07/22 14:46:12 dial tcp 127.0.0.1:8075: getsockopt: connection refused
panic: dial tcp 127.0.0.1:8075: getsockopt: connection refused

goroutine 1 [running]:
log.Panic(0xc8200a58f0, 0x1, 0x1)
/usr/local/go/src/log/log.go:320 +0xc1
main.ClientMain(0xc82000e280, 0xe, 0x6511c0, 0xc, 0x0, 0xc82000e460, 0x20, 0x20, 0xc82000b070, 0x8, ...)
/home/sim/go/src/github.com/jedisct1/piknik/client.go:156 +0x156
main.main()
/home/sim/go/src/github.com/jedisct1/piknik/piknik.go:139 +0xf58

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1696 +0x1

Thanks,

Client/Server share psk/signpsk?

Hi Frank,

I'm taking a look at your other wonderful creations and seeing all the great stuff you create - THANK YOU.

So I think I'm reading the README correctly but maybe something is missing in it.

server:
piknik -genkeys
copy to .piknik.toml

client:
piknik -genkeys
copy to .piknik.toml
edit the connect IP address

start the server:
piknik -server

Attempt to retrieve something on client:
piknik
But I see this instead:
The server rejected the connection - Check that it is running the same Piknik version or retry later.

Do any parts of the keys need to be shared among the clients/servers? Reviewing the samples, I see both client and server share the same psk and signpsk. This all makes sense.

Would you be open to a PR, provided what I said above is accurate, to explain this in a little more detail?

Thanks!

Share a clipboard

On the README.md you mention:

Share a clipboard with your teammates (which can be a lot of fun)

How is that accomplished? Thanks!

piknik: command not found

I'm running a Linux ip-172-31-10-169 4.4.0-1044-aws #53-Ubuntu SMP Mon Dec 11 13:49:57 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux and install pikinik using
go get github.com/jedisct1/piknik and also exported the path.
But still I am getting a issuepiknik: command not found. How do I resolve it

A big thanks and several small things.

Excellent and most practical for Host/Guest virtual machine communication. Worked out of the box with one minor (Windows server side tweak). On Windows piknik.toml is not a dot file and lives in %USERPROFILE%\piknik.toml.

So: Many thanks.

2 questions:
I'm not a Go guy - what is best way way to install the built from source binaries on Ubuntu Linux and Windows 10? Just copy the binary to a suitable folder?
And might it be possible to have the Windows version of the server listen out for clipboard change notifications? Then a standard File >> Copy would (optionally) automatically get broadcast to all peers? https://learn.microsoft.com/en-us/windows/win32/dataxchg/wm-clipboardupdate [edit] A quick search shows this to be non-trivial.

open /root/.piknik.toml: no such file or directory

After installation I got a error when I tried to run the executable ./piknik.

Following is entire installation commands on docker ubuntu 16.04.

# install golang 

apt install software-properties-common
add-apt-repository ppa:longsleep/golang-backports -y 
apt-get update
apt-get install golang-go -y 

# install gvm, use gvm 

apt update ; apt-get install curl git mercurial make binutils bison gcc build-essential
bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
source ${HOME}/.gvm/scripts/gvm

gvm install go1.12.9
gvm use go1.12.9 

# install piknik

git clone https://github.com/jedisct1/piknik.git
cd piknik
go build

Following is the error message.

# ./piknik
open /root/.piknik.toml: no such file or directory

stderr for diagnostics / status?

piknik -copy, -zero, etc. print a "success" message on stdout:

echo hello | pkc 2> /dev/null
Sent

Wouldn't these be more suited for stderr?

Password input printed to stdout

Hey there!

Currently, when using the -genkeys -password option, the password input is printed to stdout:

$ piknik -genkeys -password
Password> MY_PASSWORD_IN_PLAIN_TEXT

I think it would be nicer to supress the output, as unix CLIs commonly do for password inputs.

Windows copy hangs

Thank you for creating piknik!

I'm having an issue with "piknik.exe -copy" on Windows computers (W7 / XP). Copying of files is working fine but copying of Windows clipboard just hangs. Is there any prerequisites for piknik to work on Windows?
I'm using version 0.9.1 precompiled binaries.
Tried it on three computers with the same issue.
Could you please look into this.
Thanks

Here is what I see http://i.is.cc/m38KTaW.gif

proxy support

I would love to see that this great app got proxy support of some sort. It would make it easier to use from corp networks where you are usually behind some sort of proxy.

EOF issue with master

Hi Frank,

After having matching Psk and SignPk in my client and server, I also get EOF as a response.

Both client and server are running trunk/master of piknik and both are OpenBSD -current.

client:

# Configuration for a client

Connect   = "192.168.40.10:8075"    # Edit appropriately
Psk    = "54dd744595c95b4d6322d63b2fc36d1d733cd35b812c58632649aa6db82853fd"
SignPk = "ac79a831d64ffbcf0be39f99cf10c472c576cca268f135885f5a3eacac231990"
SignSk    = "d2be27ec196a376af003cf5821e7cc12d7e99ed7eb394e8095b8bc40ce89d017"
EncryptSk = "fe94512220a17de70ee658cfcf0c1fd93621cdc316d7a08eeb292cd749641ace"

server:

# Configuration for a server

Listen = "0.0.0.0:8075" # Edit appropriately
Psk    = "54dd744595c95b4d6322d63b2fc36d1d733cd35b812c58632649aa6db82853fd"
SignPk = "ac79a831d64ffbcf0be39f99cf10c472c576cca268f135885f5a3eacac231990"

server:

$ piknik -server &
[1] 58833

client:

$ piknik
The clipboard might be empty

client sending:

$ piknik -copy < foo
EOF

In this case foo is a zero byte file, but happens to any file regardless of size.

$ go version
go version go1.12.7 openbsd/amd64
$ sysctl kern.version
kern.version=OpenBSD 6.5-current (GENERIC.MP) #144: Fri Jul 26 09:23:09 MDT 2019
    [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP

When using a shared password, I was able to send files. I can show the output of that, if needed.

Release 0.9.1 seg faults on both OpenBSD machines so I can't try with that build.
https://github.com/jedisct1/piknik/releases/tag/0.9.1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.