diff --git a/lib/aes.ex b/lib/aes.ex index 2b4b876..d8a7338 100644 --- a/lib/aes.ex +++ b/lib/aes.ex @@ -10,55 +10,97 @@ defmodule CA.AES do def readPEM(folder, name), do: hd(:public_key.pem_decode(e(2, :file.read_file(folder <> name)))) def shared(pub, key, scheme), do: :crypto.compute_key(:ecdh, pub, key, scheme) - def decryptAES256ECB(data, key, iv \\ :crypto.strong_rand_bytes(16)) do - :crypto.crypto_one_time(:aes_256_ecb,key,iv,data,[{:encrypt,false}]) + def decryptAES128GCM(data, key, _iv) do + <> = data + :crypto.crypto_one_time_aead(:aes_128_gcm, key, iv, bin, "AES256GCM", tag, false) end - def decryptAES256CBC(data, key, iv \\ :crypto.strong_rand_bytes(16)) do - :crypto.crypto_one_time(:aes_256_cbc,key,iv,data,[{:encrypt,false}]) + def decryptAES128CCM(data, key, _iv) do + <> = data + :crypto.crypto_one_time_aead(:aes_128_ccm, key, iv, bin, "AES256GCM", tag, false) end - def decryptAES256GCM(data, key, iv \\ :crypto.strong_rand_bytes(16)) do + def decryptAES256GCM(data, key, _iv) do <> = data - :crypto.crypto_one_time_aead(:aes_256_gcm, key, iv, data, "AES256GCM", tag, false) + :crypto.crypto_one_time_aead(:aes_256_gcm, key, iv, bin, "AES256GCM", tag, false) end - def decryptAES256CCM(data, key, iv \\ :crypto.strong_rand_bytes(16)) do + def decryptAES256CCM(data, key, _iv) do <> = data - :crypto.crypto_one_time_aead(:aes_256_ccm, key, iv, data, "AES256CCM", tag, false) + :crypto.crypto_one_time_aead(:aes_256_ccm, key, iv, bin, "AES256GCM", tag, false) + end + + def decryptAES256CBC(data, key, iv) do + :crypto.crypto_one_time(:aes_256_cbc,key,iv,data,[{:encrypt,false},{:padding,:pkcs_padding}]) + end + + def decryptAES128CBC(data, key, iv) do + :crypto.crypto_one_time(:aes_128_cbc,key,iv,data,[{:encrypt,false},{:padding,:pkcs_padding}]) + end + + def decryptAES256ECB(data, key, _iv) do + :crypto.crypto_one_time(:aes_256_ecb,key,data,[{:encrypt,false},{:padding,:pkcs_padding}]) + end + + def decryptAES128ECB(data, key, _iv) do + :crypto.crypto_one_time(:aes_128_ecb,key,data,[{:encrypt,false},{:padding,:pkcs_padding}]) + end + + def encryptAES256ECB(data, key, _iv) do + :crypto.crypto_one_time(:aes_256_ecb,key,data,[{:encrypt,true},{:padding,:pkcs_padding}]) end - def encryptAES256ECB(data, key, iv \\ :crypto.strong_rand_bytes(16)) do - :crypto.crypto_one_time(:aes_256_ecb,key,iv,data,[{:encrypt,true}]) + def encryptAES128ECB(data, key, _iv) do + :crypto.crypto_one_time(:aes_128_ecb,key,data,[{:encrypt,true},{:padding,:pkcs_padding}]) end - def encryptAES256CBC(data, key, iv \\ :crypto.strong_rand_bytes(16)) do - :crypto.crypto_one_time(:aes_256_cbc,key,iv,data,[{:encrypt,true}]) + def encryptAES256CBC(data, key, iv) do + :crypto.crypto_one_time(:aes_256_cbc,key,iv,data,[{:encrypt,true},{:padding,:pkcs_padding}]) end - def encryptAES256GCM(data, key, iv \\ :crypto.strong_rand_bytes(16)) do + def encryptAES128CBC(data, key, iv) do + :crypto.crypto_one_time(:aes_128_cbc,key,iv,data,[{:encrypt,true},{:padding,:pkcs_padding}]) + end + + def encryptAES256GCM(data, key, iv) do {cipher, tag} = :crypto.crypto_one_time_aead(:aes_256_gcm, key, iv, data, "AES256GCM", true) iv <> tag <> cipher end - def encryptAES256CCM(data, key, iv \\ :crypto.strong_rand_bytes(16)) do - {cipher, tag} = :crypto.crypto_one_time_aead(:aes_256_ccm, key, iv, data, "AES256CCM", true) + def encryptAES256CCM(data, key, iv) do + {cipher, tag} = :crypto.crypto_one_time_aead(:aes_256_ccm, key, iv, data, "AES256GCM", true) + iv <> tag <> cipher + end + + def encryptAES128GCM(data, key, iv) do + {cipher, tag} = :crypto.crypto_one_time_aead(:aes_128_gcm, key, iv, data, "AES256GCM", true) + iv <> tag <> cipher + end + + def encryptAES128CCM(data, key, iv) do + {cipher, tag} = :crypto.crypto_one_time_aead(:aes_128_ccm, key, iv, data, "AES256GCM", true) iv <> tag <> cipher end # public API is ASN.1 based - def encrypt(crypto_codec, data, key, iv \\ :crypto.strong_rand_bytes(16)) def encrypt(:'id-aes256-ECB', data, key, iv), do: encryptAES256ECB(data, key, iv) def encrypt(:'id-aes256-CBC', data, key, iv), do: encryptAES256CBC(data, key, iv) def encrypt(:'id-aes256-GCM', data, key, iv), do: encryptAES256GCM(data, key, iv) def encrypt(:'id-aes256-CCM', data, key, iv), do: encryptAES256CCM(data, key, iv) + def encrypt(:'id-aes128-GCM', data, key, iv), do: encryptAES128GCM(data, key, iv) + def encrypt(:'id-aes128-CCM', data, key, iv), do: encryptAES128CCM(data, key, iv) + def encrypt(:'id-aes128-CBC', data, key, iv), do: encryptAES128CBC(data, key, iv) + def encrypt(:'id-aes128-ECB', data, key, iv), do: encryptAES128ECB(data, key, iv) - def decrypt(crypto_codec, data, key, iv \\ :crypto.strong_rand_bytes(16)) def decrypt(:'id-aes256-ECB', data, key, iv), do: decryptAES256ECB(data, key, iv) def decrypt(:'id-aes256-CBC', data, key, iv), do: decryptAES256CBC(data, key, iv) def decrypt(:'id-aes256-GCM', data, key, iv), do: decryptAES256GCM(data, key, iv) def decrypt(:'id-aes256-CCM', data, key, iv), do: decryptAES256CCM(data, key, iv) + def decrypt(:'id-aes128-GCM', data, key, iv), do: decryptAES128GCM(data, key, iv) + def decrypt(:'id-aes128-CCM', data, key, iv), do: decryptAES128CCM(data, key, iv) + def decrypt(:'id-aes128-CBC', data, key, iv), do: decryptAES128CBC(data, key, iv) + def decrypt(:'id-aes128-ECB', data, key, iv), do: decryptAES128ECB(data, key, iv) def testSMIME() do {:ok,base} = :file.read_file "priv/encrypted.txt" ; [_,s] = :string.split base, "\n\n" @@ -74,8 +116,10 @@ defmodule CA.AES do check_BrainPoolP512t1_GCM256(), check_SECT571_GCM256(), check_X448_GCM256(), + check_X448_GCM128(), check_X448_CBC256(), - check_X448_ECB256(), + check_X448_CBC128(), + check_X448_ECB128(), ] :ok end @@ -88,6 +132,7 @@ defmodule CA.AES do maximK = privat "server.key" maximS = :binary.part(shared(aliceP,maximK,scheme),0,32) aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32) + true = aliceS == maximS iv = :crypto.strong_rand_bytes(16) x = encrypt(:'id-aes256-GCM', "Success!", maximS, iv) "Success!" = decrypt(:'id-aes256-GCM', x, aliceS, iv) @@ -98,8 +143,9 @@ defmodule CA.AES do scheme = :x25519 {aliceP,aliceK} = :crypto.generate_key(:ecdh, scheme) {maximP,maximK} = :crypto.generate_key(:ecdh, scheme) - maximS = shared(aliceP,maximK,scheme) - aliceS = shared(maximP,aliceK,scheme) + maximS = :binary.part(shared(aliceP,maximK,scheme),0,32) + aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32) + true = aliceS == maximS iv = :crypto.strong_rand_bytes(16) x = encrypt(:'id-aes256-GCM', "Success!", maximS, iv) "Success!" = decrypt(:'id-aes256-GCM', x, aliceS, iv) @@ -112,6 +158,7 @@ defmodule CA.AES do {maximP,maximK} = :crypto.generate_key(:ecdh, scheme) maximS = :binary.part(shared(aliceP,maximK,scheme),0,32) aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32) + true = aliceS == maximS iv = :crypto.strong_rand_bytes(16) x = encrypt(:'id-aes256-GCM', "Success!", maximS, iv) "Success!" = decrypt(:'id-aes256-GCM', x, aliceS, iv) @@ -124,45 +171,49 @@ defmodule CA.AES do {maximP,maximK} = :crypto.generate_key(:ecdh, scheme) maximS = :binary.part(shared(aliceP,maximK,scheme),0,32) aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32) + true = aliceS == maximS iv = :crypto.strong_rand_bytes(16) x = encrypt(:'id-aes256-GCM', "Success!", maximS, iv) "Success!" = decrypt(:'id-aes256-GCM', x, aliceS, iv) :ok end - def check_BrainPoolP512t1_GCM256() do # BrainPoolP512t1 - scheme = :brainpoolP512t1 + def check_SECT571_GCM256() do # SECT571r1 + scheme = :sect571r1 {aliceP,aliceK} = :crypto.generate_key(:ecdh, scheme) {maximP,maximK} = :crypto.generate_key(:ecdh, scheme) maximS = :binary.part(shared(aliceP,maximK,scheme),0,32) aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32) + true = aliceS == maximS iv = :crypto.strong_rand_bytes(16) x = encrypt(:'id-aes256-GCM', "Success!", maximS, iv) "Success!" = decrypt(:'id-aes256-GCM', x, aliceS, iv) :ok end - def check_SECT571_GCM256() do # SECT571r1 - scheme = :sect571r1 + def check_X448_GCM256() do # X488 + scheme = :x448 {aliceP,aliceK} = :crypto.generate_key(:ecdh, scheme) {maximP,maximK} = :crypto.generate_key(:ecdh, scheme) maximS = :binary.part(shared(aliceP,maximK,scheme),0,32) aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32) + true = aliceS == maximS iv = :crypto.strong_rand_bytes(16) x = encrypt(:'id-aes256-GCM', "Success!", maximS, iv) "Success!" = decrypt(:'id-aes256-GCM', x, aliceS, iv) :ok end - def check_X448_GCM256() do # X488 + def check_X448_GCM128() do # X488 scheme = :x448 {aliceP,aliceK} = :crypto.generate_key(:ecdh, scheme) {maximP,maximK} = :crypto.generate_key(:ecdh, scheme) - maximS = :binary.part(shared(aliceP,maximK,scheme),0,32) - aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32) + maximS = :binary.part(shared(aliceP,maximK,scheme),0,16) + aliceS = :binary.part(shared(maximP,aliceK,scheme),0,16) + true = aliceS == maximS iv = :crypto.strong_rand_bytes(16) - x = encrypt(:'id-aes256-GCM', "Success!", maximS, iv) - "Success!" = decrypt(:'id-aes256-GCM', x, aliceS, iv) + x = encrypt(:'id-aes128-GCM', "Success!", maximS, iv) + "Success!" = decrypt(:'id-aes128-GCM', x, aliceS, iv) :ok end @@ -172,19 +223,35 @@ defmodule CA.AES do {maximP,maximK} = :crypto.generate_key(:ecdh, scheme) maximS = :binary.part(shared(aliceP,maximK,scheme),0,32) aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32) - x = encrypt(:'id-aes256-CBC', "Success!", maximS) - "Success!" = decrypt(:'id-aes256-CBC', x, aliceS) + true = aliceS == maximS + iv = :crypto.strong_rand_bytes(16) + x = encrypt(:'id-aes256-CBC', "Success!", maximS, iv) + "Success!" = decrypt(:'id-aes256-CBC', x, aliceS, iv) :ok end - def check_X448_ECB256() do # X488 + def check_X448_CBC128() do # X488 scheme = :x448 {aliceP,aliceK} = :crypto.generate_key(:ecdh, scheme) {maximP,maximK} = :crypto.generate_key(:ecdh, scheme) - maximS = :binary.part(shared(aliceP,maximK,scheme),0,32) - aliceS = :binary.part(shared(maximP,aliceK,scheme),0,32) - x = encrypt(:'id-aes256-ECB', "Success!", maximS) - "Success!" = decrypt(:'id-aes256-ECB', x, aliceS) + maximS = :binary.part(shared(aliceP,maximK,scheme),0,16) + aliceS = :binary.part(shared(maximP,aliceK,scheme),0,16) + true = aliceS == maximS + iv = :crypto.strong_rand_bytes(16) + x = encrypt(:'id-aes128-CBC', "Success!", maximS, iv) + "Success!" = decrypt(:'id-aes128-CBC', x, aliceS, iv) + :ok + end + + def check_X448_ECB128() do # X488 + scheme = :x448 + {aliceP,aliceK} = :crypto.generate_key(:ecdh, scheme) + {maximP,maximK} = :crypto.generate_key(:ecdh, scheme) + maximS = :binary.part(shared(aliceP,maximK,scheme),0,16) + aliceS = :binary.part(shared(maximP,aliceK,scheme),0,16) + true = aliceS == maximS + x = encrypt(:'id-aes128-ECB', "Success!", maximS, "") + "Success!" = decrypt(:'id-aes128-ECB', x, aliceS, "") :ok end diff --git a/lib/ca.ex b/lib/ca.ex index f290824..0e7fe6f 100644 --- a/lib/ca.ex +++ b/lib/ca.ex @@ -22,7 +22,7 @@ defmodule CA do end def convertOTPtoPKIX(cert) do - {:Certificate,{:TBSCertificate,:v3,a,ai,rdn,v,rdn2,{p1,{p21,p22,pki},p3},b,c,ext},ai,code} = + {:Certificate,{:TBSCertificate,:v3,a,ai,rdn,v,rdn2,{p1,{p21,p22,_pki},p3},b,c,ext},ai,code} = :public_key.pkix_decode_cert(:public_key.pkix_encode(:OTPCertificate, cert, :otp), :plain) {:Certificate,{:TBSCertificate,:v3,a,ai,CA.CAdES.unsubj(rdn),v,CA.CAdES.unsubj(rdn2), {p1,{p21,p22,{:namedCurve,{1,3,132,0,34}}},p3},b,c,ext},ai,code} diff --git a/lib/cmc.ex b/lib/cmc.ex index cbe08d4..7edc371 100644 --- a/lib/cmc.ex +++ b/lib/cmc.ex @@ -29,7 +29,7 @@ defmodule CA.CMC do case :gen_tcp.recv(socket, 0) do {:ok, data} -> {:ok, dec} = :'EnrollmentMessageSyntax-2009'.decode(:'PKIData', data) - {:PKIData, controlSequence, reqSequence, cmsSequence, otherMsgSequence} = dec + {:PKIData, _controlSequence, _reqSequence, cmsSequence, _otherMsgSequence} = dec :io.format 'PKIData:~n~p~n', [dec] __MODULE__.message(socket, cmsSequence) loop(socket) diff --git a/lib/cmp.ex b/lib/cmp.ex index 47a2ce0..f2198af 100644 --- a/lib/cmp.ex +++ b/lib/cmp.ex @@ -17,21 +17,20 @@ defmodule CA.CMP do end def baseKey(pass, salt, iter), do: - :lists.foldl(fn _, acc -> :crypto.hash(:sha256, acc) end, pass <> salt, :lists.seq(1,iter)) + :lists.foldl(fn _, acc -> + :crypto.hash(:sha256, acc) end, pass <> salt, + :lists.seq(1,iter)) def validateProtection(header, body, code) do - {:PKIHeader, pvno, from, to, messageTime, {_,oid,{_,param}} = protectionAlg, senderKID, recipKID, - transactionID, senderNonce, recipNonce, freeText, generalInfo} = header - {oid, salt, owf, mac, counter} = protection(protectionAlg) + {:PKIHeader, _, _, _, _, protectionAlg, _, _, _, _, _, _, _} = header + {_oid, salt, _owf, _mac, counter} = protection(protectionAlg) incomingProtection = CA."ProtectedPart"(header: header, body: body) {:ok, bin} = :"PKIXCMP-2009".encode(:'ProtectedPart', incomingProtection) verifyKey = baseKey(:application.get_env(:ca, :pbm, "0000"), salt, counter) :crypto.mac(:hmac, CA.KDF.hs(:erlang.size(code)), verifyKey, bin) end - def message(socket, header, {:ir, req} = body, code) do - {:PKIHeader, pvno, from, to, messageTime, {_,oid,{_,param}} = protectionAlg, senderKID, recipKID, - transactionID, senderNonce, recipNonce, freeText, generalInfo} = header + def message(_socket, _header, {:ir, req}, _) do :lists.map(fn {:CertReqMsg, req, sig, code} -> :io.format 'request: ~p~n', [req] :io.format 'signature: ~p~n', [sig] @@ -39,17 +38,13 @@ defmodule CA.CMP do end, req) end - def message(socket, header, {:genm, req} = body, code) do - {:PKIHeader, pvno, from, to, messageTime, {_,oid,{_,param}} = protectionAlg, senderKID, recipKID, - transactionID, senderNonce, recipNonce, freeText, generalInfo} = header - {:ok, parameters} = :"PKIXCMP-2009".decode(:'PBMParameter', param) - {:PBMParameter, salt, {_,owf,_}, counter, {_,mac,_} } = parameters + def message(_socket, _header, {:genm, req} = _body, _code) do :io.format 'generalMessage: ~p~n', [req] end def message(socket, header, {:p10cr, csr} = body, code) do - {:PKIHeader, pvno, from, to, messageTime, protectionAlg, senderKID, recipKID, - transactionID, senderNonce, recipNonce, freeText, generalInfo} = header + {:PKIHeader, pvno, from, to, messageTime, protectionAlg, _senderKID, _recipKID, + transactionID, senderNonce, _recipNonce, _freeText, _generalInfo} = header code = validateProtection(header, body, code) {ca_key, ca} = CA.CSR.read_ca() @@ -63,7 +58,7 @@ defmodule CA.CMP do [ CA."CertResponse"(certReqId: 0, certifiedKeyPair: CA."CertifiedKeyPair"(certOrEncCert: {:certificate, {:x509v3PKCert, CA.convertOTPtoPKIX(cert)}}), - status: CA."PKIStatusInfo"(status: 1))]) + status: CA."PKIStatusInfo"(status: 0))]) pkibody = {:cp, reply} pkiheader = CA."PKIHeader"(sender: to, recipient: from, pvno: pvno, recipNonce: senderNonce, @@ -71,7 +66,7 @@ defmodule CA.CMP do answer(socket, pkiheader, pkibody, validateProtection(pkiheader, pkibody, code)) end - def message(socket, header, {:certConf, statuses} = body, code) do + def message(socket, header, {:certConf, statuses}, code) do {:PKIHeader, _, from, to, _, _, _, _, _, senderNonce, _, _, _} = header :lists.map(fn {:CertStatus,bin,no,{:PKIStatusInfo, :accepted, _, _}} -> @@ -108,10 +103,10 @@ defmodule CA.CMP do def loop(socket) do case :gen_tcp.recv(socket, 0) do {:ok, data} -> - {{_,headers},asn} = :asn1rt_nif.decode_ber_tlv(data) + {{_,_headers},asn} = :asn1rt_nif.decode_ber_tlv(data) [_,body] = :string.split asn, "\r\n\r\n", :all {:ok,dec} = :'PKIXCMP-2009'.decode(:'PKIMessage', body) - {:PKIMessage, header, body, code, extra} = dec + {:PKIMessage, header, body, code, _extra} = dec __MODULE__.message(socket, header, body, code) loop(socket) {:error, :closed} -> :exit