Como funciona a criptografia moderna com Go
A criptografia remonta aos dias em que os antigos gregos e romanos enviavam mensagens secretas substituindo letras decifráveis por apenas chaves. Participe da nossa rápida lição de história para saber mais sobre como a criptografia funciona.
Na nota HTG de hoje, daremos um breve histórico da criptografia, como ela funciona e alguns exemplos de diferentes tipos de criptografia – não deixe de conferir a edição anterior, onde explicamos por que tantos geeks odeiam o IE.
Tipos de criptografia
Portanto, a criptografia é uma ferramenta indispensável para proteger nossa privacidade de olhares indiscretos.
Segurança nunca é demais, certo? Então, quando se trata do mundo digital, é preciso prestar mais atenção.
Pensando nisso, foi elaborado este artigo que foi divido em três partes para melhor entendimento de como funciona a Criptografia moderna:
Função de hash criptográficas;
Criptografia de chave simétrica;
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 uma entrada, geralmente um fluxo de bytes de tamanho arbitrário, e computam ou agregam essa entrada em uma saída de tamanho fixo.
Essa string de comprimento fixo deve ser exclusiva para cada entrada que colocamos nessa função.
A saída é chamada de “hash”, “digestão de mensagem”, “impressão digital digital”, “digestão” ou “soma de verificação”.
Para simplificar o entendimento, a tradução mais famosa em português é “resumo”.
Esse recurso é a base de todos os sistemas criptográficos modernos – e é assim que a criptografia moderna funciona no núcleo – os sistemas que são usados em nossas comunicações digitais hoje.
A função hash ideal tem 3 propriedades principais:
Calcular o hash de qualquer valor de entrada deve ser muito fácil em termos de poder de computação.
Dado que o invasor só tem saída, deve ser muito difícil calcular o poder computacional da entrada.
É extremamente improvável que duas mensagens diferentes gerem o mesmo hash de saída, ou seja, colisões de hash devem ser difíceis de encontrar.
Exemplo de 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 de criptografia no qual a mesma chave é usada para criptografar e descriptografar as mensagens que queremos proteger.
Essa chave, também conhecida como chave compartilhada, precisa ser trocada entre os participantes que transmitirão informações com segurança entre si.
A desvantagem é que qualquer pessoa com a chave pode acessar informações criptografadas com essa chave.
Portanto, o envio de chaves entre os participantes deve ocorrer em um ambiente confidencial 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("blogPostBlogblogPostGeekHu") 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("blogPostBlogblogPostGeekHu") 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 usa um par de chaves.
Nesse caso, uma é chamada de chave pública distribuível e a outra é chamada de chave privada, que somente o proprietário pode conhecer.
Usando esta chave privada, o usuário pode assinar mensagens.
Isso significa que ele criará um token digital exclusivo que comprova que o usuário realizou essa assinatura e, usando essa chave privada, ele também poderá descriptografar mensagens criptografadas que foram enviadas especificamente a ele.
Usando a chave pública do mesmo usuário, outro participante pode verificar a assinatura acima.
Isso prova que o usuário executou a ação e conseguiu criptografar as mensagens com esse usuário, que tem a chave privada como destinatário.
Dessa forma, evitamos o problema de criptografia simétrica da troca de chaves entre os participantes.
Este sistema é uma parte fundamental de muitos dos sistemas de segurança que temos hoje em todo o mundo, incluindo a maior parte da Internet.
Uma desvantagem é que requer mais poder de computação para gerar chaves e usá-las.
As mensagens também ocupam mais bytes de espaço, o que muitas vezes impede o uso desse sistema de criptografia 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("blogPostBlog") 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("blogPostBlog") 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() }
Conclusão
A partir desses trechos de código, você pode iniciar mais facilmente sua pesquisa e implementação de criptografia usando essa linguagem muito poderosa.
Espero que tenha gostado do texto sobre como funciona a criptografia em Go, caso tenha alguma dúvida entre em contato conosco sobre este tema ou similar.