├── public
└── logo.jpg
├── next-env.d.ts
├── utils
└── sample-data.ts
├── pages
├── _app.js
└── index.tsx
├── interfaces
└── index.ts
├── postcss.config.js
├── README.md
├── schema.gql.old
├── styles
└── index.css
├── .gitignore
├── tailwind.config.js
├── tsconfig.json
├── package.json
└── LICENSE
/public/logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/u-u-z/EncryptedClipboard/HEAD/public/logo.jpg
--------------------------------------------------------------------------------
/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/utils/sample-data.ts:
--------------------------------------------------------------------------------
1 | import { User } from '../interfaces'
2 |
3 | /** Dummy user data. */
4 | export const sampleUserData: User[] = [
5 | { id: 101, name: 'Alice' },
6 | { id: 102, name: 'Bob' },
7 | { id: 103, name: 'Caroline' },
8 | { id: 104, name: 'Dave' },
9 | ]
10 |
--------------------------------------------------------------------------------
/pages/_app.js:
--------------------------------------------------------------------------------
1 | import '../styles/index.css'
2 | import '@hackplan/uui/lib/index.css';
3 | import { RecoilRoot } from "recoil";
4 |
5 | function MyApp({ Component, pageProps }) {
6 | return
7 | }
8 |
9 | export default MyApp
10 |
--------------------------------------------------------------------------------
/interfaces/index.ts:
--------------------------------------------------------------------------------
1 | // You can include shared interfaces/types in a separate file
2 | // and then use them in any component by importing them. For
3 | // example, to import the interface below do:
4 | //
5 | // import User from 'path/to/interfaces';
6 |
7 | export type User = {
8 | id: number
9 | name: string
10 | }
11 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | 'tailwindcss',
4 | 'postcss-flexbugs-fixes',
5 | [
6 | 'postcss-preset-env',
7 | {
8 | autoprefixer: {
9 | flexbox: 'no-2009',
10 | },
11 | stage: 3,
12 | features: {
13 | 'custom-properties': false,
14 | },
15 | },
16 | ],
17 | ],
18 | }
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Seclip
2 |
3 | 一个在线加密内容、生成链接分享的工具,可以用来发服务器密码之类的。
4 |
5 | 来瞧瞧:https://seclip.remi.fun/
6 |
7 | ## 搞这个干啥
8 |
9 | 因为一次业务救火,用微信转发服务器密码,感觉这么做有点智障 ··· 又因为太笨不知道类似 privatebin.info 这类应用的存在,于是自己写了一个 ···
10 |
11 | ## 这个安全么?
12 |
13 | 正确的使用对称加密,大概比较安全吧,(只要人不傻)。
14 |
15 | 加密是直接通过 AES 生成的 url,使用了 `crypto-js` 库。密文都在 url 上,对称加密密钥不丢失就不会泄露 ···
16 |
17 | ## 之后想添加的功能
18 |
19 | - [ ] 二维码;
20 | - [ ] 压缩密文 base64?
21 | - [ ] 短网址?
22 | - [ ] 非对称加密?
23 |
24 |
--------------------------------------------------------------------------------
/schema.gql.old:
--------------------------------------------------------------------------------
1 | enum SiteType {
2 | WEBAPP
3 | }
4 |
5 | enum BlockType {
6 | MAIN
7 | FEATURES
8 | }
9 |
10 | type Site {
11 | name: String!
12 | type: SiteType
13 | color: [String]
14 | fontFamily: String!
15 | blocks: [Block] @relation
16 | }
17 |
18 | type Block {
19 | type: BlockType
20 | name: String!
21 | props: String! #JSON
22 | site: Site
23 | }
24 |
25 | type Query {
26 | allSites: [Site]
27 | allBlocks:[Block]
28 | }
--------------------------------------------------------------------------------
/styles/index.css:
--------------------------------------------------------------------------------
1 | /* index.css */
2 |
3 |
4 | @tailwind base;
5 |
6 | /* Write your own custom base styles here */
7 |
8 | /* Start purging... */
9 | @tailwind components;
10 | /* Stop purging. */
11 |
12 | /* Write you own custom component styles here */
13 | .btn-blue {
14 | @apply bg-blue-500 text-white font-bold py-2 px-4 rounded;
15 | }
16 |
17 | /* Start purging... */
18 | @tailwind utilities;
19 | /* Stop purging. */
20 |
21 | /* Your own custom utilities */
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 |
27 | # local env files
28 | .env.local
29 | .env.development.local
30 | .env.test.local
31 | .env.production.local
32 |
33 | # vercel
34 | .vercel
35 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | purge: ['./components/**/*.{js,ts,jsx,tsx}', './pages/**/*.{js,ts,jsx,tsx}'],
3 | theme: {
4 | extend: {
5 | backgroundColor: {
6 | primary: "var(--color-bg-primary)",
7 | secondary: "var(--color-bg-secondary)",
8 | },
9 | textColor: {
10 | accent: "var(--color-text-accent)",
11 | primary: "var(--color-text-primary)",
12 | secondary: "var(--color-text-secondary)",
13 | },
14 | },
15 | },
16 | variants: {},
17 | plugins: [],
18 | }
19 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowJs": true,
4 | "alwaysStrict": true,
5 | "esModuleInterop": true,
6 | "forceConsistentCasingInFileNames": true,
7 | "isolatedModules": true,
8 | "jsx": "preserve",
9 | "lib": ["dom", "es2017"],
10 | "module": "esnext",
11 | "moduleResolution": "node",
12 | "noEmit": true,
13 | "noFallthroughCasesInSwitch": true,
14 | "noUnusedLocals": true,
15 | "noUnusedParameters": true,
16 | "resolveJsonModule": true,
17 | "skipLibCheck": true,
18 | "strict": true,
19 | "target": "esnext"
20 | },
21 | "exclude": ["node_modules"],
22 | "include": ["**/*.ts", "**/*.tsx"]
23 | }
24 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-typescript",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "dev": "next",
6 | "build": "next build",
7 | "start": "next start",
8 | "type-check": "tsc"
9 | },
10 | "dependencies": {
11 | "@hackplan/uui": "^0.4.15",
12 | "@types/crypto-js": "^3.1.47",
13 | "@types/uuid": "^8.3.0",
14 | "copy-to-clipboard": "^3.3.1",
15 | "crypto-js": "^4.0.0",
16 | "next": "latest",
17 | "react": "^16.12.0",
18 | "react-dom": "^16.12.0",
19 | "react-hook-form": "^6.4.1",
20 | "recoil": "^0.0.10",
21 | "typestyle": "^2.1.0",
22 | "uuid": "^8.3.0",
23 | "vercel": "^20.1.0"
24 | },
25 | "devDependencies": {
26 | "@types/node": "^12.12.21",
27 | "@types/react": "^16.9.16",
28 | "@types/react-dom": "^16.9.4",
29 | "postcss-flexbugs-fixes": "4.2.1",
30 | "postcss-preset-env": "^6.7.0",
31 | "tailwindcss": "^1.6.0",
32 | "typescript": "4.0.2"
33 | },
34 | "license": "ISC"
35 | }
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 HackPlan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import { Button, Dialog, TextArea, TextField, Toaster, ToasterPosition } from '@hackplan/uui';
2 | import Head from 'next/head'
3 | import React, { useState, useEffect } from 'react'
4 | import AES from 'crypto-js/aes';
5 | import cryptoUtf8 from 'crypto-js/enc-utf8';
6 | import copy from 'copy-to-clipboard';
7 |
8 | const cryptContent = (content: string, key: string) => AES.encrypt(content, key).toString();
9 | const GlobalMsg: any = Toaster.create({
10 | maxToasts: 5,
11 | position: ToasterPosition.TopRight,
12 | })
13 |
14 | const IndexPage = (props: any) => {
15 | const beforeDecryptDialogStatus: boolean = (props.cryptBase64 && props.cryptBase64.length > 0) ? true : false
16 | const [content, setContent] = useState("");
17 | const [password, setPassword] = useState("");
18 | const [inputStatus, setInputStatus] = useState(true);
19 | const [cryptResult, setCryptResult] = useState("项目开源在 github.com/u-u-z/EncryptedClipboard")
20 | const [decryptDialogStatus, setDecryptDialogStatus] = useState(beforeDecryptDialogStatus);
21 | const [resultError, setResultError] = useState(false);
22 | useEffect(() => {
23 | if (inputStatus === false) {
24 | setInputStatus(true)
25 | setCryptResult("项目开源在 github.com/u-u-z/EncryptedClipboard")
26 | }
27 | }, [content]);
28 |
29 | return
30 |
31 |
加密剪贴板
32 |
33 |
34 |
35 |
36 |
37 | {/*
*/}
38 |
39 |
78 |
85 |
86 |
87 |
88 |
93 |
94 | {
95 | setPassword(value);
96 | }} placeholder={'密码'} />
97 |
98 |
99 |
110 |
111 |
112 |
113 | {
114 | !inputStatus ? : <>>
118 | }
119 |
120 |
121 |
128 |
129 |
130 |
131 |
132 | }
133 |
134 | IndexPage.getInitialProps = async (params: any) => {
135 | try {
136 | if (params.query.s) {
137 | return {
138 | cryptBase64: decodeURIComponent(params.query.s)
139 | }
140 | } else {
141 | return {}
142 | }
143 | } catch {
144 | return {}
145 | }
146 | }
147 |
148 |
149 | export default IndexPage
150 |
--------------------------------------------------------------------------------