func encryptSymmsg(password string, msg []byte) string { symmsg := new(Symmsg) rounds := 42 copy(symmsg.symalg[:], "SP") copy(symmsg.kdfalg[:], "BK") symmsg.kdfrounds = uint32(rounds) rand.Read(symmsg.salt[:]) rand.Read(symmsg.nonce[:]) key, _ := bcrypt_pbkdf.Key([]byte(password), symmsg.salt[:], rounds, 32) var symkey [32]byte copy(symkey[:], key) enc := secretbox.Seal(nil, msg, &symmsg.nonce, &symkey) copy(symmsg.tag[:], enc[0:16]) enc = enc[16:] var buf bytes.Buffer buf.Write(symmsg.symalg[:]) buf.Write(symmsg.kdfalg[:]) binary.Write(&buf, binary.BigEndian, symmsg.kdfrounds) buf.Write(symmsg.salt[:]) buf.Write(symmsg.nonce[:]) buf.Write(symmsg.tag[:]) hdr := base64.StdEncoding.EncodeToString(buf.Bytes()) hdr = wraplines(hdr) str := base64.StdEncoding.EncodeToString(enc) str = wraplines(str) return "-----BEGIN REOP ENCRYPTED MESSAGE-----\n" + "ident:<symmetric>\n" + hdr + "\n" + "-----BEGIN REOP ENCRYPTED MESSAGE DATA-----\n" + str + "\n" + "-----END REOP ENCRYPTED MESSAGE-----\n" }
func decryptMsg(seckeyfile, pubkeyfile string, ciphertext []byte) string { var ident string var msglen int var msgraw []byte var hdr []byte if len(ciphertext) >= 6 && string(ciphertext[0:4]) == "RBF\u0000" { algorithm := string(ciphertext[4:6]) switch algorithm { case "SP": if len(ciphertext) <= 68 { fmt.Fprintln(os.Stderr, "Badly formatted message!") os.Exit(1) } hdr = ciphertext[4:68] ciphertext = ciphertext[68:] break default: nyi("Binary decryption") } identlen := readUint32(ciphertext[0:4]) ident = string(ciphertext[4 : 4+identlen]) msgraw = ciphertext[4+identlen:] } else { // in the C, these are pointers to halfway through ciphertext // that's not fun var begin int var end int var beginmsg = []byte("-----BEGIN REOP ENCRYPTED MESSAGE-----\n") var begindata = []byte("-----BEGIN REOP ENCRYPTED MESSAGE DATA-----\n") var endmsg = []byte("-----END REOP ENCRYPTED MESSAGE-----\n") if bytes.Index(ciphertext, beginmsg) != 0 { fmt.Fprintln(os.Stderr, "Badly formatted message!") os.Exit(1) } begin, ident = readIdent(ciphertext[len(beginmsg):]) begin = begin + len(beginmsg) end = begin + bytes.Index(ciphertext[begin:], begindata) if end == -1 { fmt.Fprintln(os.Stderr, "Badly formatted message!") os.Exit(1) } // this was nasty to figure out; it's a sizeof() a union with several structs hdr = b64pton(ciphertext[begin:end], 128) begin = end + len(begindata) end = begin + bytes.Index(ciphertext[begin:], endmsg) if end == -1 { fmt.Fprintln(os.Stderr, "Badly formatted message!") os.Exit(1) } msglen = (end - begin - 1) / 4 * 3 msgraw = b64pton(ciphertext[begin:end], msglen) for msgraw[len(msgraw)-1] == 0 { msgraw = msgraw[:len(msgraw)-1] } } algorithm := string(hdr[:2]) switch algorithm { case "SP": msg := new(Symmsg) copy(msg.symalg[:], hdr[0:2]) copy(msg.kdfalg[:], hdr[2:4]) msg.kdfrounds = readUint32(hdr[4:8]) copy(msg.salt[:], hdr[8:24]) copy(msg.nonce[:], hdr[24:48]) copy(msg.tag[:], hdr[48:64]) if string(msg.kdfalg[:]) != "BK" { fmt.Fprintln(os.Stderr, "unsupported KDF") os.Exit(1) } password := os.Getenv("REOP_PASSPHRASE") if password == "" { fmt.Print("passphrase: ") password = string(gopass.GetPasswd()) } key, _ := bcrypt_pbkdf.Key([]byte(password), msg.salt[:], int(msg.kdfrounds), 32) var symkey [32]byte copy(symkey[:], key) raw := append(msg.tag[:], msgraw...) var dec []byte dec, worked := secretbox.Open(nil, raw, &msg.nonce, &symkey) if !worked { fmt.Fprintln(os.Stderr, "Decryption failed!") os.Exit(1) } return string(dec) case "eC": //seckey := readSeckey(seckeyfile) //pubkey := readPubkey(pubkeyfile) nyi("Public-key decryption with identity " + ident) case "CS": nyi("Old public-key algorithm") case "eS": nyi("Old symmetric algorithm") } return "" }