Yu-Jung Cheng
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.

      Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Explore these features while you wait
      Complete general settings
      Bookmark and like published notes
      Write a few more notes
      Complete general settings
      Write a few more notes
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # GCM Encryption ###### tags: `gcm` A basic understand about GCM mode (Galois Counter Mode) in AES encryption. #### Key notes Advanced Encryption Standard (AES) is a fast, secure and very popular block cipher that is commonly used to encrypt electronic data. AES has three different block ciphers: AES-128 (128 bit), AES-192 (192 bit) and AES-256 (256 bit) - each cipher is named after the key length they use for encryption and decryption. AES supports many different "modes". Modes are the internal algorithm used to encrypt data; each mode can potentially have different inputs and outputs but they always have a single input for data to encrypt and a single output for encrypted data along with an input key. GCM is a mode of AES that uses the CTR (counter) mode to encrypt data and uses Galois mode for authentication. Aside from the CTR mode which is used to encrypt the data, Galois mode authentication allows us to check at the end of decryption that the message has not been tampered with. GCM is well known for its speed and that it's a mode that it's patent-free. Galois/Counter Mode (GCM) is a mode of operation for symmetric-key cryptographic block ciphers which is widely adopted for its performance. CTR mode turns a block cipher into a stream cipher. It generates the next keystream block by encrypting successive values of a "counter". The counter can be any function which produces a sequence which is guaranteed not to repeat for a long time, although an actual increment-by-one counter is the simplest and most popular. Nonce is used by authentication protocols to ensure that old communications cannot be reprocessed. Hashing. Proof of work systems use nonce values to vary input to a cryptographic hash function. This helps fulfill arbitrary conditions and provide a desired difficulty. #### Install ``` ycheng@NUC10:~$ python3 -m pip install pycryptodome Defaulting to user installation because normal site-packages is not writeable Collecting pycryptodome Downloading pycryptodome-3.16.0-cp35-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (2.3 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.3/2.3 MB 6.4 MB/s eta 0:00:00 Installing collected packages: pycryptodome Successfully installed pycryptodome-3.16.0 ``` #### Generate a key When generating a key from a password, we need to take a string provided by the user and create an appropriately sized byte sequence; the method used must produce the same output for the same inputs. To do this we can use Crypto.Protocol.KDF.scrypt (API reference). scrypt allows us to generate a key of any length by simply passing a password and salt. ##### Generating a Salt A salt is random data that is used as an additional input to a one-way function that "hashes" data. ``` #!/usr/bin/env python3 from Crypto.Random import get_random_bytes salt = get_random_bytes(32) print(salt) ``` ``` ycheng@NUC10:~/Data/learn/python/gcm-encryption$ ./generate-a-salt.py b'\xfd\xde\xee\x19zx:\x99\xd1\x17N\xc6\xf2$h\xe7\xc9\xf9x\xb0\xe4\x1e\x9e\xd0\x92\xe36W\xf6\xb9\xaaL' ``` ##### Generating the key using scrypt ``` #!/usr/bin/env python3 from Crypto.Protocol.KDF import scrypt salt = b'\xfd\xde\xee\x19zx:\x99\xd1\x17N\xc6\xf2$h\xe7\xc9\xf9x\xb0\xe4\x1e\x9e\xd0\x92\xe36W\xf6\xb9\xaaL' password = 'mypassword123' key = scrypt(password, salt, key_len=32, N=2**17, r=8, p=1) print(key) ``` ``` ycheng@NUC10:~/Data/learn/python/gcm-encryption$ ./generate-a-key-using-scrypt.py b'\xe6N\xba\xc2\x0b\x02q\x800R\xa7\x95\x1c\x96?\xed,\xef\xc8`\xdd\xc7/\xac\xe05\x8d\xf0\x85O3\xe2' ``` As long as passing same salt and password, it generates same key. #### Source and Storage Planning Before we begin, we need to do a bit of planning of what is being encrypted (the source) and any transformations required, the inputs and outputs for both encryption and decryption and storing values we need to remember with the encrypted file. ##### Identifying your source and transformations ``` #!/usr/bin/env python3 import io my_bytes_object = b'\xfd\xde\xee\x19zx:\x99\xd1\x17N\xc6\xf2$h\xe7\xc9\xf9x\xb0\xe4\x1e\x9e\xd0\x92\xe36W\xf6\xb9\xaaL' file_object = io.BytesIO(my_bytes_object) print(file_object.read()) my_string_to_encrypt = 'My string to be encrypted!' my_file = io.BytesIO(my_string_to_encrypt.encode()) print(my_file.read().decode()) ``` ``` ycheng@NUC10:~/Data/learn/python/gcm-encryption$ ./convert-bytes-object-to-bytesIO.py b'\xfd\xde\xee\x19zx:\x99\xd1\x17N\xc6\xf2$h\xe7\xc9\xf9x\xb0\xe4\x1e\x9e\xd0\x92\xe36W\xf6\xb9\xaaL' My string to be encrypted! ``` ##### Encryption planning ![](https://i.imgur.com/HUtBEzE.png) 1. Generate a new salt. 2. Use **scrypt** to convert the salt and password into a key. 3. Open a new file and write the salt out. - We write the salt to the output file first as we will need it when decrypting later. - Putting it in this file allows us to keep the correct salt with the encrypted data. - Putting it at the top of the file means we can easily read it out before decrypting (we know the length as it's always the same). 4. Create a new AES encryption instance using the key. 5. Write the nonce out to the file. - The nonce is a random byte sequence generated by the instances of AES and is the start of the counter in CTR mode. - This is different so if the same key and file and encrypted together again, the encryption will be different. (**I am not pretty understand this, I think it means this nonce value keep changing through each encryption block.**) - Just like the salt, this is also stored at the top of the file so we can read it out again before decrypting to tell the CTR mode where to start counting from. 6. Read some data from the file into a buffer and then give it to the encryption instance. 7. Write the encrypted data to the file. - 6 and 7 are repeated over and over again until there is no more data coming from the source file. - We read small parts out of the file at a time so we don't have to load the whole file into memory. 8. Write the tag to the output file. - This is the authentication **code** produced from the Galois mode authentication. - This is used in the decryption phase to identify tampering/corruption. ##### Decryption planning ![](https://i.imgur.com/yhvA2q0.png) 1. Read the salt from the source file. - The salt we generated was 32 bytes long, so calling .read(32) will get the salt out of the encrypted file. 2. Use scrypt to convert the salt and password into a key again. 3. Read the nonce from the source file like we did for the salt. - AES GCM always generates a nonce that is 16 bytes long, so calling .read(16) will get the nonce out of the encrypted file. 4. Create a new AES decryption instance using the key and the nonce. 5. Read the encrypted file bit-by-bit and decrypt, then output each part to the output file. Leave the tag still in the file (16 bytes also) - Just like when we read the file slowly to encrypt 6. Finally, read the tag and verify the decryption. #### Encryption source code ``` Python 3.10.6 #!/usr/bin/env python3 import sys from Crypto.Random import get_random_bytes from Crypto.Cipher import AES from Crypto.Protocol.KDF import scrypt BUFFER_SIZE = 1024*1024 password = str(sys.argv[1]) input_filename = str(sys.argv[2]) output_filename = input_filename + '.encrypted' salt = get_random_bytes(32) # generate a salt key = scrypt(password, salt, key_len=32, N=2**17, r=8, p=1) with open(output_filename, 'wb') as file_out: file_out.write(salt) cipher = AES.new(key, AES.MODE_GCM) file_out.write(cipher.nonce) with open(input_filename, 'rb') as file_in: data = file_in.read(BUFFER_SIZE) while len(data) != 0: encrypted_data = cipher.encrypt(data) file_out.write(encrypted_data) data = file_in.read(BUFFER_SIZE) tag = cipher.digest() file_out.write(tag) ``` ``` ycheng@NUC10:~/Data/learn/python/gcm-encryption$ dd if=/dev/urandom of=./input_file bs=1024 count=4 4+0 records in 4+0 records out 4096 bytes (4.1 kB, 4.0 KiB) copied, 0.000561881 s, 7.3 MB/s ycheng@NUC10:~/Data/learn/python/gcm-encryption$ ./encryption.py password123 input_file ycheng@NUC10:~/Data/learn/python/gcm-encryption$ ls -l ./input_file* -rw-rw-r-- 1 ycheng ycheng 4096 Jan 3 16:22 ./input_file -rw-rw-r-- 1 ycheng ycheng 4160 Jan 3 16:50 ./input_file.encrypted ``` #### Decryption source code ``` Python 3.10.6 #!/usr/bin/env python3 import os import sys from Crypto.Cipher import AES from Crypto.Protocol.KDF import scrypt BUFFER_SIZE = 1024*1024 SALT_SIZE = 32 password = str(sys.argv[1]) input_filename = str(sys.argv[2]) output_filename = str(sys.argv[3]) with open(input_filename, 'rb') as file_in: salt = file_in.read(SALT_SIZE) key = scrypt(password, salt, key_len=32, N=2**17, r=8, p=1) nonce = file_in.read(16) cipher = AES.new(key, AES.MODE_GCM, nonce=nonce) filesize = os.path.getsize(input_filename) encrypted_data_size = filesize - 32 - 16 - 16 # total size - salt - nonce - tag = encrypted data size with open(output_filename, 'wb') as file_out: for _ in range(int(encrypted_data_size / BUFFER_SIZE)): data = file_in.read(BUFFER_SIZE) decrypted_data = cipher.decrypt(data) file_out.write(decrypted_data) data = file_in.read(int(encrypted_data_size % BUFFER_SIZE)) decrypted_data = cipher.decrypt(data) file_out.write(decrypted_data) tag = file_in.read(16) try: cipher.verify(tag) except ValueError as e: file_in.close() file_out.close() os.remove(output_filename) raise e ``` ``` ycheng@NUC10:~/Data/learn/python/gcm-encryption$ ./decryption.py password123 input_file.encrypted output_file.decrypted ycheng@NUC10:~/Data/learn/python/gcm-encryption$ ls -l ./output_file.decrypted -rw-rw-r-- 1 ycheng ycheng 4096 Jan 3 16:51 ./output_file.decrypted ``` **__NOTE__**: use same "password" to decrypt. **__NOTE__**: use "diff" or "cmp" to compare files. #### Terms The Advanced Encryption Standard (AES), also known by its original name Rijndael, is a specification for the encryption of electronic data established by the U.S. National Institute of Standards and Technology (NIST) in 2001. A rainbow table is a precomputed table for caching the output of cryptographic hash functions, usually for cracking password hashes. #### Reference https://nitratine.net/blog/post/python-gcm-encryption-tutorial/ https://nitratine.net/blog/post/python-encryption-and-decryption-with-pycryptodome/ https://en.wikipedia.org/wiki/Galois/Counter_Mode https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR) https://asecuritysite.com/encryption/aes_gcm https://github.com/wolf43/AES-GCM-example https://www.techtarget.com/searchsecurity/definition/nonce

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password
    or
    Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully