@@ -14,10 +14,10 @@ LessPass servers are hosted on Vultr. Create an account on Vultr and receive \$1 | |||||
## How does it work? | ## How does it work? | ||||
- :gb: [LessPass - How Does It Work?](https://blog.lesspass.com/lesspass-how-it-works-dde742dd18a4#.vbgschksh) | |||||
- :fr: [LessPass - comment ça marche?](https://blog.lesspass.com/lesspass-comment-%C3%A7a-marche-9f1201fffda5#.yjmd1bcad) | |||||
- :de: [LessPass - Wie funktioniert das?](https://blog.lesspass.com/lesspass-wie-funktioniert-das-9483e5fc2c09) | |||||
- :it: [LessPass - Come funziona?](https://blog.lesspass.com/lesspass-come-funziona-5d1785b4a564) | |||||
- :gb: [LessPass - How Does It Work?](https://blog.lesspass.com/2016-10-19/how-does-it-work) | |||||
- :fr: [LessPass - comment ça marche?](https://blog.lesspass.com/2016-07-08/comment-ca-marche) | |||||
- :de: [LessPass - Wie funktioniert das?](https://blog.lesspass.com/2017-07-18/wie-funktioniert-das) | |||||
- :it: [LessPass - Come funziona?](https://blog.lesspass.com/2019-04-04/come-funziona) | |||||
## Videos | ## Videos | ||||
@@ -1,71 +0,0 @@ | |||||
# Logs | |||||
logs | |||||
*.log | |||||
npm-debug.log* | |||||
yarn-debug.log* | |||||
yarn-error.log* | |||||
# Runtime data | |||||
pids | |||||
*.pid | |||||
*.seed | |||||
*.pid.lock | |||||
# Directory for instrumented libs generated by jscoverage/JSCover | |||||
lib-cov | |||||
# Coverage directory used by tools like istanbul | |||||
coverage | |||||
# nyc test coverage | |||||
.nyc_output | |||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | |||||
.grunt | |||||
# Bower dependency directory (https://bower.io/) | |||||
bower_components | |||||
# node-waf configuration | |||||
.lock-wscript | |||||
# Compiled binary addons (http://nodejs.org/api/addons.html) | |||||
build/Release | |||||
# Dependency directories | |||||
node_modules/ | |||||
jspm_packages/ | |||||
# Typescript v1 declaration files | |||||
typings/ | |||||
# Optional npm cache directory | |||||
.npm | |||||
# Optional eslint cache | |||||
.eslintcache | |||||
# Optional REPL history | |||||
.node_repl_history | |||||
# Output of 'npm pack' | |||||
*.tgz | |||||
# dotenv environment variables file | |||||
.env | |||||
# gatsby files | |||||
.cache/ | |||||
public | |||||
# Mac files | |||||
.DS_Store | |||||
# Yarn | |||||
yarn-error.log | |||||
.pnp/ | |||||
.pnp.js | |||||
# Yarn Integrity file | |||||
.yarn-integrity | |||||
.netlify/ |
@@ -1,13 +0,0 @@ | |||||
FROM node:lts AS builder | |||||
LABEL maintainer="LessPass <contact@lesspass.com>" | |||||
LABEL name="LessPass Blog" | |||||
WORKDIR /opt/blog | |||||
COPY package.json yarn.lock ./ | |||||
RUN yarn install | |||||
COPY . /opt/blog | |||||
RUN yarn build | |||||
FROM nginx:alpine | |||||
COPY --from=builder /opt/blog/build /usr/share/nginx/html | |||||
COPY nginx.conf /etc/nginx/conf.d/default.conf | |||||
EXPOSE 80 | |||||
CMD ["nginx", "-g", "daemon off;"] |
@@ -1,9 +0,0 @@ | |||||
- name: Guillaume Vincent | |||||
bio: | | |||||
Software craftsman. Humanist, open source addict, blogger and fan of scuba diving. | |||||
I ♥ code, design, UX and cats. Creator of LessPass | |||||
avatar: ./avatars/guillaume-vincent.jpg | |||||
social: | |||||
- url: https://twitter.com/guillaume20100 | |||||
- url: https://github.com/guillaumevincent | |||||
featured: true |
@@ -1,123 +0,0 @@ | |||||
--- | |||||
title: LessPass How Does It Work? | |||||
author: Guillaume Vincent | |||||
date: 2016-10-19 | |||||
hero: ./images/HowItWorks.png | |||||
--- | |||||
Managing your Internet passwords is not easy. You probably use a password manager to help you. The system is simple, the tool generates random passwords whenever you need them and saves them into a file protected with a strong password. | |||||
This system is very robust, you only need to remember one password to rule them all! Now you have a unique password for each site on the Internet. | |||||
I have used this system for a long time. But every time I met the same problems: | |||||
* How do I synchronize this file on all my devices ? | |||||
* How do I access a password on my parents’ computer without installing my password manager ? | |||||
* How do I access a password on my phone, without any installed app ? | |||||
So I searched for a simpler solution and as none satisfied all those criteria I created LessPass. | |||||
* I want a password manager with open source code, that does not require synchronization. | |||||
The trick is to compute passwords rather than generate and store random passwords. | |||||
LessPass generates unique passwords for websites, email accounts, or anything else based on a master password and information you know. | |||||
LessPass is different from other password managers that you can find on the Internet because: | |||||
* It does not save your passwords in a database ; | |||||
* It does not need to sync your devices ; | |||||
* It is open source (source code can be audited). | |||||
The system uses a pure function, i.e. a function that given the same parameters will always give the same result. In our case, given a login, a master password, a site and options it will return a unique password. | |||||
No need to save your passwords in an encrypted file. You just need to access the tool to recalculate a password from information that you know (mostly the login). | |||||
To raise the cost of breaking your master password, the generation of the password must be time consuming, especially by brute force. So LessPass uses PBKDF2 with 100,000 iterations and a hash function sha-256. | |||||
Password generation is based on pure functions. | |||||
The hash generated by the first function is derived and processed in order to respect the requested options (i.e. length, lowercase, uppercase, numbers, special characters): | |||||
![how it works demo](./images/HowItWorks.png) | |||||
The source code is available [here](https://github.com/lesspass/lesspass/), I invite you to have a look . | |||||
## What does it look like? | |||||
A picture is worth a thousand words: | |||||
![lesspass demo](./images/demo.gif) | |||||
The simplest way to try it is to use the official website https://lesspass.com/ to type in your site, login and master password. The password will be generated on the fly so you just have to copy it (using the button or the keyboard). | |||||
Try it on your phone, on another computer, even offline, it will give the same result. No need to sync. | |||||
## Is it available on my OS/device? | |||||
Yes, as soon as you have access to a browser it’s available to you. But we went beyond that and added: | |||||
* an Android application ; | |||||
* a Chrome extension ; | |||||
* a Firefox extension ; | |||||
* a command line interface ; | |||||
* and the official site (for more security use browser extensions). | |||||
## What about complex password rules? | |||||
Sometimes sites have specific password rules. For instance, some banks only accept passwords made of numbers. So you have to remember both a strong password and complex rules. | |||||
Well, we built a “connected” version to tackle that. It works by saving your password’s profile, i.e. everything **except the master password and the generated password** to be able to generate the password. Then, next time you need this password you just have to select the profile and type the master password. | |||||
Here is what a profile looks like: | |||||
{ | |||||
"login": "38491092", | |||||
"site": "www.ingdirect.fr", | |||||
"lowercase": false, | |||||
"uppercase": false, | |||||
"symbols": false, | |||||
"numbers": true, | |||||
"counter": 1, | |||||
"length": 6 | |||||
} | |||||
Below is a user connecting to it’s account to use his bank’s account profile: | |||||
The connected version can help you save complex profiles. | |||||
![lesspass demo](./images/demo-lesspass-connected.gif) | |||||
## Self Hosted | |||||
You can host your own LessPass Database if you do not want to use the official one. The requirement for self-hosting is to have `docker` and `docker-compose` installed on your machine. | |||||
Look at the documentation on github if you are interested in | |||||
## How do I change a password without changing my master password? | |||||
That’s the purpose of the counter field in the options field set, increment it and you will get a new password. | |||||
Counter field | |||||
## How to contribute? | |||||
* If you are a scientist, help us write a white paper ; | |||||
* Send pull requests to improve or fix the source code ; | |||||
* Rate the Firefox or the Chrome extension ; | |||||
* Send us to the stars on github ; | |||||
## Open Culture | |||||
LessPass is open source (GPLv3 license), we refuse to install cookies, analysis tools on our applications (there are no Google Analytics, or links to external services on our tools). | |||||
We host our code on Vultr’s servers and our DNS are managed by Gandi . | |||||
We really like the idea of an open culture: all bugs that we find are visible. | |||||
We document our algorithms and our approach: no magic, no black box. | |||||
We love feedback and your ideas to improve the tool: we are aware of some limitations (change of master password, for example) but we are working to improve the product. | |||||
We are not sponsored by any company, developing LessPass is done during our free time. | |||||
If you have comments or questions, feel free to email us at contact@lesspass.com | |||||
I want to thank Édouard Lopez for all the work on user experience and great feadback on the product! |
@@ -1,54 +0,0 @@ | |||||
module.exports = { | |||||
siteMetadata: { | |||||
title: `LessPass Blog`, | |||||
name: `LessPass`, | |||||
siteUrl: `https://blog.lesspass.com`, | |||||
description: `LessPass blog`, | |||||
hero: { | |||||
heading: `LessPass blog`, | |||||
maxWidth: 652, | |||||
}, | |||||
social: [ | |||||
{ | |||||
name: `twitter`, | |||||
url: `https://twitter.com/guillaume20100`, | |||||
}, | |||||
{ | |||||
name: `github`, | |||||
url: `https://github.com/lesspass/lesspass`, | |||||
}, | |||||
], | |||||
}, | |||||
plugins: [ | |||||
{ | |||||
resolve: "@narative/gatsby-theme-novela", | |||||
options: { | |||||
contentPosts: "content/posts", | |||||
contentAuthors: "content/authors", | |||||
basePath: "/", | |||||
authorsPage: true, | |||||
sources: { | |||||
local: true, | |||||
// contentful: true, | |||||
}, | |||||
}, | |||||
}, | |||||
{ | |||||
resolve: `gatsby-plugin-manifest`, | |||||
options: { | |||||
name: `LessPass Blog`, | |||||
short_name: `LessPass`, | |||||
start_url: `/`, | |||||
background_color: `#fff`, | |||||
theme_color: `#fff`, | |||||
display: `standalone`, | |||||
icon: `src/assets/favicon.png`, | |||||
}, | |||||
}, | |||||
{ | |||||
resolve: `gatsby-plugin-netlify-cms`, | |||||
options: { | |||||
}, | |||||
}, | |||||
], | |||||
}; |
@@ -1,22 +0,0 @@ | |||||
{ | |||||
"private": true, | |||||
"name": "site", | |||||
"version": "1.0.0", | |||||
"license": "MIT", | |||||
"scripts": { | |||||
"build": "gatsby build", | |||||
"dev": "gatsby develop", | |||||
"clean": "gatsby clean", | |||||
"proxy": "netlify-cms-proxy-server" | |||||
}, | |||||
"dependencies": { | |||||
"@narative/gatsby-theme-novela": "^0.*", | |||||
"gatsby": "^2.13.41", | |||||
"gatsby-plugin-manifest": "^2.2.4", | |||||
"gatsby-plugin-netlify-cms": "^4.1.40", | |||||
"netlify-cms-app": "^2.11.23", | |||||
"netlify-cms-proxy-server": "^1.1.4", | |||||
"react": "^16.8.6", | |||||
"react-dom": "^16.8.6" | |||||
} | |||||
} |
@@ -1,131 +0,0 @@ | |||||
import React from "react"; | |||||
/** | |||||
* Paste in your SVG logo and return it from this component. | |||||
* Make sure you have a height set for your logo. | |||||
* It is recommended to keep the height within 25-35px. | |||||
* Logo comes with a property vallue called `fill`. `fill` is useful | |||||
* when you want to change your logo depending on the theme you are on. | |||||
*/ | |||||
export default function Logo({ fill }) { | |||||
return ( | |||||
<svg width="50" height="50" version="1.1"> | |||||
<defs> | |||||
<filter colorInterpolationFilters="sRGB"> | |||||
<feFlood | |||||
floodColor="#000" | |||||
floodOpacity="0.4" | |||||
result="flood" | |||||
></feFlood> | |||||
<feComposite | |||||
in="flood" | |||||
in2="SourceGraphic" | |||||
operator="in" | |||||
result="composite1" | |||||
></feComposite> | |||||
<feGaussianBlur result="blur" stdDeviation="2"></feGaussianBlur> | |||||
<feOffset dx="4" dy="4" result="offset"></feOffset> | |||||
<feComposite | |||||
in="SourceGraphic" | |||||
in2="offset" | |||||
operator="over" | |||||
result="composite2" | |||||
></feComposite> | |||||
</filter> | |||||
<filter id="a" colorInterpolationFilters="sRGB"> | |||||
<feFlood | |||||
floodColor="#000" | |||||
floodOpacity="0.4" | |||||
result="flood" | |||||
></feFlood> | |||||
<feComposite | |||||
in="flood" | |||||
in2="SourceGraphic" | |||||
operator="in" | |||||
result="composite1" | |||||
></feComposite> | |||||
<feGaussianBlur result="blur" stdDeviation="1"></feGaussianBlur> | |||||
<feOffset dx="4" dy="4" result="offset"></feOffset> | |||||
<feComposite | |||||
in="SourceGraphic" | |||||
in2="offset" | |||||
operator="over" | |||||
result="composite2" | |||||
></feComposite> | |||||
</filter> | |||||
<filter colorInterpolationFilters="sRGB"> | |||||
<feFlood | |||||
floodColor="#000" | |||||
floodOpacity="0.4" | |||||
result="flood" | |||||
></feFlood> | |||||
<feComposite | |||||
in="flood" | |||||
in2="SourceGraphic" | |||||
operator="in" | |||||
result="composite1" | |||||
></feComposite> | |||||
<feGaussianBlur result="blur" stdDeviation="2"></feGaussianBlur> | |||||
<feOffset dx="4" dy="4" result="offset"></feOffset> | |||||
<feComposite | |||||
in="SourceGraphic" | |||||
in2="offset" | |||||
operator="over" | |||||
result="composite2" | |||||
></feComposite> | |||||
</filter> | |||||
</defs> | |||||
<g fillOpacity="1" stroke="none" transform="translate(-5.421 -5)"> | |||||
<rect | |||||
width="40.035" | |||||
height="40.035" | |||||
x="-19.72" | |||||
y="22.706" | |||||
fill="#0275d8" | |||||
opacity="0.9" | |||||
rx="8.007" | |||||
transform="rotate(-45)" | |||||
></rect> | |||||
<path | |||||
style={{ | |||||
lineHeight: "normal", | |||||
InkscapeFontSpecification: "Sans", | |||||
WebkitTextIndent: "0", | |||||
textIndent: "0", | |||||
WebkitTextAlign: "start", | |||||
textAlign: "start", | |||||
WebkitTextDecorationLine: "none", | |||||
textDecorationLine: "none", | |||||
WebkitTextTransform: "none", | |||||
textTransform: "none", | |||||
marker: "none", | |||||
}} | |||||
fill="#fff" | |||||
fillRule="nonzero" | |||||
strokeWidth="10" | |||||
d="M79.92 55.04c-12.363 0-22.471 10.136-22.471 22.5 0 10.28 6.991 18.98 16.453 21.628v45.872h18.253c.126 0 .225-.099.225-.225v-10.237c0-.126-.104-.26-.225-.225H85.94V130.5h6.215c.126 0 .225-.1.225-.225v-10.238a.223.223 0 00-.225-.225H85.94V99.168c9.462-2.648 16.453-11.348 16.453-21.628 0-12.364-10.108-22.5-22.472-22.5zm0 8.831c7.597 0 13.641 6.073 13.641 13.67 0 7.596-6.044 13.64-13.64 13.64-7.596 0-13.64-6.044-13.64-13.64 0-7.597 6.044-13.67 13.64-13.67z" | |||||
baselineShift="baseline" | |||||
color="#000" | |||||
direction="ltr" | |||||
display="inline" | |||||
enableBackground="accumulate" | |||||
filter="url(#a)" | |||||
fontFamily="Sans" | |||||
fontSize="medium" | |||||
fontStretch="normal" | |||||
fontStyle="normal" | |||||
fontVariant="normal" | |||||
fontWeight="normal" | |||||
letterSpacing="normal" | |||||
overflow="visible" | |||||
textAnchor="start" | |||||
textDecoration="none" | |||||
transform="matrix(.33333 0 0 .33333 3.78 -3.347)" | |||||
visibility="visible" | |||||
wordSpacing="normal" | |||||
writingMode="lr-tb" | |||||
></path> | |||||
</g> | |||||
</svg> | |||||
); | |||||
} |
@@ -1,21 +0,0 @@ | |||||
import React from "react"; | |||||
import Layout from "@narative/gatsby-theme-novela/src/components/Layout"; | |||||
import Section from "@narative/gatsby-theme-novela/src/components/Section"; | |||||
import SEO from "@narative/gatsby-theme-novela/src/components/SEO"; | |||||
import Headings from "@narative/gatsby-theme-novela/src/components/Headings"; | |||||
function NotFoundPage() { | |||||
return ( | |||||
<Layout> | |||||
<SEO /> | |||||
<Section> | |||||
<div style={{ marginTop: "100px" }}> | |||||
<Headings.h1>404: Page Not Found</Headings.h1> | |||||
</div> | |||||
</Section> | |||||
</Layout> | |||||
); | |||||
} | |||||
export default NotFoundPage; |
@@ -1,43 +0,0 @@ | |||||
backend: # Set up your backend | |||||
name: gitlab | |||||
local_backend: true # Optional if you want to use the local proxy mode | |||||
publish_mode: editorial_workflow | |||||
media_folder: media # I'm not using these default media directories at the moment. | |||||
public_folder: /media | |||||
collections: | |||||
- name: "posts" | |||||
label: "Posts" | |||||
folder: "content/posts" | |||||
create: true | |||||
delete: true | |||||
path: "{{slug}}/index" | |||||
slug: "{{year}}-{{month}}-{{day}}-{{slug}}" | |||||
media_folder: "images" | |||||
public_folder: "./images" | |||||
fields: | |||||
- { label: "Title", name: "title", widget: "string" } | |||||
- { label: "Author", name: "author", widget: "relation", collection: "authors", valueField: "name", searchFields: ["name"] } | |||||
- { label: "Publish Date", name: "date", widget: "datetime", format: "YYYY-MM-DD", dateFormat: "YYYY-MM-DD", timeFormat: false } | |||||
- { label: "Excerpt", name: "excerpt", widget: "string", required: false } | |||||
- { label: "Hero", name: "hero", widget: "image" } | |||||
- { label: "Body", name: "body", widget: "markdown" } | |||||
- name: "authors" | |||||
label: "Authors" | |||||
folder: "content/authors/authors" | |||||
create: true | |||||
delete: true | |||||
format: "yml" | |||||
identifier_field: "name" | |||||
media_folder: "avatars" | |||||
public_folder: "./avatars" | |||||
editor: | |||||
preview: false | |||||
fields: | |||||
- { label: Name, name: name, widget: string } | |||||
- { label: Bio, name: bio, widget: string } | |||||
- { label: Featured, name: featured, widget: boolean, default: false } | |||||
- { label: Avatar, name: avatar, widget: image } | |||||
- { label: Social, name: social, widget: list, collapsed: false, field: { label: URL, name: url, widget: string } } |
@@ -244,7 +244,7 @@ | |||||
</p> | </p> | ||||
<p> | <p> | ||||
<a | <a | ||||
href="https://blog.lesspass.com/lesspass-how-it-works-dde742dd18a4#.vbgschksh" | |||||
href="https://blog.lesspass.com/2016-10-19/how-does-it-work" | |||||
class="btn btn-secondary" | class="btn btn-secondary" | ||||
> | > | ||||
How does it work? | How does it work? | ||||