{"_id":"react-fumbler","_rev":"89-6c8d4dd9f762b6d348c07a0a5d344095","name":"react-fumbler","dist-tags":{"latest":"2.0.0"},"versions":{"1.1.19":{"name":"react-fumbler","version":"1.1.19","description":"react-keybox-firestore, sorting logic for pouchdb local storage key storage for on-device, end-to-end-encryption","main":"src/index.js","keywords":["firebase","firestore","firebase-firestore","pouchdb","react","rsa","encryption","e2e","end-to-end","2048","modulo","crypto","privacy","js-crypto-rsa"],"repository":{"type":"git","url":"git+https://github.com/nickcarducci/react-fumbler.git"},"sideEffects":false,"license":"UNLICENSED","author":{"name":"Nick Carducci nick@carducci.sh"},"bugs":{"url":"https://github.com/nickcarducci/react-fumbler"},"gitHead":"3461066dddeda4309585eeff58a95d393ae6d479","homepage":"https://github.com/nickcarducci/react-fumbler#readme","_id":"react-fumbler@1.1.19","_nodeVersion":"14.15.1","_npmVersion":"7.19.1","dist":{"integrity":"sha512-PwQ4quAfc+QkQWomCPOTB24lr8s5v4Sz5riIliCZYTaiCUSfG75cpMPz+l5at/4erJOq8GsDGS6Sq/d8KUUqCw==","shasum":"431bcc4fe0dcb54eac24f1b70aa6e7d4250eb0c8","tarball":"https://registry.npmjs.org/react-fumbler/-/react-fumbler-1.1.19.tgz","fileCount":4,"unpackedSize":71527,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhmHkVCRA9TVsSAnZWagAAC0YP/jyxunjInJRemgBFEZhO\nXOrc5j1aWoBNjXfGDx2c+KL9fOVaDVOc//My1HHYYmnVxK5/sePr1wREr/ib\nYZXeHRm9/CIwAPo0L3KXsZWXZnrgNsGmM4Qx4KZx2MG9vgu+4FjNvr9Z0air\n9StiJnYm3hwVCqtqmad4QsxdeKh4+AAraVjqsIvCkGT98OqFrCA5UPWpVUka\nDspBM3EtmgRntqDFOG+Dr2lQ1sDROfyjY6D8ahTLNcDwzMWXnWyuusu4mTag\nWvELAsPV9XzkFbmLgAWwjqUUS1hQn/lQoHvCxSJ+0LntZNGsVK1+EWrFeQhv\nwlx9iPtj4/jpibQcigc8Reh5fiatK8X5qG8b5kKDpbFTXOvaENNvZFFZB7B5\nkIpgkDd9KdWJLmXJib0gCQ5VaJK9Hwi3su7eocZsvMWKcfOtBZ9Hz0EeSZkE\nvpyCDXyvpZMma60it0pHYxEsy5GLdQpe9/iM3wwVhuDZ+LYbAX1jYlS2JRJ/\naU5qwF9ZJBYIqH7XpenGUolC6kEsDHWESgVgyXEScjqniopznFBa4NQZU6fN\nZkkOIJKkfos50Bv6Fz3vHV4cZA0BgR/YZO8YsaR64QS0tvAiauP1uNnRo0mV\n7XJbClcO8E6nMOhC/OvD1zq5MPgl1xYEwqF96BH7QmOH/bmbPP1/N5E36qRD\nlvde\r\n=PlG+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID/6kuQgFR74VvhmogChSvwlLsE/Wxpp1KW3VH1VEK+iAiAG+x8KafR6Ah7ZuRn5UOAmaqJI8Qw8XCaEbXwBSoV/xg=="}]},"_npmUser":{"name":"nickcarducci","email":"nick@carducci.sh"},"directories":{},"maintainers":[{"name":"nickcarducci","email":"nick@carducci.sh"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/react-fumbler_1.1.19_1637382421084_0.38548777612064167"},"_hasShrinkwrap":false},"2.0.0":{"name":"react-fumbler","version":"2.0.0","description":"react-keybox-firestore, sorting logic for pouchdb local storage key storage for on-device, end-to-end-encryption","main":"src/index.js","keywords":["firebase","firestore","firebase-firestore","pouchdb","react","rsa","encryption","e2e","end-to-end","2048","modulo","crypto","privacy","js-crypto-rsa"],"repository":{"type":"git","url":"git+https://github.com/nickcarducci/react-fumbler.git"},"sideEffects":false,"license":"UNLICENSED","author":{"name":"Nick Carducci nmcarducci@gmail.com"},"bugs":{"url":"https://github.com/nickcarducci/react-fumbler"},"gitHead":"3461066dddeda4309585eeff58a95d393ae6d479","homepage":"https://github.com/nickcarducci/react-fumbler#readme","_id":"react-fumbler@2.0.0","_nodeVersion":"16.17.0","_npmVersion":"8.15.0","dist":{"integrity":"sha512-Gg1LDmtazmIlYURkDczYSwwtoSLdS0teYmjLQ+rQOekr4jmifO5VTT/a8nebya8SDI8u2K0ysBZEVJ0ysO50CA==","shasum":"8a1d3a6bc02d6903327cd7a249593e420070e6c4","tarball":"https://registry.npmjs.org/react-fumbler/-/react-fumbler-2.0.0.tgz","fileCount":4,"unpackedSize":72546,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDE/t8EpKoeLSw3BW+xGdA2M5CvSU3gnnREVaTV8CtVsgIhAOvUr7j3HoyOj1rjZLLAGkhwJ5ITuRhMT4f+vMvqhmsg"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjqc2gACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoLUg/+ILPWbSOJozUdTBeuMQF3CVrvJXcCy8jUKq0akahQ6uOTuSql\r\nhHWGkAiqXCViWc/YV8PXPeVorjYw2jTqVFhwl3DKGDZt9WLTIrtgBjZ7M7eb\r\nJIJYq+onnI+k3YkXqNjYhrDxkGKUd9cIEhjmvOfRh5IHvl4Tn2EtJV9AD0LC\r\nPjAoDlalOTOvB6VG52zleBVmzvLTM4kXhXHEfaNT1aSmK5/xhlyeSgTUHcEY\r\njG4KInACxXJlTEaTBmQCD1GgiPyiPKUFQKfFnj2QyQeiaUZSrJd5UgSpN7hI\r\n9GY9xvq8XRZXhIdb/tZmrgLc4F5YXaECeZ8o+NkQxfE8/FPtjQXx7r+h0fm8\r\nogfJEU1vCJ1tvouxna8SEYIxSJ3kHL2NoomssIh5t+p9X8hwAiAHywvdIq/D\r\nwekxnJKZ+YLnnsMO1NcR+M56rDXhcSdDeBYgcqOKcwhyQQOtF1VixKFtzhbZ\r\nwdUId9HXqCYm3MeO15ZyVe35c6Ob+G7qpsbd5t0Gx1Yu4DdGt4VhzeDzIVTj\r\nO5v6MgM4fUX2u0IqGJWsc93r5Opr9sJzKDms0SfNcLDpoU0VaAQxQljksY88\r\n5kb8qj/1hZkACMRifF0e5GPkMk+3cMw0O6QCA9Egkfg0EkBguCn/lqP8D1DQ\r\nprsm4lbt85ODnxzEVlWCN1e16z//KVsDiFY=\r\n=ywO4\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"nickcarducci","email":"nick@carducci.sh"},"directories":{},"maintainers":[{"name":"nickcarducci","email":"nick@carducci.sh"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/react-fumbler_2.0.0_1672072608771_0.3972992093477825"},"_hasShrinkwrap":false}},"time":{"created":"2021-07-30T16:17:41.112Z","1.0.0":"2021-07-30T16:17:41.305Z","modified":"2022-12-26T16:36:49.044Z","1.0.1":"2021-07-30T17:18:54.697Z","1.0.2":"2021-07-30T17:26:00.186Z","1.0.3":"2021-07-30T18:50:39.761Z","1.0.4":"2021-07-30T18:56:32.567Z","1.0.5":"2021-07-30T19:25:15.450Z","1.0.6":"2021-07-30T22:58:11.683Z","1.0.7":"2021-08-01T23:15:21.838Z","1.0.8":"2021-08-02T01:23:10.449Z","1.0.9":"2021-08-02T14:30:16.107Z","1.1.0":"2021-08-02T14:39:16.926Z","1.1.1":"2021-08-02T14:46:16.349Z","1.1.2":"2021-08-02T17:44:57.327Z","1.1.3":"2021-08-03T08:48:38.308Z","1.1.4":"2021-08-03T09:13:55.826Z","1.1.5":"2021-08-03T10:29:45.484Z","1.1.6":"2021-08-03T10:41:46.083Z","1.1.7":"2021-08-05T00:24:23.310Z","1.1.8":"2021-08-05T20:05:20.794Z","1.1.9":"2021-08-08T21:25:41.499Z","1.1.10":"2021-08-09T10:31:48.645Z","1.1.11":"2021-08-09T10:33:43.016Z","1.1.12":"2021-08-09T11:05:20.390Z","1.1.13":"2021-08-09T11:36:36.203Z","1.1.14":"2021-08-09T11:48:10.810Z","1.1.15":"2021-08-09T18:45:40.802Z","1.1.16":"2021-08-10T12:57:42.596Z","1.1.17":"2021-08-11T19:18:50.002Z","1.1.18":"2021-09-13T07:24:57.017Z","1.1.19":"2021-11-20T04:27:01.265Z","2.0.0":"2022-12-26T16:36:48.959Z"},"maintainers":[{"name":"nickcarducci","email":"nick@carducci.sh"}],"description":"react-keybox-firestore, sorting logic for pouchdb local storage key storage for on-device, end-to-end-encryption","homepage":"https://github.com/nickcarducci/react-fumbler#readme","keywords":["firebase","firestore","firebase-firestore","pouchdb","react","rsa","encryption","e2e","end-to-end","2048","modulo","crypto","privacy","js-crypto-rsa"],"repository":{"type":"git","url":"git+https://github.com/nickcarducci/react-fumbler.git"},"author":{"name":"Nick Carducci nmcarducci@gmail.com"},"bugs":{"url":"https://github.com/nickcarducci/react-fumbler"},"license":"UNLICENSED","readme":"#Thanks for checking out, something's amiss, hold on... this is new\n\nJust put what is in path(__dirname, src, index.js) in for now, as I figure out\nbabel config\n# Fumbler, your RSA encryption suite for firebase-firestore (in React)!\n\n![alt text](https://www.dropbox.com/s/spk5p2uu7xs7vj3/fumbler%20%281%29.png?dl=0 \"react-fumbler key-loop(array) & O.K.!\")\n\nThe reliability of this relies on cors so that no private key-modulo, off-local-storage is required.\n\n### find your account key thru device-to-device RSA boxes\n\nLICENSE AGPL-3\nNo redistribution but for strategy of parts, unless retributed\n\nhow to use, Chats: create a public and private user data collection [users,userDatas] or whatever\n\nTO DO: update read me to v9 firestore\n\n    /*\n    userDatas = {\n      pendingDeviceBoxes: firebase.firestore.FieldValue.arrayRemove(\n        accountBox.box\n      ),\n      key: user[\"deviceBox\" + deviceBox.box]: ,\n      [\"deviceBox\" + deviceBox]: rsa.encrypt(\n        accountBox.key,\n        deviceBox,\n        \"SHA-256\",\n        {\n          name: \"RSA-PSS\"\n        }\n      )\n    }\n    keybox = {\n      key: privateKey,\n      box: publicKey\n    }\n    */\n    addUserDatas = (meAuth) => {\n        const users = firebase.firestore().collection(\"users\");\n        users.doc(meAuth.uid).onSnapshot((doc) => {\n            if (doc.exists) {\n                var userDatas = doc.data();\n                user.id = doc.id\n                const userDatas = firebase.firestore().collection(\"userDatas\");\n                userDatas.doc(meAuth.uid).onSnapshot((doc) => {\n                    if (doc.exists) {\n                        var userDatas = doc.data();\n                        this.setState(\n                            {\n                                user: { ...user, ...userDatas }\n                            },\n                            () => this.getEntities(meAuth)\n                        );\n                    }\n                }, standardCatch);\n            }\n        }, standardCatch);\n    };\n    import React from \"react\";\n    import PouchDB from \"pouchdb\";\n    import upsert from \"pouchdb-upsert\";\n    import rsa from \"js-crypto-rsa\";\n\n    const standardCatch = (err) => console.log(err.message);\n    const arrayMessage = (message) =>\n        message\n            .toLowerCase()\n            //capture or, excluding set, match 2 or more of the preceding token\n            .replace(/((\\r\\n|\\r|\\n)+[^a-zA-Z]+_+[ ]{2,})+/g, \" \")\n            .split(\" \");\n    const specialFormatting = (x, numbersOk) =>\n        x\n            .toLowerCase()\n            //replace or regex a-z or A-Z includes space whitespace\n            .replace(!numbersOk ? /[^a-zA-Z,']+/g : /[^a-zA-Z0-9,']+/g, \" \")\n            .split(\" \")\n            .map((word) => {\n                var end = word.substring(1);\n                if (word.includes(\"'\")) {\n                    var withapos = word.lastIndexOf(\"'\");\n                    var beginning = word.substring(1, withapos);\n                    if (beginning.length === 1) {\n                        end =\n                            beginning +\n                            \"'\" +\n                            word.charAt(withapos + 1).toUpperCase() +\n                            word.substring(withapos + 2);\n                    }\n                }\n                var resword = word.charAt(0).toUpperCase() + end;\n                return [\"Of\", \"And\", \"The\"].includes(resword)\n                    ? resword.toLowerCase()\n                    : arrayMessage(resword).join(\" \");\n            })\n            .join(\" \");\n\n\n    class RSA {\n        //Key-Box device query Asymmetric-Encryption\n        constructor(name) {\n            PouchDB.plugin(upsert);\n            const title = \"rsaPrivateKeys\";\n            this.db = new PouchDB(title, {});\n        }\n        deleteKey = async (_id) =>\n            await this.db\n                .remove(_id)\n                .then(() => {\n                    this.db.destroy().then(() => console.log(\"destoyed\"));\n                })\n                .catch(standardCatch);\n        //deleteKeys = async () => await destroy(this.db);\n        setPrivateKey = async (c) =>\n            await this.db //has upsert plugin from class constructor\n                .upsert(c._id, (c) => {\n                    var copy = { ...c }; //pouch-db \\(construct, protocol)\\\n                    return copy; //return a copy, don't displace immutable object fields\n                });\n        readPrivateKeys = async (notes = {}) =>\n            //let notes = {};\n            await this.db\n                .allDocs({ include_docs: true })\n                .then(\n                    (allNotes) => {\n                        return allNotes.rows.map((n) => (notes[n.doc.key] = n.doc));\n                    }\n                    // && and .then() are functionally the same;\n                )\n                .catch(standardCatch);\n    }\n\n    class DDB {\n        constructor(name) {\n            PouchDB.plugin(upsert);\n            const title = \"deviceName\";\n            this.db = new PouchDB(title, {\n                //revs_limit: 1, //revision-history\n                //auto_compaction: true //zipped...\n            });\n        }\n        deleteDeviceName = async (_id) =>\n            await this.db\n                .remove(_id)\n                .then(() => {\n                    this.db.destroy().then(() => console.log(\"destoyed\"));\n                })\n                .catch(standardCatch);\n\n        destroy = () => this.db.destroy().then(() => console.log(\"destoyed\"));\n        storeDeviceName = async (c) =>\n            await this.db //has upsert plugin from class constructor\n                .upsert(c._id, (c) => {\n                    var copy = { ...c }; //pouch-db \\(construct, protocol)\\\n                    return copy; //return a copy, don't displace immutable object fields\n                });\n        readDeviceName = async (notes = {}) =>\n        //let notes = {};\n        {\n            return await this.db\n                .allDocs({ include_docs: true })\n                .then(\n                    (allNotes) => {\n                        return allNotes.rows.map((n) => (notes[n.doc.key] = n.doc));\n                    }\n                    // && and .then() are functionally the same;\n                )\n                .catch(standardCatch);\n        };\n    }\n    const firestore = getFirestore(firebase);// new firestore v9\n    class Chats extends React.Component {\n        constructor(props) {\n            super(props);\n            let ddb = new DDB();\n            this.state = {\n                ddb,\n                rsaKeys: [],\n                chats: []\n            keyBoxes,\n                standbyMode\n            };\n        }\n        updateVintageCollection = () =>\n          this.setState({\n            deviceCollection: firebase.firestore().collection(\"devices\"),\n            userUpdatable: firebase\n              .firestore()\n              .collection(\"users\")\n              .doc(this.props.auth.uid),\n            userDatas: firebase\n              .firestore()\n              .collection(\"userDatas\")\n              .doc(this.props.auth.uid)\n          });\n        handleKeysForRoom = (room) => {\n            const { recipientsProfiled, threadId, user } = this.props;\n            const { rsaPrivateKeys } = this.state;\n            const rooms = firebase.firestore().collection(\"rooms\");\n            this.props.getRoomKeys(\n                room,\n                rsaPrivateKeys,\n                threadId,\n                recipientsProfiled,\n                rooms,\n                user\n            );\n        };\n        componentDidUpdate = (prevProps) => {\n            if (auth !== prevProps.auth)\n              auth !== undefined && this.updateVintageCollection();\n            if (\n                this.props.user !== undefined &&\n                this.props.user.key &&\n                this.props.recentChats &&\n                this.props.recipientsProfiled &&\n                this.props.recipientsProfiled.length > 0 &&\n                this.props.recipientsProfiled.length === this.props.recipients.length &&\n                this.state.room &&\n                this.state.room !== this.state.lastRoom\n            ) {\n                this.handleKeysForRoom(this.state.room);\n                this.setState({ lastRoom: this.state.room }, () => {\n                    const { room } = this.state;\n\n                    /*\n                    room = {\n                      id: collection + doc.id,\n                      [\"saltedKeys\" + userId]: roomKeyInBox,\n                      ...,\n                      [\"saltedKeys\" + userId]: roomKeyInBox\n                    }\n                    */\n                    const roomKey = room[\"saltedKey\" + this.props.auth.uid];\n                    this.setState({ roomKey }, () => {\n                        let p = 0;\n                        let chats = [];\n                        this.props.recentChats.map(async (x) => {\n                            p++;\n                            var foo = { ...x };\n                            const message = await rsa.decrypt(\n                                x.message,\n                                this.props.user.key,\n                                \"SHA-256\",\n                                {\n                                    name: \"RSA-PSS\"\n                                }\n                            );\n                            if (message) {\n                                foo.message = message;\n                                chats.push(foo);\n                            }\n                        });\n                        if (p === this.props.recentChats.length) {\n                            this.setState({ chats });\n                        }\n                    });\n                });\n            }\n            return <div>\n                <Chatter\n                    getRoomKeys={this.props.getRoomKeys}\n                />\n                {/*(() => console.log(\"go\"))()*/}\n                {this.props.auth === undefined ? (\n                    \"Login to forge vintages\"\n                ) : this.state.deviceCollection ? (\n                    <Vintages\n                      firestore={firestore} //new firestore v9\n                        Vintages={this.props.Vintages}\n                        rsaPrivateKeys={this.state.rsaPrivateKeys}\n                        ddb={this.state.ddb}\n                        show={\n                            true\n                            /*(!this.stream &&\n                            openFolder &&\n                            this.state.openFrom === \"Folder\") ||\n                          this.stream*/\n                        }\n                        auth={this.props.auth}\n                        setParentState={this.props.setNapkin}\n                        user={this.props.user}\n                        vintageOfKeys={this.props.vintageOfKeys}\n                        deviceCollection={this.state.deviceCollection}\n                        userUpdatable={this.state.userUpdatable}\n                        userDatas={this.state.userDatas}\n                    />\n                ) : (\n                            \"loading keys after login\"\n                        )}\n            </div>\n\nhow to use, Files\n\n    class Files extends React.Component {\n        constructor(props) {\n            super(props);\n            let rsaPrivateKeys = new RSA();\n            this.state = {\n                rsaPrivateKeys,\n                videos: []\n            };\n        }\n        componentDidUpdate = async (prevProps) => {\n            if (\n                this.props.auth !== undefined &&\n                this.props.videos !== [] &&\n                this.props.videos !== prevProps.videos\n            ) {\n                await this.state.rsaPrivateKeys\n                    .readPrivateKeys()\n                    .then(async (keysOutput) => {\n                        const keyBoxes = Object.values(keysOutput);\n                        if (keyBoxes) {\n                            let p = 0;\n                            let videos = [];\n                            const accountBox = keyBoxes.find(\n                                (x) => x._id === this.props.auth.uid\n                            );\n                            this.props.videos.map(async (x) => {\n                                p++;\n                                var foo = { ...x };\n                                var readFile = new FileReader();\n                                await fetch(x.gsUrl, {\n                                    \"Access-Control-Allow-Origin\": \"*\"\n                                })\n                                    .then((blob) => blob.blob())\n                                    .then((img) => {\n                                        if (!/image/.test(img.type)) {\n                                            return null; //not an image\n                                        }\n\n                                        readFile.readAsDataURL(img);\n                                        /*var reader = new FileReader();\n                                  reader.readAsArrayBuffer(img);\n                                  FileReader.readAsDataURL:\n                                  \"returns base64 that contains many characters, \n                                  and use more memory than blob url, but removes\n                                  from memory when you don't use it (by garbage collector)\"*/\n                                    })\n                                    .catch((err) =>\n                                        this.setState(\n                                            {\n                                                Errorf: err.message,\n                                                Photo: null\n                                            },\n                                            () => console.log(\"REACT-LOCAL-PHOTO: \" + err.message)\n                                        )\n                                    );\n\n                                //readFile.onerror = (err) => console.log(err.message);\n                                readFile.onloadend = (reader) => {\n                                    this.setState({ readFile }, async () => {\n                                        if (reader.target.readyState === 2) {\n                                            const gsUrl = await rsa.decrypt(\n                                                reader.target.result,\n                                                accountBox.key,\n                                                \"SHA-256\",\n                                                {\n                                                    name: \"RSA-PSS\"\n                                                }\n                                            );\n                                            if (gsUrl) {\n                                                foo.gsUrl = gsUrl;\n                                                videos.push(foo);\n                                            }\n                                        }\n                                    });\n                                };\n                            });\n                            if (p === this.props.videos.length) this.setState({ videos });\n                        }\n                    });\n            }\n        };\n\nSEE LICENSE IN LICENSE.lz.txt\n\ncopying the src code? https://github.com/npm/cli/issues/3514\nnpm install --force npm uninstall @babel/polyfill --save ...","readmeFilename":"Readme.md"}