惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
J
Java Code Geeks
小众软件
小众软件
Jina AI
Jina AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Hugging Face - Blog
Hugging Face - Blog
Stack Overflow Blog
Stack Overflow Blog
Blog — PlanetScale
Blog — PlanetScale
C
Check Point Blog
人人都是产品经理
人人都是产品经理
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - Franky
Apple Machine Learning Research
Apple Machine Learning Research
G
Google Developers Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Hackread – Cybersecurity News, Data Breaches, AI and More
The GitHub Blog
The GitHub Blog
腾讯CDC
T
The Blog of Author Tim Ferriss
大猫的无限游戏
大猫的无限游戏
量子位
M
MIT News - Artificial intelligence
Last Week in AI
Last Week in AI
L
LangChain Blog

Obsidian Blog

Obsidian Sync audits by Cure53 and Trail of Bits The future of Obsidian plugins Obsidian October 2025 Less is safer: how Obsidian reduces the risk of supply chain attacks Obsidian is now free for work 2024 Gems of the year winners 2024 Gems of the year nominations Second audit of Obsidian apps completed by Cure53 Obsidian Softwear: new Fractal t-shirts and hoodies Save the web Obsidian October 2024 Obsidian Sync now starts at $4 per month with the new Standard plan Announcing JSON Canvas: an open file format for infinite canvas data 2023 Gems of the year winners New security page and independent audit completed by Cure53 2023 Gems of the year nominations New Obsidian Sync plans: bigger, better, faster, smoother Goodbye legacy editor Obsidian Importer now converts Apple Notes to portable, durable files Obsidian October 2023 Free your notes The new Obsidian icon New developer documentation site Obsidian Publish now offers more for less: a lower price, with new features, improved SEO and accessibility 2022 Gems of the year winners I’m joining Obsidian full-time as CEO New Code of Conduct for our community 2022 Gems of the year nominations Obsidian October 2022 winners Obsidian October 2022
How to verify Obsidian Sync's end-to-end encryption
licat · 2023-06-05 · via Obsidian Blog

On our About page, we describe the guiding principles that have shaped Obsidian since the start. Privacy is one of these principles, and we go to great lengths to make sure we can uphold this statement:

We believe that your thoughts and ideas belong to you and deserve complete privacy. That’s why your data is stored on your device, inaccessible to us. When you use our online services, your data is protected with end-to-end encryption for maximum security.

When you use Obsidian Sync, your data is end-to-end encrypted. But how can you be sure that is true?

In this guide, we provide step-by-step instructions so that you can trustlessly verify the end-to-end encryption of your data when it is sent and received via our Sync servers.

How Obsidian Sync works

Let’s review how Obsidian Sync encryption works:

  1. You provide a vault password, or let our managed server generate one for you. This password is separate from your account password and is only used for establishing a remote vault.
  2. The Obsidian app generates a unique salt for each vault. A salt is random data used to protect your password by mixing it with your password before hashing.
  3. Your base key is derived from your password + salt using an algorithm called scrypt.
  4. Your encryption key is derived from the base key using an algorithm called HKDF. If your vault was created using the older encryption version, the encryption key uses the base key directly.
  5. This encryption key is used to encrypt/decrypt data with AES-256 using Galois/Counter Mode.

In the next few steps, you’ll learn how to get your vault’s salt, and test the encryption of your data.

Getting your vault’s salt and encryption version

First, get the salt used to derive your encryption key by following these steps:

  1. Make sure that Obsidian Sync is turned on.
  2. Open Developer Tools in the Obsidian app using the hotkey Cmd+Opt+I on macOS or Ctrl+Shift+I on Windows.
  3. Go to the Console and run the following code, by copy/pasting it and pressing the Return key:
let data = await (await fetch('https://api.obsidian.md/vault/list', {method:'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({token: JSON.parse(localStorage.getItem('obsidian-account')).token})})).json();
let vaults = [].concat(data.shared, data.vaults);
let vault = vaults.find(v => v.id === app.internalPlugins.getEnabledPluginById('sync').vaultId);
console.log(`The salt of your vault ${vault.name} is: "${vault.salt}" with encryptionVersion ${vault.encryption_version}`);

You should see a message containing your salt and encryption version:

The salt of your vault Notes is: "8II2%?YeNpddlbd@4Z)c" with encryptionVersion 0

Decrypting data

Next, find an example of a sync event and decrypt it. Here we will use the Network tab of Developers Tools. This is where all sync events are logged, so you can see data that is being sent and received by the Obsidian app, and confirm that it is using your encryption key.

  1. Go to the Network tab of the Developer Tools, and filter by "Socket" types (for WebSocket).
  2. Find the WebSocket connection to Obsidian Sync. It will look like sync-xx.obsidian.md — you may need to reload Obsidian to see it.
  3. In the WebSocket data stream, go to the Message tab. There you will see binary messages of uploads and downloads. If you aren’t seeing them, you can easily trigger one by modifying any synced note in your vault.
  4. Right click on one of them and choose Copy message > Copy as Base64.
  5. Using the following code, enter your password, your salt, and base64 binary data, and change the encryption version if necessary. Then, run the decryption routine in the Console (alternatively you can run it in a NodeJS prompt or script).
// Use the standard crypto package from NodeJS
let crypto = require('crypto');

// Enter your password, salt, and base64 binary data
let password = '8VbM0dCTdyX4QzO(@)Y7';
let salt = '8zUqk?w*rnU7LneIzJR&';
let data = Buffer.from('sAsic1PU9IpdteFDoff+dSVHTL1KnOWaGE5PJnYf51L8qPJFslqHWcqZAdrYaUMdXqirdlw4rDhtvWb9Lg==', 'base64');

// Enter the encryption protocol version (0 or 3)
let encryptionVersion = 3;

// Derive the encryption/decryption key from your password and salt
let key = crypto.scryptSync(Buffer.from(password.normalize('NFKC'), 'utf8'), Buffer.from(salt.normalize('NFKC'), 'utf8'),
  32, {N: 32768, r: 8, p: 1, maxmem: 128 * 32768 * 8 * 2});
let aesKey = key;
if (encryptionVersion === 3) {
  aesKey = crypto.hkdfSync('sha256', key, '', 'ObsidianAesGcm', 32);
}

// Split up the data blob into the 12-bytes IV, the encrypted data, and the 16-bytes auth tag.
let iv = data.subarray(0, 12);
let encryptedData = data.subarray(12, data.length - 16);
let authTag = data.subarray(data.length - 16);

// Decrypt the data
let decipher = crypto.createDecipheriv('aes-256-gcm', aesKey, iv);
decipher.setAuthTag(authTag);
let decrypted = Buffer.concat([decipher.update(encryptedData), decipher.final()]);

// Print it to a string
console.log(decrypted.toString('utf8'));

The data that is returned should be a revision of a file that was sent or received via the Obsidian Sync’s servers. That’s it! If it properly decrypts, you’ll know your encryption key is working.


2025-09-05 edit: Updated instructions to support new Sync version.