1. Início
  2. Back-end
  3. Como funciona a criptografia moderna com Go

Como funciona a criptografia moderna com Go

como funciona a criptografia

Olá pessoal, neste segundo texto irei abordar como funciona a criptografia e seus conceitos teóricos demonstrando também esses conceitos na prática utilizando GoLang.

Se ainda não conhece esta linguagem você pode ler meu último artigo sobre tutorial GoLang: por onde começar com a linguagem de programação Go.

O que é criptografia?

De forma direta, a criptografia funciona como um modelo de segurança que ajuda na proteção de todos os conteúdos transmitidos entre duas ou mais fontes, a criptografia de dados, evitando a intercepção por alguma fonte indesejada.

Hoje em dia, uma grande parte da informação mundial é transmitida na forma digital e tornar os arquivos ininteligível é fundamental para a segurança dos dados, principalmente quando a informação é sensível.

Por causa disso, informações privadas de cidadãos e empresas, são vulneráveis à ataques de atores maliciosos sejam eles privados ou à serviço de governos.

Tipos de criptografia

Logo, a criptografia é uma ferramenta indispensável para proteger nossa privacidade de olhos curiosos.

Segurança nunca é demais, certo? Quando o assunto é o mundo digital então, o cuidado deve ser redobrado.

Pensando nisso, foi elaborado este artigo que foi divido em três partes para melhor entendimento de como funciona a Criptografia moderna:

  1. Função de hash criptográficas;
  2. Criptografia de chave simétrica;
  3. Criptografia assimétrica ou criptografia de chave pública.

Como funciona a função de hash criptográfica

São funções computacionais ou algoritmos de computador, que recebem um input, que é geralmente um stream de bytes de qualquer tamanho e computa ou resume esse input em um output de tamanho fixo.

Essa string de tamanho fixo tem de ser única para cada input que nós colocamos nessa função.

O output é chamado de ‘hash value’, ‘message digest’, ‘digital fingerprint’, ‘digest’ or ‘checksum’.

Simplificando o entendimento, em português a tradução mais conhecida é ‘resumo’.

Esta função é a base de fundação para todos os sistemas criptográficos modernos – é assim que a criptografia moderna funciona em sua essência – estes que são usadas nos dias de hoje nas nossas comunicações digitais.

A função hash ideal tem 3 propriedades principais:

  1. Tem de ser extremamente fácil em termos de poder computacional para calcular o valor hash de qualquer valor arbitrário de input.
  2. Tem de ser extremamente difícil em termos de poder computacional para calcular o input dado que o atacante só tenha o output.
  3. Tem de ser extremamente improvável que duas mensagens diferentes gerem o mesmo hash de output, em outras palavras, deve ser difícil achar colisões de hashes.

Exemplo do Hash SHA2-256 escrito em Go:

package main


import (
 "crypto/sha256"
 "fmt"
)

func main() {
 sum := sha256.Sum256([]byte("Criptografia moderna usando linguagem Go"))
 fmt.Printf("%x", sum)
}

Como funciona a criptografia de chave simétrica

A criptografia de chave simétrica é um sistema criptográfico que a mesma chave é utilizada para cifrar e também para decifrar as mensagens que desejamos proteger.

Esta chave também é conhecida como segredo compartilhado que precisa ser trocado entre os participantes que irão transmitir entre si as informações de maneira segura.

O ponto negativo é que qualquer um que possuir a chave terá acesso às informações cifradas utilizando aquela chave.

Portanto o envio da chave entre os participantes deve se dar em um ambiente secreto e protegido.

Exemplo de código de AES-GCM na linguagem Go:

package main

import (
	"crypto/aes"
	"crypto/cipher"
	"encoding/hex"
	"fmt"
)

func encrypt() {
	key := []byte("blogPostGeekHunterblogPostGeekHu")
	plaintext := []byte("Este é o texto plano a ser cifrado")
	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err.Error())
	}
	nonce := []byte("blogPostGeek")
	aesgcm, err := cipher.NewGCM(block)
	if err != nil {
		panic(err.Error())
	}
	ciphertext := aesgcm.Seal(nil, nonce, plaintext, nil)
	fmt.Printf("Ciphertext: %x\n", ciphertext)
}

func decrypt() {
	key := []byte("blogPostGeekHunterblogPostGeekHu")
	ciphertext, _ := hex.DecodeString("839a362d3d61d1c2987c73d751058a50dfe39bcd06cd0cdbcd29f3b0a06368874aa2ba8fe7c9f386d77ed5a554e0f17307ec9b")
	nonce := []byte("blogPostGeek")
	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err.Error())
	}
	aesgcm, err := cipher.NewGCM(block)
	if err != nil {
		panic(err.Error())
	}
	plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)
	if err != nil {
		panic(err.Error())
	}
	fmt.Printf("Plaintext: %s\n", string(plaintext))
}

func main() {
	encrypt()
	decrypt()
}

Como funciona a criptografia de chave pública

A criptografia de chave pública é um sistema criptográfico que utiliza um par de chaves.

No caso, é chamada de chave pública e que pode ser distribuída e outra chamada de chave privada que somente deve ser conhecida pelo dono.

Com esta chave chave privada um usuário pode assinar uma mensagem.

Isto quer dizer que ele criará uma marca digital única que prova que aquele usuário realizou aquela assinatura, também poderá com esta chave privada decifrar mensagens cifradas enviadas especificamente para ele.

Já com a chave pública deste mesmo usuário, um outro participante pode verificar a assinatura acima.

Isso prova que foi aquele usuário que a realizou como também poderá cifrar uma mensagem que tem aquele usuário possuidor daquela chave privada como destinatário.

Assim evitamos o problema da criptografia simétrica de troca de chave entre os participantes.

Este sistema é parte fundamental de muitos sistemas seguros que temos hoje no mundo todo, inclusive em boa parte da internet.

Um lado negativo é que precisa de mais poder computacional para gerar as chaves e usá-las.

As mensagens também ocupam mais espaço em bytes, o que muitas vezes pode impedir o uso desse sistema criptográfico em sistemas digitais com recursos computacionais limitados.

Exemplo de código utilizando par de chaves RSA na linguagem Go:

package main

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"fmt"
	"io"
	"os"
) // RSA

const (
	rsaKeySize = 2048
)

type keypair struct {
	priv *rsa.PrivateKey
	pub  *rsa.PublicKey
}

var kp keypair
var ciphertext, signedMessage []byte
var hashed [32]byte
var rng io.Reader

func generateKeypair() error {

	var err error
	kp.priv, err = rsa.GenerateKey(rand.Reader, rsaKeySize)
	if err != nil {
		return err
	}

	kp.pub = &kp.priv.PublicKey
	return nil
}

func encrypt() {

	var err error

	secretMessage := []byte("This is the plaintext to be encrypted")

	label := []byte("blogPostGeekHunter")

	ciphertext, err = rsa.EncryptOAEP(sha256.New(), rng, kp.pub, secretMessage, label)

	if err != nil {
		fmt.Fprintf(os.Stderr, "Error from encryption: %s\n", err)
		return
	} // Since encryption is a randomized function, ciphertext will be
	// different each time.
	fmt.Printf("Ciphertext: %x\n", ciphertext)
}
func decrypt() {
	label := []byte("blogPostGeekHunter")
	plaintext, err := rsa.DecryptOAEP(sha256.New(), rng, kp.priv, ciphertext, label)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error from decryption: %s\n", err)
		return
	}

	fmt.Printf("Plaintext: %s\n", string(plaintext))
}

func sign() {

	var err error
	message := []byte("This is the plaintext to be signed")
	hashed = sha256.Sum256(message)
	signedMessage, err = rsa.SignPKCS1v15(rng, kp.priv, crypto.SHA256, hashed[:])
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error from encryption: %s\n", err)
		return
	}
	fmt.Printf("Signed Message: %x\n", signedMessage)
}

func verify() {
	err := rsa.VerifyPKCS1v15(kp.pub, crypto.SHA256, hashed[:], signedMessage)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error from decryption: %s\n", err)
		return
	}
	fmt.Printf("Message verified!")
}

func main() { // crypto/rand.Reader is a good source of entropy for randomizing    // encryption function.
	rng = rand.Reader // generates pair of keys
	generateKeypair() // encrypt message
	encrypt()         // decrypt message
	decrypt()         // sign message
	sign()            // verify message
	verify()
}

>> Você desenvolvedor, encontre vagas para desenvolvedores em Go na GeekHunter

Conclusão

À partir desses trechos de códigos, ficará mais fácil pra você começar seus estudos e implementações criptográficas utilizando esta linguagem tão poderosa.

Espero que tenham curtido o texto sobre como funciona a criptografia em Go e qualquer dúvida entrem em contato para batermos um papo sobre esse ou assuntos similares.

Abraços e até a próxima!

Categorias

Leituras Recomendadas

Quer receber conteúdos incríveis como esses?

Assine nossa newsletter para ficar por dentro de todas as novidades do universo de TI e carreiras tech.