gcm | helps developers send data from ruby backend servers
kandi X-RAY | gcm Summary
Support
Quality
Security
License
Reuse
Currently covering the most popular Java, JavaScript and Python libraries. See a Sample Here
gcm Key Features
gcm Examples and Code Snippets
pip install pycryptodome
from Crypto.Cipher import AES import binascii, os def encrypt_AES_GCM(msg, secretKey): aesCipher = AES.new(secretKey, AES.MODE_GCM) ciphertext, authTag = aesCipher.encrypt_and_digest(msg) return (ciphertext, aesCipher.nonce, authTag) def decrypt_AES_GCM(encryptedMsg, secretKey): (ciphertext, nonce, authTag) = encryptedMsg aesCipher = AES.new(secretKey, AES.MODE_GCM, nonce) plaintext = aesCipher.decrypt_and_verify(ciphertext, authTag) return plaintext secretKey = os.urandom(32) # 256-bit random encryption key print("Encryption key:", binascii.hexlify(secretKey)) msg = b'Message for AES-256-GCM + Scrypt encryption' encryptedMsg = encrypt_AES_GCM(msg, secretKey) print("encryptedMsg", { 'ciphertext': binascii.hexlify(encryptedMsg[0]), 'aesIV': binascii.hexlify(encryptedMsg[1]), 'authTag': binascii.hexlify(encryptedMsg[2]) }) decryptedMsg = decrypt_AES_GCM(encryptedMsg, secretKey) print("decryptedMsg", decryptedMsg)
Encryption key: b'233f8ce4ac6aa125927ccd98af5750d08c9c61d98a3f5d43cbf096b4caaebe80' encryptedMsg {'ciphertext': b'1334cd5d487f7f47924187c94424a2079656838e063e5521e7779e441aa513de268550a89917fbfb0492fc', 'aesIV': b'2f3849399c60cb04b923bd33265b81c7', 'authTag': b'af453a410d142bc6f926c0f3bc776390'} decryptedMsg b'Message for AES-256-GCM + Scrypt encryption'
encryptedMsg = (b'wrong chiphertext', encryptedMsg[1], encryptedMsg[2]) decryptedMsg = decrypt_AES_GCM(encryptedMsg, secretKey) # ValueError: MAC check failed
from Crypto.Cipher import AES import scrypt, os, binascii def encrypt_AES_GCM(msg, password): kdfSalt = os.urandom(16) secretKey = scrypt.hash(password, kdfSalt, N=16384, r=8, p=1, buflen=32) aesCipher = AES.new(secretKey, AES.MODE_GCM) ciphertext, authTag = aesCipher.encrypt_and_digest(msg) return (kdfSalt, ciphertext, aesCipher.nonce, authTag) def decrypt_AES_GCM(encryptedMsg, password): (kdfSalt, ciphertext, nonce, authTag) = encryptedMsg secretKey = scrypt.hash(password, kdfSalt, N=16384, r=8, p=1, buflen=32) aesCipher = AES.new(secretKey, AES.MODE_GCM, nonce) plaintext = aesCipher.decrypt_and_verify(ciphertext, authTag) return plaintext msg = b'Message for AES-256-GCM + Scrypt encryption' password = b's3kr3tp4ssw0rd' encryptedMsg = encrypt_AES_GCM(msg, password) print("encryptedMsg", { 'kdfSalt': binascii.hexlify(encryptedMsg[0]), 'ciphertext': binascii.hexlify(encryptedMsg[1]), 'aesIV': binascii.hexlify(encryptedMsg[2]), 'authTag': binascii.hexlify(encryptedMsg[3]) }) decryptedMsg = decrypt_AES_GCM(encryptedMsg, password) print("decryptedMsg", decryptedMsg)
encryptedMsg {'kdfSalt': b'2dd0b783290747ba62a63fc53591170d', 'ciphertext': b'223ed888dcd216dcd40c47ff7cdaa7fd7eab65f4f0405350a43c5cad5b6b47b527c709edec29d7d6967518', 'aesIV': b'7f114d946c77508ed2e6afe652c78f21', 'authTag': b'e84a14b9542320a0b1473141c989c48f'} decryptedMsg b'Message for AES-256-GCM + Scrypt encryption'
public byte[][] gcmEncrypt(SecretKey key, byte[] iv, byte[] data) throws GeneralSecurityException { Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, iv)); byte[] ciphertext = cipher.doFinal(data); return new byte[][] { iv, ciphertext }; }
public byte[] gcmDecrypt(SecretKey key, byte[] iv, byte[] ciphertext) throws GeneralSecurityException { Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(128, iv)); byte[] plaintext = cipher.doFinal(ciphertext); return plaintext; }
Trending Discussions on gcm
Trending Discussions on gcm
QUESTION
I know there are some other questions (with answers) to this topic. But no of these was helpful for me.
I have a postfix server (postfix 3.4.14 on debian 10) with following configuration (only the interesting section):
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_exclude_ciphers = aNULL, LOW, EXP, MEDIUM, ADH, AECDH, MD5, DSS, ECDSA,
CAMELLIA128, 3DES, CAMELLIA256, RSA+AES, eNULL
smtp_tls_exclude_ciphers = aNULL, LOW, EXP, MEDIUM, ADH, AECDH, MD5, DSS, ECDSA,
CAMELLIA128, 3DES, CAMELLIA256, RSA+AES, eNULL
tls_preempt_cipherlist = yes
tls_high_cipherlist = !aNULL:!eNULL:!CAMELLIA:HIGH:@STRENGTH
If I check the configuration with openssl I get (please note that I have made the domain name unrecognizable with "xxxxxx.de"):
#> openssl s_client -connect xxxxxx.de:25 -starttls smtp
CONNECTED(00000003)
depth=3 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = xxxxxx.de
verify return:1
---
Certificate chain
0 s:/CN=xxxxxx.de
i:/C=US/O=Let's Encrypt/CN=R3
1 s:/C=US/O=Let's Encrypt/CN=R3
i:/C=US/O=Internet Security Research Group/CN=ISRG Root X1
2 s:/C=US/O=Internet Security Research Group/CN=ISRG Root X1
i:/O=Digital Signature Trust Co./CN=DST Root CA X3
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFRjCCBC6gAwIBAgISA6SNmc1MPKtxwSiNNKEvxc/EMA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
...
...
...
VG2iG8sEGCcgG4w1LnWTO4tMlCYFE+tcXxAfE/7pB/VjmvRZlLCypanuwBzVRw5W
bPwabUtCMRDrRlT8wI9UHAhQYTb5Hhm0F0u1hi6e/7fybK6tuFnPpWs/vgT3Z4Fj
2onoaTHk/rKlhQ==
-----END CERTIFICATE-----
subject=/CN=xxxxxx.de
issuer=/C=US/O=Let's Encrypt/CN=R3
---
No client certificate CA names sent
Peer signing digest: SHA256
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 4950 bytes and written 450 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: B20E725616C98083988847B90FB42BFDCAEED745129C53E79E723692C641F6F5
Session-ID-ctx:
Master-Key: A3D2C497E11E47C6260C119E47DC3B4CAA119485EAFA5BCF6CDA882F115D80E78960C802A48E375DAA293A3A2C1DAE35
Key-Arg : None
Krb5 Principal: None
PSK identity: None
PSK identity hint: None
TLS session ticket lifetime hint: 7200 (seconds)
TLS session ticket:
0000 - ec 40 39 d6 f4 94 ac 7b-d8 f8 ef 94 98 62 d7 35 .@9....{.....b.5
0010 - de fb c3 f5 f3 b1 3a d1-24 3e 62 57 fb 06 56 eb ......:.$>bW..V.
0020 - 84 61 2a 0d 30 7d 9f ac-70 e7 a8 a3 23 4a c6 57 .a*.0}..p...#J.W
0030 - dc 21 7c d3 5d f4 e8 14-c5 4c 18 da 35 1d 32 49 .!|.]....L..5.2I
0040 - f0 19 de 75 77 22 25 f9-74 4d a2 47 39 0d ce 75 ...uw"%.tM.G9..u
0050 - 0a 04 41 85 0d 67 05 fe-a4 09 ec 72 4b a5 ad f4 ..A..g.....rK...
0060 - 8b 73 a2 a3 2e 28 46 b8-2a 60 4b ed ce 75 09 fb .s...(F.*`K..u..
0070 - ef 95 e3 e2 6e 6a 90 bd-9e 46 e8 c9 aa 52 c3 ae ....nj...F...R..
0080 - 72 6f 9f 37 fd 6c 12 e9-bb 60 83 c6 c4 44 ca 85 ro.7.l...`...D..
0090 - cb ee 1d bd 69 29 77 31-4f 96 d5 4d 93 8e 63 d2 ....i)w1O..M..c.
Start Time: 1623221077
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
250 CHUNKING
Here I'm wondering about the line
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
because TLSv1/SSLv3 should be disabled by the postfix configuration. Could be that the probelm?
However. On the Client side I have a Java application (openJDK 11.0.11) and every time I will send an E-Mail I get:
javax.mail.MessagingException: Could not convert socket to TLS;
nested exception is:
javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1907)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:666)
at javax.mail.Service.connect(Service.java:295)
...
Of course, I have already edit the conf/security/java.security
file. I have added already ECDHE-RSA-AES256-GCM-SHA384
as jdk.tls.legacyAlgorithms
. Here the interesting settings from java.securtity
:
jdk.tls.legacyAlgorithms= \
K_NULL, C_NULL, M_NULL, \
DH_anon, ECDH_anon, \
RC4_128, RC4_40, DES_CBC, DES40_CBC, \
3DES_EDE_CBC, ECDHE-RSA-AES256-GCM, ECDHE-RSA-AES256-GCM-SHA384
jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \
RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224, \
include jdk.disabled.namedCurves
jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
include jdk.disabled.namedCurves
May be I'm blind, but I don't see where my problem is ...
EDIT
Ok, at first I have removed my extensions from jdk.tls.legacyAlgorithms
because this are not helpful and wrong (thanks to dave_thompson_085 for the hint).
Here are the Java code for sending the emails (the code has a "long" history so please don't wonder why there are Vector
instead of ArrayList
or so was used...)
// create some properties and get the default Session
Properties props = new Properties();
props.put("mail.smtp.host", smtpServer);
props.put("mail.smtp.port", "25");
props.put("mail.debug", "true");
// SMTP AUTH?
Session session;
if (username != null && pwd != null && username.length() > 0 && pwd.length() > 0) {
props.put("mail.smtp.auth", "true");
// props.put("mail.smtp.user", username);
// props.put("mail.password", pwd);
// if SMTP AUTH: use in every case TLS!
tls = true;
session = Session.getInstance(props, new MyPasswordAuthenticator(username, pwd));
} else {
session = Session.getDefaultInstance(props, null);
}
// TLS?
if (tls) {
props.put("mail.smtp.starttls.enable", "true");
// props.put("mail.smtp.tls", "true");
}
// create a message
SMTPMessage mimeMsg = new SMTPMessage(session);
InternetAddress addressFrom = new InternetAddress(sender);
mimeMsg.setFrom(addressFrom);
mimeMsg.setEnvelopeFrom(sender);
// set recipients ...
InternetAddress[] tos = new InternetAddress[receivers.size()];
int i = 0;
for (String addr : receivers) {
tos[i++] = new InternetAddress(addr, extractPersonalNameFromEMailAddr(addr));
}
// set cc recipients ...
InternetAddress[] ccAddrs = new InternetAddress[0];
if (ccs != null) {
ccAddrs = new InternetAddress[ccs.size()];
i = 0;
for (String addr : ccs) {
ccAddrs[i++] = new InternetAddress(addr, extractPersonalNameFromEMailAddr(addr));
}
}
mimeMsg.setRecipients(Message.RecipientType.TO, tos);
mimeMsg.setRecipients(Message.RecipientType.CC, ccAddrs);
// set return notifications
if (readNotificationRequest) {
String notifyAddr = replyTo;
if (notifyAddr == null || notifyAddr.trim().length() == 0) notifyAddr = sender;
mimeMsg.addHeader("Disposition-Notification-To", "<" + notifyAddr + ">");
mimeMsg.addHeader("Return-Receipt-To", "<" + notifyAddr + ">");
}
mimeMsg.addHeader("Date", mailDateFormat.format(new Date()));
mimeMsg.setNotifyOptions(deliverNotificationRequest);
mimeMsg.setReturnOption(deliverNotificationContent);
if (replyTo != null) {
Address[] replyToAddrs = new Address[1];
replyToAddrs[0] = new InternetAddress(this.replyTo);
mimeMsg.setReplyTo(replyToAddrs);
mimeMsg.setFrom(replyToAddrs[0]);
}
mimeMsg.setSentDate(new Date());
mimeMsg.setSubject(subject);
// mimeMsg.setContent(msg, msgType);
// set the text content:
MimeBodyPart msgPart = new MimeBodyPart();
msgPart.setContent(msg, msgType + "; charset=" + charset);
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(msgPart);
// add the attachments:
String attFile;
MimeBodyPart attachment;
Iterator it = new Vector(attachments).iterator();
while (it.hasNext()) {
attFile = it.next();
attachment = new MimeBodyPart();
attachment.setDataHandler(new DataHandler(new AppOctetStreamFileDataSource(attFile)));
attachment.setFileName(FileUtil.extractFilename(attFile));
multipart.addBodyPart(attachment);
}
mimeMsg.setContent(multipart);
System.out.println("mail.smtp.ssl.trust: <<" + System.getProperty("mail.smtp.ssl.trust") + ">>");
System.out.println("mail.smtp.ssl.socketfactory.class: <<" + System.getProperty("mail.smtp.ssl.socketfactory.class") + ">>");
System.out.println("mail.smtp.socketfactory.class: <<" + System.getProperty("mail.smtp.socketfactory.class") + ">>");
System.out.println("mail.smtp.ssl.protocols: <<" + System.getProperty("mail.smtp.ssl.protocols") + ">>");
System.out.println("mail.smtp.ssl.ciphersuites: <<" + System.getProperty("mail.smtp.ssl.ciphersuites") + ">>");
System.out.println("SSLContext.getDefault().getDefaultSSLParameters().getProtocols(): "
+ Arrays.toString(SSLContext.getDefault().getDefaultSSLParameters().getProtocols()));
System.out.println("Arrays.toString(SSLContext.getDefault().getDefaultSSLParameters().getCipherSuites(): "
+ Arrays.toString(SSLContext.getDefault().getDefaultSSLParameters().getCipherSuites()));
session.setDebug(debug);
Transport transport = session.getTransport("smtp");
transport.connect(smtpServer, 25, username, pwd);
//System.out.println("#########" + System.getProperty("mail.smtp.localhost"));
transport.sendMessage(mimeMsg, mimeMsg.getAllRecipients());
transport.close();
For debugging I have add some System.out's for output the some interesting values.
Here the stdout
output:
DEBUG: JavaMail version 1.4.7
DEBUG: successfully loaded resource: /META-INF/javamail.default.providers
DEBUG: Tables of loaded providers
DEBUG: Providers Listed By Class Name: {com.sun.mail.smtp.SMTPSSLTransport=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], com.sun.mail.smtp.SMTPTransport=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle], com.sun.mail.imap.IMAPSSLStore=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], com.sun.mail.pop3.POP3SSLStore=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], com.sun.mail.imap.IMAPStore=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], com.sun.mail.pop3.POP3Store=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle]}
DEBUG: Providers Listed By Protocol: {imaps=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], imap=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], smtps=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], pop3=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle], pop3s=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], smtp=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]}
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
mail.smtp.ssl.trust: <>
mail.smtp.ssl.socketfactory.class: <>
mail.smtp.socketfactory.class: <>
mail.smtp.ssl.protocols: <>
mail.smtp.ssl.ciphersuites: <>
SSLContext.getDefault().getDefaultSSLParameters().getProtocols(): [TLSv1.3, TLSv1.2]
Arrays.toString(SSLContext.getDefault().getDefaultSSLParameters().getCipherSuites(): [TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
and the stderr
:
javax.net.ssl|DEBUG|01|main|2021-06-10 08:28:39.042 CEST|SSLCipher.java:438|jdk.tls.keyLimits: entry = AES/GCM/NoPadding KeyUpdate 2^37. AES/GCM/NOPADDING:KEYUPDATE = 137438953472
javax.net.ssl|ERROR|01|main|2021-06-10 08:28:39.306 CEST|TransportContext.java:341|Fatal (HANDSHAKE_FAILURE): Couldn't kickstart handshaking (
"throwable" : {
javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
at java.base/sun.security.ssl.HandshakeContext.(HandshakeContext.java:170)
at java.base/sun.security.ssl.ClientHandshakeContext.(ClientHandshakeContext.java:98)
at java.base/sun.security.ssl.TransportContext.kickstart(TransportContext.java:221)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:433)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:411)
at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:549)
at com.sun.mail.util.SocketFetcher.startTLS(SocketFetcher.java:486)
at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1902)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:666)
at javax.mail.Service.connect(Service.java:295)
at com.coco_on.tools.general.useCases.net.UCSendEMail.start(UCSendEMail.java:470)
at com.tetrixSystems.tHiddenExecuter.Executer.start(Executer.java:233)
at com.tetrixSystems.tHiddenExecuter.UCMain.start(UCMain.java:83)
at com.tetrixSystems.tHiddenExecuter.UCMain.main(UCMain.java:49)}
)
javax.net.ssl|DEBUG|01|main|2021-06-10 08:28:39.306 CEST|SSLSocketImpl.java:1638|close the underlying socket
javax.net.ssl|DEBUG|01|main|2021-06-10 08:28:39.306 CEST|SSLSocketImpl.java:1657|close the SSL connection (initiative)
javax.mail.MessagingException: Could not convert socket to TLS;
nested exception is:
javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1907)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:666)
at javax.mail.Service.connect(Service.java:295)
at com.coco_on.tools.general.useCases.net.UCSendEMail.start(UCSendEMail.java:470)
at com.tetrixSystems.tHiddenExecuter.Executer.start(Executer.java:233)
at com.tetrixSystems.tHiddenExecuter.UCMain.start(UCMain.java:83)
at com.tetrixSystems.tHiddenExecuter.UCMain.main(UCMain.java:49)
Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
at java.base/sun.security.ssl.HandshakeContext.(HandshakeContext.java:170)
at java.base/sun.security.ssl.ClientHandshakeContext.(ClientHandshakeContext.java:98)
at java.base/sun.security.ssl.TransportContext.kickstart(TransportContext.java:221)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:433)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:411)
at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:549)
at com.sun.mail.util.SocketFetcher.startTLS(SocketFetcher.java:486)
at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1902)
... 6 more
On postfix server side is openssl 1.1.1 installed:
#> openssl version
OpenSSL 1.1.1d 10 Sep 2019
I don't believe that java is using internally openssl, but may be also interesting the client side openssl version (CentOS/RHEL 7):
#> openssl version
OpenSSL 1.0.2k-fips 26 Jan 2017
ANSWER
Answered 2021-Jun-15 at 08:30Here I'm wondering about the line [in s_client]
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
You're apparently using OpenSSL 1.0.2, where that's a basically useless relic. Back in the days when OpenSSL supported SSLv2 (mostly until 2010, although almost no one used it much after 2000), the ciphersuite values used for SSLv3 and up (including all TLS, but before 2014 OpenSSL didn't implement higher than TLS1.0) were structured differently than those used for SSLv2, so it was important to qualify the ciphersuite by the 'universe' it existed in. It has almost nothing to do with the protocol version actually used, which appears later in the session-param decode:
SSL-Session:
Protocol : TLSv1.2
...
-- although you already know this from the ciphersiote, because ECDHE-RSA-AES256-GCM-SHA384 cannot be used in any protocol version other than TLS1.2.
In OpenSSL 1.1.0 up, the protocol state machine is redesigned and among other things this field is changed to display the minimum protocol version compatible with the ciphersuite, which is no longer totally useless, but still may be different from the actual protocol used.
In any case your exception occurs before JSSE client even sends the ClientHello to the server to start the handshake, so it is physically impossible for it to be be caused by anything wrong in the server. It is instead caused by something wrong in the coding or configuration on the (Java) client, about which you have provided almost no information.
It may help to run with sysprop javax.net.debug=ssl:handshake
although this problem occurs early and may be before anything usefully traceable.
Make sure you don't have sysprops mail.smtp.ssl.{protocols,ciphersuites}
set to something unsuitable. See e.g. com.sun.mail.util.SocketFetcher.configureSSLSocket and Docker Container javax.mail.MessagingException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate); and links there. Also check for any settings of mail.smtp.ssl.trust mail.smtp.ssl.socketfactory.class mail.smtp.socketfactory.class
, and any code that alters the SSLSocketFactory
default and maybe (EDIT) alteration to the SSLContext
default i.e. at or near the point you try to connect with javamail print or otherwise get Arrays.toString(SSLContext.getDefaultSSLParameters().getProtocols())
and the same for getCipherSuites
.
EDIT2: it's version dependent. Older Sun/Oracle (i.e. pre-Jakarta) versions below 1.5.3 (2015-04-15) had the default (if mail.smtp.ssl.protocols
is NOT configured) HARDCODED to TLSv1
meaning 1.0 ONLY. As a result the connection will fail with the exception in the Q on a Java that has TLS1.0 disabled, as 11.0.11 does when installed, and also 16.0.0 up and 8u291 (presumably up). On Java instances without TLS1.0 disabled it will attempt the connection, but if the server refuses TLS1.0 -- which the one in this Q should -- the connection will still fail with a different exception.
I have added already ECDHE-RSA-AES256-GCM-SHA384 as jdk.tls.legacyAlgorithms.
That's backwards. Legacy algorithms are ones you prefer NOT to use and accept only as fallback; this ciphersuite is among the best currently available and should be preferred (and is by default, so you shouldn't change it). Plus, although the doc and comments in the file don't make this clear, the legacy constraint only applies server-side anyway -- because that's where ciphersuite selection, and for 1.3 related algorithm selection, is done.
QUESTION
I am trying encrypting in JS front end and decrypt in python backend using AES GCM cryptographic algorithm. I am using Web cryptography api for JS front end and python cryptography library for python backend as cryptographic library. I have fixed the IV for now in both side. I have implemented encryption-decryption code in both side, they work on each side. But I think the padding is done differently, can't seem to figure out how the padding is done in web cryptography api. Here is the encryption and decryption for the python backend:
def encrypt(derived_key, secret):
IV = bytes("ddfbccae-b4c4-11", encoding="utf-8")
aes = Cipher(algorithms.AES(derived_key), modes.GCM(IV))
encryptor = aes.encryptor()
padder = padding.PKCS7(128).padder()
padded_data = padder.update(secret.encode()) + padder.finalize()
return encryptor.update(padded_data) + encryptor.finalize()
def decrypt(derived_key, secret):
IV = bytes("ddfbccae-b4c4-11", encoding="utf-8")
aes = Cipher(algorithms.AES(derived_key), modes.GCM(IV))
decryptor = aes.decryptor()
decrypted_data = decryptor.update(secret)
unpadder = padding.PKCS7(128).unpadder()
return unpadder.update(decrypted_data) + unpadder.finalize()
Here's the JS code for encryption and decryption code:
async function encrypt(secretKey, message) {
let iv = "ddfbccae-b4c4-11";
iv = Uint8Array.from(iv, x => x.charCodeAt(0))
let encoded = getMessageEncoding(message);
ciphertext = await window.crypto.subtle.encrypt(
{
name: "AES-GCM",
iv: iv
},
secretKey,
encoded
);
return ciphertext;
}
async function decrypt(secretKey, cipherText) {
iv = "ddfbccae-b4c4-11";
iv = Uint8Array.from(iv, x => x.charCodeAt(0))
try {
let decrypted = await window.crypto.subtle.decrypt(
{
name: "AES-GCM",
iv: iv
},
secretKey,
cipherText
);
let dec = new TextDecoder();
console.log("Decrypted message: ");
console.log(dec.decode(decrypted));
} catch (e) {
console.log("error");
}
}
I try to encrypt in the JS side and decrypt in the python side. But I got the following error:
If I try to encrypt the same string in both side I got these outputs: In python the encrypted text: \x17O\xadn\x11*I\x94\x99\xc6\x90\x8a\xa9\x9cc=
In JS the encrypted text: \x17O\xadn\x11*I\xdf\xe3F\x81(\x15\xcc\x8c^z\xdf+\x1d\x91K\xbc
How to solve this padding issue?
ANSWER
Answered 2021-Jun-14 at 18:01GCM is a stream cipher mode and therefore does not require padding. During encryption, an authentication tag is implicitly generated, which is used for authentication during decryption. Also, an IV/nonce of 12 bytes is recommended for GCM.
The posted Python code unnecessarily pads and doesn't take the authentication tag into account, unlike the JavaScript code, which may be the main reason for the different ciphertexts. Whether this is the only reason and whether the JavaScript code implements GCM correctly, is difficult to say, since the getMessageEncoding()
method was not posted, so testing this was not possible.
Also, both codes apply a 16 bytes IV/nonce instead of the recommended 12 bytes IV/nonce.
Cryptography offers two possible implementations for GCM. One implementation uses the architecture of the non-authenticating modes like CBC. The posted Python code applies this design, but does not take authentication into account and therefore implements GCM incompletely. A correct example for this design can be found here.
Cryptography generally recommends the other approach for GCM (s. the Danger note), namely the AESGCM
class, which performs implicit authentication so that this cannot be accidentally forgotten or incorrectly implemented.
The following implementation uses the AESGCM
class (and also takes into account the optional additional authenticated data):
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import base64
#import os
#key = AESGCM.generate_key(bit_length=256)
#nonce = os.urandom(12)
key = base64.b64decode('MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDE=') # fix for testing, AES-256
nonce = base64.b64decode('MDEyMzQ1Njc4OTAx') # fix for testing, 12 bytes
plaintext = b'The quick brown fox jumps over the lazy dog'
aad = b'the aad' # aad = None without additional authenticated data
aesgcm = AESGCM(key)
ciphertext = aesgcm.encrypt(nonce, plaintext, aad)
print('Ciphertext (B64): ' + base64.b64encode(ciphertext).decode('utf8'))
decrypted = aesgcm.decrypt(nonce, ciphertext, aad)
print('Decrypted: ' + decrypted.decode('utf8'))
with the output:
Output
Ciphertext (B64): JOetStCANhPISvQ6G6IcRBauqbtC8fzRooblayHqkqSPKzLbidx/gBWfLNzBC+ZpcAGnGnHXaI7CB1U=
Decrypted: The quick brown fox jumps over the lazy dog
The authentication tag is appended to the ciphertext, so the (Base64 decoded) result has the length of the plaintext (43 bytes) plus the length of the tag (16 bytes, default), giving a total of 59 bytes.
For testing, a predefined key and IV/nonce are used with regard to a comparison with the result of the JavaScript code. Note that in practice a key/IV pair may only be used once for security reasons, which is especially important for GCM mode, e.g. here. Therefore a random IV/nonce is typically generated for each encryption.
The WebCrypto API is a low level API for cryptography and does not provide methods for Base64 encoding/decoding. In the following, js-base64 is used for simplicity. Just like the Python code, the tag is appended to the ciphertext.
A possible implementation for AES-GCM using the key and IV/nonce of the Python code that is functionally essentially the same as the posted JavaScript code is:
(async () => {
var key = Base64.toUint8Array('MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDE='); // fix for testing, AES-256
var nonce = Base64.toUint8Array('MDEyMzQ1Njc4OTAx'); // fix for testing, 12 bytes
var plaintext = new TextEncoder().encode("The quick brown fox jumps over the lazy dog");
var aad = new TextEncoder().encode('the aad');
var keyImported = await await crypto.subtle.importKey(
"raw",
key,
{ name: "AES-GCM" },
true,
["decrypt", "encrypt"]
);
var ciphertext = await await crypto.subtle.encrypt(
{ name: "AES-GCM", iv: nonce, additionalData: aad }, // { name: "AES-GCM", iv: nonce } without additional authenticated data
keyImported,
plaintext
);
console.log('Ciphertext (Base64):\n', Base64.fromUint8Array(new Uint8Array(ciphertext)).replace(/(.{48})/g,'$1\n'));
var decrypted = await await crypto.subtle.decrypt(
{ name: "AES-GCM", iv: nonce, additionalData: aad }, // { name: "AES-GCM", iv: nonce } without additional authenticated data
keyImported,
ciphertext
);
console.log('Plaintext:\n', new TextDecoder().decode(decrypted).replace(/(.{48})/g,'$1\n'));
})();
with the output:
Ciphertext (Base64):
JOetStCANhPISvQ6G6IcRBauqbtC8fzRooblayHqkqSPKzLbidx/gBWfLNzBC+ZpcAGnGnHXaI7CB1U=
Plaintext:
The quick brown fox jumps over the lazy dog
where the ciphertext is the same as that of the Python code.
QUESTION
I want implement a elliptic curve diffie hellman using HKDF as key derivation function. I am using a python backend and (vanilla) javascript in frontend. I am using python cryptography library in backend and Web Crypto api in frontend as cryptographic library. I created ECDH key pair in both side and exchanged the pbulic keys. Now I am trying to create the AES shared key with the exchanged public key and private key along with HKDF algorithm. I am able to do it in the python backend (I followed this example for the python code):
def encrypt(public_key, secret):
global loaded_public_key
loaded_public_key = public_key
shared_key = server_private_key.exchange(ec.ECDH(), public_key)
IV = bytes("ddfbccae-b4c4-11", encoding="utf-8")
derived_key = HKDF(
algorithm=hashes.SHA256(),
length=32,
salt=None,
info=None,
).derive(shared_key)
aes = Cipher(algorithms.AES(derived_key), modes.GCM(IV))
encryptor = aes.encryptor()
padder = padding.PKCS7(128).padder()
padded_data = padder.update(secret.encode()) + padder.finalize()
return encryptor.update(secret.encode()) + encryptor.finalize()
But Iam not sure how to do it using web crypto api. Here is my attempt: (but doesn't work)
async function deriveSecretKey(privateKey, publicKey) {
let sharedKey = await window.crypto.subtle.deriveKey(
{
name: "ECDH",
public: publicKey
},
privateKey,
{
name: "AES-GCM",
length: 256
},
false,
["encrypt", "decrypt"]
);
return window.crypto.subtle.deriveKey(
{
name: "HKDF",
hash: {name: "SHA-256"} ,
salt: new ArrayBuffer(0),
info: new ArrayBuffer(0)
},
sharedKey,
{
name: "AES-GCM",
length: 256
},
false,
["encrypt", "decrypt"]
);
}
How can I create the shared AES key along with HKDF (same way as python) in the frontend using web crypto api?
ANSWER
Answered 2021-Jun-13 at 11:02The referenced Python code uses P-384 (aka secp384r1) as elliptic curve. This is compatible with the WebCrypto API, which supports three curves P-256 (aka secp256r1), P-384 and P-521 (aka secp521r1), see EcKeyImportParams
.
The following WebCrypto code generates a shared secret using ECDH and derives an AES key from the shared secret using HKDF. In detail the following happens:
- To allow comparison of the derived key with that of the referenced Python code, predefined EC keys are applied. The private key is imported as PKCS#8, the public key as X.509/SPKI. Note that due to a Firefox bug concerning the import of EC keys, the script below cannot be run in the Firefox browser.
- After the import the shared secret is created with ECDH using
deriveBits()
(and notderiveKey()
). - The shared secret is imported with
importKey()
and then the AES key is derived using HKDF, again withderiveBits()
.
(async () => {
await deriveKey();
})();
async function deriveKey() {
//
// Key import
//
var server_x509 = `-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEd7fej9GYVI7Vt6x5B6XhruHvmE/rnzIj
HmpxP8PKfnfWgrJbyG2cgQc3mf9uusqk1FKImA86rx2+avK8+7xIK9wxuF3x2KQq
nxNp7bUBit3phyhp72Nt/QLXmZHcDKXL
-----END PUBLIC KEY-----`;
var client_pkcs8 = `-----BEGIN PRIVATE KEY-----
MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBjr4EGktNtx+3xErsC
MzldruzzfAEEO8Oth1/3b8sNfrqRsAgMnB/oVy024I+15wOhZANiAASbTF7LLedW
dik6nH8JX8WeU0R1ZRlqq0EAZ/t+UrFcSOaVJSOx5jMJ3nrqwuk2DnobDqFwXH6t
ZMsZHh4NFZ+bCVeHJRqy4SCZvQFB/xcksF29p1v14XHYI/XKMGyLLx4=
-----END PRIVATE KEY-----`;
var client_private_key = b64_to_ab(client_pkcs8.replace('-----BEGIN PRIVATE KEY-----', '').replace('-----END PRIVATE KEY-----', ''));
var server_public_key = b64_to_ab(server_x509.replace('-----BEGIN PUBLIC KEY-----', '').replace('-----END PUBLIC KEY-----', ''));
var privateKey = await window.crypto.subtle.importKey(
'pkcs8',
client_private_key,
{ name: "ECDH", namedCurve: "P-384" },
true,
["deriveKey", "deriveBits"]
);
var publicKey = await window.crypto.subtle.importKey(
"spki",
server_public_key,
{ name: "ECDH", namedCurve: "P-384" },
true,
[]
);
//
// Determine shared secret
//
var sharedSecret = await window.crypto.subtle.deriveBits(
{ name: "ECDH", namedCurve: "P-384", public: publicKey },
privateKey,
384
);
console.log("Shared secret:\n", ab_to_b64(sharedSecret).replace(/(.{48})/g,'$1\n'));
//
// Derive key from shared secret via HKDF
//
var sharedSecretKey = await window.crypto.subtle.importKey(
"raw",
sharedSecret,
{ name: "HKDF" },
false,
["deriveKey", "deriveBits"]
);
var derived_key = await crypto.subtle.deriveBits(
{ name: "HKDF", hash: "SHA-256", salt: new Uint8Array([]), info: new Uint8Array([]) },
sharedSecretKey,
256
);
console.log("Derived key:\n", ab_to_b64(derived_key).replace(/(.{48})/g,'$1\n'))
};
function b64_to_ab(base64_string){
return Uint8Array.from(atob(base64_string), c => c.charCodeAt(0));
}
function ab_to_b64(arrayBuffer){
return btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));
}
with the following output:
Shared secret:
xbU6oDHMTYj3O71liM5KEJof3/0P4HlHJ28k7qtdqU/36llCizIlOWXtj8v+IngF
Derived key:
Yh0FkhqrT9XDQqIiSrGv5YmBjCSj9jhR5fF6HusbN1Q=
To compare the generated AES key with that of the referenced Python code, the following Python code is used, which is based on the referenced code but applies predefined keys that are the counterparts of the keys used in the WebCrypto code. Since the focus here is on key derivation, the AES part is not considered:
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import serialization
import base64
def deriveKey():
server_pkcs8 = b'''-----BEGIN PRIVATE KEY-----
MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBReGpDVmoVTzxNbJx6
aL4L9z1EdB91eonAmAw7mKDocLfCJITXZPUAmM46c6AipTmhZANiAAR3t96P0ZhU
jtW3rHkHpeGu4e+YT+ufMiMeanE/w8p+d9aCslvIbZyBBzeZ/266yqTUUoiYDzqv
Hb5q8rz7vEgr3DG4XfHYpCqfE2nttQGK3emHKGnvY239AteZkdwMpcs=
-----END PRIVATE KEY-----'''
client_x509 = b'''-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEm0xeyy3nVnYpOpx/CV/FnlNEdWUZaqtB
AGf7flKxXEjmlSUjseYzCd566sLpNg56Gw6hcFx+rWTLGR4eDRWfmwlXhyUasuEg
mb0BQf8XJLBdvadb9eFx2CP1yjBsiy8e
-----END PUBLIC KEY-----'''
client_public_key = serialization.load_pem_public_key(client_x509)
server_private_key = serialization.load_pem_private_key(server_pkcs8, password=None)
shared_secret = server_private_key.exchange(ec.ECDH(), client_public_key)
print('Shared secret: ' + base64.b64encode(shared_secret).decode('utf8')) # Shared secret: xbU6oDHMTYj3O71liM5KEJof3/0P4HlHJ28k7qtdqU/36llCizIlOWXtj8v+IngF
derived_key = HKDF(
algorithm=hashes.SHA256(),
length=32,
salt=None,
info=None,
).derive(shared_secret)
print('Derived key: ' + base64.b64encode(derived_key).decode('utf8')) # Derived key: Yh0FkhqrT9XDQqIiSrGv5YmBjCSj9jhR5fF6HusbN1Q=
deriveKey()
with the following output:
Shared secret: xbU6oDHMTYj3O71liM5KEJof3/0P4HlHJ28k7qtdqU/36llCizIlOWXtj8v+IngF
Derived key: Yh0FkhqrT9XDQqIiSrGv5YmBjCSj9jhR5fF6HusbN1Q=
which corresponds to the values of the WebCrypto code.
QUESTION
I tried every possible solution on the internet with no hope
What I am trying to do is simply use aws lambda functions (through the aws console) to fetch user fcm token from lets say DynamoDB (not included in the question), use that token to create endpointArn, send push to that specific device
I tested to send Using SNS console and the push gets to the device successfully but I failed to get it to the device using Lambda functions although it gives success status and message ID
Here is the code I used
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set region
AWS.config.update({region: 'us-east-1'});
const sns = new AWS.SNS()
const sampleMessage = {
"GCM": {
"notification": {
"body": "Sample message for Android endpoints",
"title":"Title Test"
}
}
}
exports.handler = async (event) => {
const snsPayload = JSON.stringify(sampleMessage);
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
const params = {
PlatformApplicationArn: '',
Token: ''
};
try {
const endpointData = await sns.createPlatformEndpoint(params).promise();
const paramsMessage = {
Message: snsPayload,
TargetArn: endpointData.EndpointArn
};
var publishTextPromise = await sns.publish(paramsMessage).promise();
response.MessageId = publishTextPromise.MessageId;
response.result = 'Success';
}
catch (e) {
console.log(e.stack)
response.result = 'Error'
}
return response;
};
ANSWER
Answered 2021-Jun-12 at 09:43After some trials and errors I figured out the solution for my own question
1- The GCM part of the payload should be a string not a json 2- The message parameter should have an attribute that explicitly sets the mime type of the payload to Json
Taking all that into consideration
const GCM_data = {
'notification': {
'body': 'Hellow from lambda function',
'title': 'Notification Title'
}
}
const data = {
"GCM": JSON.stringify(GCM_data)
}
const snsPayload = JSON.stringify(data)
and the params should look like
const paramsMessage = {
Message: snsPayload,
TargetArn: endpointData.EndpointArn,
MessageStructure: 'json'
};
and this will work :)
QUESTION
In my previous question (RAM not being freed in c# after working with files) I asked about a way to clear RAM. someone suggested using streams instead of reading it into a variable. I found Encrypting/Decrypting large files (.NET) which uses streams but it is not using AesGcm. The problem is that I can't find how to use AesGcm with streams. AesGcm.decrypt only accepts Byte[] in the ciphertext field, and AesManaged doesn't have CihperMode.GCM.
Currently, decryption takes 4GB of ram when decrypting an 800MB file. How can I decrypt a file with AesGcm without filling the RAM?
Thanks.
ANSWER
Answered 2021-Feb-01 at 14:24I'll say that AesGcm
(and probably AesCcm
) in .NET don't support "streaming" mode and it seems the consensus (https://crypto.stackexchange.com/questions/51537/delayed-tag-checks-in-aes-gcm-for-streaming-data) is that you shouldn't create a streaming mode AesGcm
. I'll add another reference about this https://github.com/dotnet/runtime/issues/27348 . I'm not an expert in cryptography so it isn't clear for me what are the problems about streaming an encrypted document and checking for its authentication tags only at the end.
If possible you should change the algorithm. Otherwise other solutions can be found. The Bouncycastle library supports AesGcm.
QUESTION
I try to divide an xml output from nmap into arrays. The nmap script scans the ssh ciphers of a port and the goal of my python script is to filter the nmap output into insecure ciphers. The xml output looks like this:
My current python code:
# create element tree object
tree = ET.parse(xmlfile)
# get root element
root = tree.getroot()
# create new arrays
keyx_alg = []
encr_alg = []
mac_alg = []
hkey_alg = []
comp_alg = []
for child in root.findall('host'):
for gchild in child.findall('ports'):
for ggchild in gchild.findall('port'):
for gggchild in ggchild.findall('script'):
for ggggchild in gggchild.findall('table'):
# iterate through the table an append the content into the array
# e.g.: iterate trough the table with key="kex_algorithms" and append the content into the array "keyx_alg"
I can't figure out how to get the tables into the respective arrays. Maybe one of you knows the solution.
ANSWER
Answered 2021-Jun-10 at 08:10see below (the code collects the tables data into a dict)
import xml.etree.ElementTree as ET
xml = '''
'''
data = {}
root = ET.fromstring(xml)
for table in root.findall('.//table'):
data[table.attrib['key']] = [e.text for e in table.findall('elem')]
for k, v in data.items():
print(f'{k} --> {v}')
output
kex_algorithms --> ['curve25519-sha256', 'curve25519-sha256@libssh.org', 'ecdh-sha2-nistp256', 'ecdh-sha2-nistp384', 'ecdh-sha2-nistp521', 'diffie-hellman-group-exchange-sha256', 'diffie-hellman-group16-sha512', 'diffie-hellman-group18-sha512', 'diffie-hellman-group14-sha256', 'diffie-hellman-group14-sha1']
server_host_key_algorithms --> ['rsa-sha2-512', 'rsa-sha2-256', 'ssh-rsa', 'ecdsa-sha2-nistp256', 'ssh-ed25519']
encryption_algorithms --> ['chacha20-poly1305@openssh.com', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-gcm@openssh.com', 'aes256-gcm@openssh.com']
mac_algorithms --> ['umac-64-etm@openssh.com', 'umac-128-etm@openssh.com', 'hmac-sha2-256-etm@openssh.com', 'hmac-sha2-512-etm@openssh.com', 'hmac-sha1-etm@openssh.com', 'umac-64@openssh.com', 'umac-128@openssh.com', 'hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1']
compression_algorithms --> ['none', 'zlib@openssh.com']
QUESTION
I am facing a problem with my React Native Android project. I am currently working on integrating AWS Amplify Push Notifications. I am receiving the following "Duplicate Classes" dependency error and I don't know, where it might originate from. Do you have a solution for this problem?
What I already did:
- I found this ticket here https://github.com/facebook/react-native/issues/27493 which seemed to indicate that there might be an issue using react-native-device-info which was the case for me. So I removed this library and replaced it with react-native-version-info. But the problem persists.
- I checked this ticket https://github.com/dantasfiles/AmplifyAndroidPush/issues/1 - when running
./gradlew :app:dependencies > ../dependencies.txt
, I get the dependency tree and can see thatcom.firebase:firebase-jobdispatcher:0.6.0
seems to be solely used by aws amplify push notifications. But still I do not know what to do about this now:
+--- project :aws-amplify_pushnotification
...
| \--- com.firebase:firebase-jobdispatcher:0.6.0
Has anybody faced this problem already and knows a solution?
Thanks a lot in advance!
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:checkDebugDuplicateClasses'.
> 1 exception was raised by workers:
java.lang.RuntimeException: java.lang.RuntimeException: Duplicate class com.google.android.gms.gcm.PendingCallback found in modules jetified-firebase-jobdispatcher-0.6.0-runtime.jar (com.firebase:firebase-jobdispatcher:0.6.0) and jetified-play-services-gcm-16.1.0-runtime.jar (com.google.android.gms:play-services-gcm:16.1.0)
Duplicate class com.google.android.gms.internal.measurement.zzu found in modules jetified-firebase-analytics-impl-16.2.4-runtime.jar (com.google.firebase:firebase-analytics-impl:16.2.4) and jetified-play-services-measurement-19.0.0-runtime.jar (com.google.android.gms:play-services-measurement:19.0.0)
Duplicate class com.google.android.gms.internal.measurement.zzv found in modules jetified-firebase-analytics-impl-16.2.4-runtime.jar (com.google.firebase:firebase-analytics-impl:16.2.4) and jetified-play-services-measurement-19.0.0-runtime.jar (com.google.android.gms:play-services-measurement:19.0.0)
Duplicate class com.google.android.gms.internal.measurement.zzw found in modules jetified-firebase-analytics-impl-16.2.4-runtime.jar (com.google.firebase:firebase-analytics-impl:16.2.4) and jetified-play-services-measurement-19.0.0-runtime.jar (com.google.android.gms:play-services-measurement:19.0.0)
Duplicate class com.google.android.gms.measurement.AppMeasurement found in modules jetified-firebase-analytics-impl-16.2.4-runtime.jar (com.google.firebase:firebase-analytics-impl:16.2.4) and jetified-play-services-measurement-impl-19.0.0-runtime.jar (com.google.android.gms:play-services-measurement-impl:19.0.0)
Duplicate class com.google.android.gms.measurement.AppMeasurement$ConditionalUserProperty found in modules jetified-firebase-analytics-impl-16.2.4-runtime.jar (com.google.firebase:firebase-analytics-impl:16.2.4) and jetified-play-services-measurement-impl-19.0.0-runtime.jar (com.google.android.gms:play-services-measurement-impl:19.0.0)
Duplicate class com.google.android.gms.measurement.AppMeasurement$EventInterceptor found in modules jetified-firebase-analytics-impl-16.2.4-runtime.jar (com.google.firebase:firebase-analytics-impl:16.2.4) and jetified-play-services-measurement-impl-19.0.0-runtime.jar (com.google.android.gms:play-services-measurement-impl:19.0.0)
Duplicate class com.google.android.gms.measurement.AppMeasurement$OnEventListener found in modules jetified-firebase-analytics-impl-16.2.4-runtime.jar (com.google.firebase:firebase-analytics-impl:16.2.4) and jetified-play-services-measurement-impl-19.0.0-runtime.jar (com.google.android.gms:play-services-measurement-impl:19.0.0)
Duplicate class com.google.android.gms.measurement.AppMeasurementContentProvider found in modules jetified-firebase-analytics-impl-16.2.4-runtime.jar (com.google.firebase:firebase-analytics-impl:16.2.4) and jetified-play-services-measurement-impl-19.0.0-runtime.jar (com.google.android.gms:play-services-measurement-impl:19.0.0)
Duplicate class com.google.android.gms.measurement.internal.zza found in modules jetified-firebase-analytics-impl-16.2.4-runtime.jar (com.google.firebase:firebase-analytics-impl:16.2.4) and jetified-play-services-measurement-impl-19.0.0-runtime.jar (com.google.android.gms:play-services-measurement-impl:19.0.0)
...
There is also a bug filed on GitHub about this issue but the bug has been closed with no actual resolution :( https://github.com/aws-amplify/amplify-js/issues/4593
ANSWER
Answered 2021-Jun-09 at 05:00Hi stackoverflow community,
after about a week of investigating and also opening a ticket in the aws-amplify-js github project, I was now able to solve the problem. In the following, I want to describe the solution if any of you might face the same problem in the future.
Here's the github ticket I had created on aws-amplify-js: https://github.com/aws-amplify/amplify-js/issues/8389
In my app/build.gradle I had the following definitions related to firebase and play-services:
// Import the BoM for the Firebase platform
implementation platform('com.google.firebase:firebase-bom:28.0.1')
// Declare the dependencies for the Firebase Cloud Messaging and Analytics libraries
// When using the BoM, you don't specify versions in Firebase library dependencies
implementation 'com.google.firebase:firebase-messaging'
implementation 'com.google.firebase:firebase-analytics'
implementation "com.google.android.gms:play-services-gcm:17.0.0"
...
configurations.all {
resolutionStrategy {
force 'com.google.android.gms:play-services-gcm:16.1.0'
force 'com.google.android.gms:play-services-base:16.1.0'
force 'com.google.firebase:firebase-core:16.0.6'
force 'com.google.firebase:firebase-messaging:17.6.0'
}
}
I had taken those definitions from different resources explaining how to integrate aws amplify push notifications and analytics.
Replacing all of those definitions with just the following two lines did the trick and allowed me to build my Android app again without a duplicate classes error:
implementation "com.google.firebase:firebase-core:15.0.2"
implementation "com.google.firebase:firebase-messaging:15.0.2"
Best The Smart Home Maker
QUESTION
I have 2 step auth fetching a Bearer token with which I am automatically populating a environmental variable {{authToken}} for use in a GET request. The GET request is correctly called with the token but I get a 401 returned thus -
{{baseUrl}}/api/products
401 Unauthorized
But at the same time I am returned a body with payload
"Response Body": "{\n \"type\": \"laborum aliquip\",\n \"title\": \"commodo fugiat ea laborum\",\n \"status\": -37650809,\n \"detail\": \"laborum sit\",\n \"instance\": \"ad ipsum ullamco\"\n}"
Below is the console output, any ideas please
08:51:52.057 POST https://frr-dev.auth.us-east-2.amazoncognito.com/oauth2/token: {
“Network”: {
“addresses”: {
“local”: {
“address”: “172.17.0.2”,
“family”: “IPv4”,
“port”: 36932
},
“remote”: {
“address”: “3.22.200.17”,
“family”: “IPv4”,
“port”: 443
}
},
“tls”: {
“reused”: false,
“authorized”: true,
“authorizationError”: null,
“cipher”: {
“name”: “ECDHE-RSA-AES128-GCM-SHA256”,
“standardName”: “TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256”,
“version”: “TLSv1.2”
},
“protocol”: “TLSv1.2”,
“ephemeralKeyInfo”: {
“type”: “ECDH”,
“name”: “prime256v1”,
“size”: 256
},
“peerCertificate”: {
“subject”: {
“commonName”: “.auth.us-east-2.amazoncognito.com",
“alternativeNames”: "DNS:.auth.us-east-2.amazoncognito.com, DNS:auth.us-east-2.amazoncognito.com, DNS:.auth-fips.us-east-2.amazoncognito.com, DNS:auth-fips.us-east-2.amazoncognito.com"
},
“issuer”: {
“country”: “US”,
“organization”: “Amazon”,
“organizationalUnit”: “Server CA 1B”,
“commonName”: “Amazon”
},
“validFrom”: “Mar 29 00:00:00 2021 GMT”,
“validTo”: “Apr 27 23:59:59 2022 GMT”,
“fingerprint”: “E3:F5:E4:1B:19:DB:F8:E5:A9:45:FA:91:9F:F1:78:46:41:AE:9A:D3”,
“serialNumber”: “0E828E74B1F5DEA9DF5A228813283301”
}
}
},
“Request Headers”: {
“user-agent”: “PostmanRuntime/7.28.0”,
“accept”: "/",
“cache-control”: “no-cache”,
“postman-token”: “f710e970-e41d-45a1-bceb-b9825272b40a”,
“host”: “frr-dev.auth.us-east-2.amazoncognito.com”,
“accept-encoding”: “gzip, deflate, br”,
“connection”: “keep-alive”,
“content-type”: “application/x-www-form-urlencoded”,
“cookie”: “XSRF-TOKEN=87fe7771-6abe-491f-a0e4-4c7f025b782a”
},
“Request Body”: {
“client_id”: “2d8t2gu9tg4s1il9fkplkajqvv”,
“client_secret”: “snid87pvn5kbmk8m4q5ufbj15h1r0hso075guo98jqrt0nv5sk2”,
“scope”: “https://drr-dev.auth.us-east-2.amazoncognito.com/read”,
“grant_type”: “client_credentials”
},
“Response Headers”: {
“date”: “Thu, 27 May 2021 07:51:51 GMT”,
“content-type”: “application/json;charset=UTF-8”,
“transfer-encoding”: “chunked”,
“connection”: “keep-alive”,
“x-amz-cognito-request-id”: “70ec8807-c407-409b-8510-e4ec644e1066”,
“x-application-context”: “application:prod:8443”,
“x-content-type-options”: “nosniff”,
“x-xss-protection”: “1; mode=block”,
“cache-control”: “no-cache, no-store, max-age=0, must-revalidate”,
“pragma”: “no-cache”,
“expires”: “0”,
“strict-transport-security”: “max-age=31536000 ; includeSubDomains”,
“x-frame-options”: “DENY”,
“server”: “Server”
},
“Response Body”: "{“access_token”:“eyJraWQiOiJ5UHNlZHFLYzE1eUFQb2hnWjJJUUgzNHZwdjUzaE1YWG4zT01NcnlUWFhzPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiIyZDh0Mmd1OXRnNHMxaWw5ZmtwbGthanF2diIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoiaHR0cHM6XC9cL2Zyci1kZXYuYXV0aC51cy1lYXN0LTIuYW1hem9uY29nbml0by5jb21cL3JlYWQiLCJhdXRoX3RpbWUiOjE2MjIxMDE5MTEsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC51cy1lYXN0LTIuYW1hem9uYXdzLmNvbVwvdXMtZWFzdC0yX2l4VkI3MXRBciIsImV4cCI6MTYyMjEwNTUxMSwiaWF0IjoxNjIyMTAxOTExLCJ2ZXJzaW9uIjoyLCJqdGkiOiI2MzUwODU4ZC00NzdmLTRkZjItYWE5Ny05NjYyYTczYzRjZjQiLCJjbGllbnRfaWQiOiIyZDh0Mmd1OXRnNHMxaWw5ZmtwbGthanF2diJ9.rDMbH7Pu0zGp52VbSp6qeZ7jcZRUHPbLFGq_DNYgmYINbARuQDPx0QZTIFxQ7_-Wbde-dYkBX1qyzct-FBBrDG03UtBnxV3fFfkrheH5YmTaGPocCFTRi78MIPyBSNQnNa0lzAqYLRGquq-1_2l6IOVdVt8M3XNI9WFneqOkoxTA6ykn9roK32itIeMFhxTFbIQzEi6sEj2yp5KejNFHXsS4QjeF6Kfk3iG7royUfMo96LdRxN0IOQhKG-RoJ3kyxpTisEXlJO3Zh4lfVGp6iETkAZIvNrL2IUhfk8oRGBMa8oxYFSG4-TwXJB4gYQKd85Hkq2J_O8seUp0Utj_HQ",“expires_in”:3600,“token_type”:“Bearer”}"
}
08:52:27.688 GET https://c55b92ff-38f7-4197-b5ca-14516bdeaa95.mock.pstmn.io/api/products: {
“Network”: {
“addresses”: {
“local”: {
“address”: “172.17.0.2”,
“family”: “IPv4”,
“port”: 46970
},
“remote”: {
“address”: “54.152.194.68”,
“family”: “IPv4”,
“port”: 443
}
},
“tls”: {
“reused”: true,
“authorized”: true,
“authorizationError”: null,
“cipher”: {
“name”: “ECDHE-RSA-AES128-GCM-SHA256”,
“standardName”: “TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256”,
“version”: “TLSv1.2”
},
“protocol”: “TLSv1.2”,
“ephemeralKeyInfo”: {},
“peerCertificate”: {}
}
},
“Request Headers”: {
“authorization”: "Bearer eyJraWQiOiJ5UHNlZHFLYzE1eUFQb2hnWjJJUUgzNHZwdjUzaE1YWG4zT01NcnlUWFhzPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiIyZDh0Mmd1OXRnNHMxaWw5ZmtwbGthanF2diIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoiaHR0cHM6XC9cL2Zyci1kZXYuYXV0aC51cy1lYXN0LTIuYW1hem9uY29nbml0by5jb21cL3JlYWQiLCJhdXRoX3RpbWUiOjE2MjIxMDE5MTEsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC51cy1lYXN0LTIuYW1hem9uYXdzLmNvbVwvdXMtZWFzdC0yX2l4VkI3MXRBciIsImV4cCI6MTYyMjEwNTUxMSwiaWF0IjoxNjIyMTAxOTExLCJ2ZXJzaW9uIjoyLCJqdGkiOiI2MzUwODU4ZC00NzdmLTRkZjItYWE5Ny05NjYyYTczYzRjZjQiLCJjbGllbnRfaWQiOiIyZDh0Mmd1OXRnNHMxaWw5ZmtwbGthanF2diJ9.rDMbH7Pu0zGp52VbSp6qeZ7jcZRUHPbLFGq_DNYgmYINbARuQDPx0QZTIFxQ7-Wbde-dYkBX1qyzct-FBBrDG03UtBnxV3fFfkrheH5YmTaGPocCFTRi78MIPyBSNQnNa0lzAqYLRGquq-1_2l6IOVdVt8M3XNI9WFneqOkoxTA6ykn9roK32itIeMFhxTFbIQzEi6sEj2yp5KejNFHXsS4QjeF6Kfk3iG7royUfMo96LdRxN0IOQhKG-RoJ3kyxpTisEXlJO3Zh4lfVGp6iETkAZIvNrL2IUhfk8oRGBMa8oxYFSG4-_TwXJB4gYQKd85Hkq2J_O8seUp0Utj_HQ”,
“accept”: “text/plain”,
“user-agent”: “PostmanRuntime/7.28.0”,
“cache-control”: “no-cache”,
“postman-token”: “0d3e7e54-489a-4a8d-9da9-15d57c57e535”,
“host”: “c55b925f-38f7-4197-b5ca-14516bdeaa95.mock.pstmn.io”,
“accept-encoding”: “gzip, deflate, br”,
“connection”: “keep-alive”
},
“Response Headers”: {
“date”: “Thu, 27 May 2021 07:52:27 GMT”,
“content-type”: “application/json; charset=utf-8”,
“content-length”: “150”,
“connection”: “keep-alive”,
“server”: “nginx”,
“x-srv-trace”: “v=1;t=abd55e34e437ba9a”,
“x-srv-span”: “v=1;s=154c00a79e2f5ef7”,
“access-control-allow-origin”: "”,
“x-ratelimit-limit”: “120”,
“x-ratelimit-remaining”: “117”,
“x-ratelimit-reset”: “1622101987”,
“etag”: “W/“96-dxvMF9rXhEEVZd8KJK0BUhR/FYE””,
“vary”: “Accept-Encoding”
},
“Response Body”: “{\n “type”: “laborum aliquip”,\n “title”: “commodo fugiat ea laborum”,\n “status”: -37650809,\n “detail”: “laborum sit”,\n “instance”: “ad ipsum ullamco”\n}”
}
ANSWER
Answered 2021-Jun-08 at 14:28Thanks @so-cal-cheesehead you are correct the API was faulty
QUESTION
I am trying to gzip all responses. In main.go
mux := mux.NewRouter()
mux.Use(middlewareHeaders)
mux.Use(gzipHandler)
Then I have the middlewares:
func gzipHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
gz := gzip.NewWriter(w)
defer gz.Close()
gzr := gzipResponseWriter{Writer: gz, ResponseWriter: w}
next.ServeHTTP(gzr, r)
})
}
func middlewareHeaders(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "max-age=2592000") // 30 days
w.Header().Set("Content-Encoding", "gzip")
w.Header().Set("Strict-Transport-Security", "max-age=63072000; includeSubDomains; preload")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token")
w.Header().Set("Access-Control-Allow-Methods", "POST")
w.Header().Set("Access-Control-Allow-Origin", "origin")
w.Header().Set("Access-Control-Allow-Credentials", "true")
w.Header().Set("Access-Control-Expose-Headers", "AMP-Access-Control-Allow-Source-Origin")
w.Header().Set("AMP-Access-Control-Allow-Source-Origin", os.Getenv("DOMAIN"))
next.ServeHTTP(w, r)
})
}
When I curl the site I get
curl -v https://example.com
* Trying 44.234.222.27:443...
* TCP_NODELAY set
* Connected to example.com (XX.XXX.XXX.XX) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=example.com
* start date: Mar 16 00:00:00 2021 GMT
* expire date: Apr 16 23:59:59 2022 GMT
* subjectAltName: host "example.com" matched cert's "example.com"
* issuer: C=GB; ST=Greater Manchester; L=Salford; O=Sectigo Limited; CN=Sectigo RSA Domain Validation Secure Server CA
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x55cadcebfe10)
> GET / HTTP/2
> Host: example.com
> user-agent: curl/7.68.0
> accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200
< date: Mon, 07 Jun 2021 20:13:19 GMT
< access-control-allow-credentials: true
< access-control-allow-headers: Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token
< access-control-allow-methods: POST
< access-control-allow-origin: origin
< access-control-expose-headers: AMP-Access-Control-Allow-Source-Origin
< amp-access-control-allow-source-origin: example.com
< cache-control: max-age=2592000
< content-encoding: gzip
< strict-transport-security: max-age=63072000; includeSubDomains; preload
< vary: Accept-Encoding
<
Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: " to save to a file.
* Failed writing body (0 != 3506)
* stopped the pause stream!
* Connection #0 to host example.com left intact
When enabling the gzip handler and gzip header the browser wants to download a file.
Can anyone spot my error?
ANSWER
Answered 2021-Jun-07 at 21:501. You should only gzip
when it's requested by the client.
Accept-Encoding: gzip
is never requested, but you gzip
the response anyway.
So curl
gives it back to you as-is.
2. Given the behavior of your browser, it sounds like double-compression. Maybe you have some HTTP reverse proxy in place which already handles compression to the browser, but doesn't compress backend traffic. So you may not need any gzipping at the backend at all - try curl --compressed
to confirm this.
3. You should filter out Content-Length
from the response. Content-Length is the final size of the compressed HTTP response, so the value changes during compression.
4. You should not blindly apply compression to all URI's. Some handlers perform gzipping already (e.g. prometheus /metrics
), and some are pointless to compress (e.g. .png
, .zip
, .gz
). At the very least strip Accept-Encoding: gzip
from the request before passing it down the handler chain, to avoid double-gzipping.
5. Transparent gzipping in Go has been implemented before. A quick search reveals this gist (adjusted for point #4 above):
package main
import (
"compress/gzip"
"io"
"io/ioutil"
"net/http"
"strings"
"sync"
)
var gzPool = sync.Pool{
New: func() interface{} {
w := gzip.NewWriter(ioutil.Discard)
return w
},
}
type gzipResponseWriter struct {
io.Writer
http.ResponseWriter
}
func (w *gzipResponseWriter) WriteHeader(status int) {
w.Header().Del("Content-Length")
w.ResponseWriter.WriteHeader(status)
}
func (w *gzipResponseWriter) Write(b []byte) (int, error) {
return w.Writer.Write(b)
}
func Gzip(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
next.ServeHTTP(w, r)
return
}
w.Header().Set("Content-Encoding", "gzip")
gz := gzPool.Get().(*gzip.Writer)
defer gzPool.Put(gz)
gz.Reset(w)
defer gz.Close()
r.Header.Del("Accept-Encoding")
next.ServeHTTP(&gzipResponseWriter{ResponseWriter: w, Writer: gz}, r)
})
}
Note - the above doesn't support chunked encoding and trailers. So there's still opportunity for improvement.
QUESTION
I'm using (CryptoKit) to use AES-GCM to encrypt some data and authenticate it as well.
However, I was wondering how I would generate an AES-GCM key from a plain text password. Normally, you would use a KDF
function for that, like PBKDF2.
In CryptoKit
, there is a HKDF
class which does about what I want: https://developer.apple.com/documentation/cryptokit/hkdf
However, I am wondering what KDF algorithm the DeriveKey function uses. Does it use PBKDF2? Does it use bcrypt
? If so, how do I specify settings, or are the settings automatically determined?
ANSWER
Answered 2021-May-29 at 21:03HKDF is defined in RFC5869. It is intended to generate keys from some cryptographically secure "keying material" (IKM). It is not intended for stretching a human-generated password. As discussed in section 4 Applications of HKDF:
On the other hand, it is anticipated that some applications will not be able to use HKDF "as-is" due to specific operational requirements, or will be able to use it but without the full benefits of the scheme. One significant example is the derivation of cryptographic keys from a source of low entropy, such as a user's password. The extract step in HKDF can concentrate existing entropy but cannot amplify entropy. In the case of password-based KDFs, a main goal is to slow down dictionary attacks using two ingredients: a salt value, and the intentional slowing of the key derivation computation. HKDF naturally accommodates the use of salt; however, a slowing down mechanism is not part of this specification. Applications interested in a password-based KDF should consider whether, for example, [PKCS5] meets their needs better than HKDF.
I don't believe that CryptoKit offers a PBKDF of any kind (PBKDF2, scrypt, bcrypt, argon2). It's a very limited framework (I have yet to find a situation where it was useful). You will likely need to continue to use CommonCrypto for this, or implement it yourself (or use something like CryptoSwift, which I believe implements several).
Community Discussions, Code Snippets contain sources that include Stack Exchange Network
Vulnerabilities
No vulnerabilities reported
Install gcm
Support
Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from over 650 million Knowledge Items
Find more librariesExplore Kits - Develop, implement, customize Projects, Custom Functions and Applications with kandi kits
Save this library and start creating your kit
Share this Page