gcm | helps developers send data from ruby backend servers

 by   decision-labs Ruby Version: Current License: MIT

kandi X-RAY | gcm Summary

gcm is a Ruby library. gcm has no bugs, it has no vulnerabilities, it has a Permissive License and it has low support. You can download it from GitHub.
The GCM gem lets your ruby backend send notifications to Android and iOS devices via Google Cloud Messaging.
    Support
      Quality
        Security
          License
            Reuse
            Support
              Quality
                Security
                  License
                    Reuse

                      kandi-support Support

                        summary
                        gcm has a low active ecosystem.
                        summary
                        It has 387 star(s) with 64 fork(s). There are 29 watchers for this library.
                        summary
                        It had no major release in the last 6 months.
                        summary
                        There are 3 open issues and 15 have been closed. On average issues are closed in 75 days. There are 2 open pull requests and 0 closed requests.
                        summary
                        It has a neutral sentiment in the developer community.
                        summary
                        The latest version of gcm is current.
                        gcm Support
                          Best in #Ruby
                            Average in #Ruby
                            gcm Support
                              Best in #Ruby
                                Average in #Ruby

                                  kandi-Quality Quality

                                    summary
                                    gcm has 0 bugs and 0 code smells.
                                    gcm Quality
                                      Best in #Ruby
                                        Average in #Ruby
                                        gcm Quality
                                          Best in #Ruby
                                            Average in #Ruby

                                              kandi-Security Security

                                                summary
                                                gcm has no vulnerabilities reported, and its dependent libraries have no vulnerabilities reported.
                                                summary
                                                gcm code analysis shows 0 unresolved vulnerabilities.
                                                summary
                                                There are 0 security hotspots that need review.
                                                gcm Security
                                                  Best in #Ruby
                                                    Average in #Ruby
                                                    gcm Security
                                                      Best in #Ruby
                                                        Average in #Ruby

                                                          kandi-License License

                                                            summary
                                                            gcm is licensed under the MIT License. This license is Permissive.
                                                            summary
                                                            Permissive licenses have the least restrictions, and you can use them in most projects.
                                                            gcm License
                                                              Best in #Ruby
                                                                Average in #Ruby
                                                                gcm License
                                                                  Best in #Ruby
                                                                    Average in #Ruby

                                                                      kandi-Reuse Reuse

                                                                        summary
                                                                        gcm releases are not available. You will need to build from source code and install.
                                                                        summary
                                                                        Installation instructions, examples and code snippets are available.
                                                                        summary
                                                                        gcm saves you 145 person hours of effort in developing the same functionality from scratch.
                                                                        summary
                                                                        It has 363 lines of code, 13 functions and 3 files.
                                                                        summary
                                                                        It has high code complexity. Code complexity directly impacts maintainability of the code.
                                                                        gcm Reuse
                                                                          Best in #Ruby
                                                                            Average in #Ruby
                                                                            gcm Reuse
                                                                              Best in #Ruby
                                                                                Average in #Ruby
                                                                                  Top functions reviewed by kandi - BETA
                                                                                  kandi's functional review helps you automatically verify the functionalities of the libraries and avoid rework.
                                                                                  Currently covering the most popular Java, JavaScript and Python libraries. See a Sample Here
                                                                                  Get all kandi verified functions for this library.
                                                                                  Get all kandi verified functions for this library.

                                                                                  gcm Key Features

                                                                                  A gem that helps developers send data from ruby backend servers to their Mobile applications on devices via Google Cloud Messaging (GCM).

                                                                                  gcm Examples and Code Snippets

                                                                                  AES-256-GCM Example
                                                                                  Pythondot imgLines of Code : 33dot imgno licencesLicense : No License
                                                                                  copy iconCopy
                                                                                  
                                                                                                                      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
                                                                                  
                                                                                  AES-256-GCM + Scrypt Example
                                                                                  Pythondot imgLines of Code : 31dot imgno licencesLicense : No License
                                                                                  copy iconCopy
                                                                                  
                                                                                                                      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'
                                                                                  
                                                                                  Encrypt the given data using GCM .
                                                                                  javadot imgLines of Code : 6dot imgLicense : Permissive (MIT License)
                                                                                  copy iconCopy
                                                                                  
                                                                                                                      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 }; }
                                                                                  Decrypts the specified ciphertext using GCM .
                                                                                  javadot imgLines of Code : 6dot imgLicense : Permissive (MIT License)
                                                                                  copy iconCopy
                                                                                  
                                                                                                                      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; }
                                                                                  Community Discussions

                                                                                  Trending Discussions on gcm

                                                                                  postfix and openJDK 11: "No appropriate protocol (protocol is disabled or cipher suites are inappropriate)"
                                                                                  chevron right
                                                                                  Encrypt in JS front end and decrypt in python backend using AES GCM
                                                                                  chevron right
                                                                                  Web cryptography implement HKDF for the output of ECDH
                                                                                  chevron right
                                                                                  Using AWS Lambda Console to send push using SNS
                                                                                  chevron right
                                                                                  AES_GCM in .net with streams
                                                                                  chevron right
                                                                                  How to divide XML tables into arrays with in Python with ElementTree
                                                                                  chevron right
                                                                                  React Native Android Duplicate class com.google.android.gms.gcm.PendingCallback found in modules jetified-firebase-jobdispatcher-0.6.0-runtime.jar
                                                                                  chevron right
                                                                                  Postman returns 401 with valid token
                                                                                  chevron right
                                                                                  Gzip header forces file download
                                                                                  chevron right
                                                                                  Password hashing using CryptoKit
                                                                                  chevron right

                                                                                  QUESTION

                                                                                  postfix and openJDK 11: "No appropriate protocol (protocol is disabled or cipher suites are inappropriate)"
                                                                                  Asked 2021-Jun-15 at 08:30

                                                                                  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:30

                                                                                  Here 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.

                                                                                  Source https://stackoverflow.com/questions/67899129

                                                                                  QUESTION

                                                                                  Encrypt in JS front end and decrypt in python backend using AES GCM
                                                                                  Asked 2021-Jun-14 at 18:01

                                                                                  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:01

                                                                                  GCM 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.

                                                                                  Source https://stackoverflow.com/questions/67963529

                                                                                  QUESTION

                                                                                  Web cryptography implement HKDF for the output of ECDH
                                                                                  Asked 2021-Jun-13 at 11:02

                                                                                  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:02

                                                                                  The 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 not deriveKey()).
                                                                                  • The shared secret is imported with importKey() and then the AES key is derived using HKDF, again with deriveBits().

                                                                                  (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.

                                                                                  Source https://stackoverflow.com/questions/67938461

                                                                                  QUESTION

                                                                                  Using AWS Lambda Console to send push using SNS
                                                                                  Asked 2021-Jun-12 at 09:43

                                                                                  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:43

                                                                                  After 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 :)

                                                                                  Source https://stackoverflow.com/questions/67767249

                                                                                  QUESTION

                                                                                  AES_GCM in .net with streams
                                                                                  Asked 2021-Jun-11 at 18:11

                                                                                  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:24

                                                                                  I'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.

                                                                                  Source https://stackoverflow.com/questions/65991075

                                                                                  QUESTION

                                                                                  How to divide XML tables into arrays with in Python with ElementTree
                                                                                  Asked 2021-Jun-10 at 08:10

                                                                                  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:10

                                                                                  see 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']
                                                                                  

                                                                                  Source https://stackoverflow.com/questions/67916313

                                                                                  QUESTION

                                                                                  React Native Android Duplicate class com.google.android.gms.gcm.PendingCallback found in modules jetified-firebase-jobdispatcher-0.6.0-runtime.jar
                                                                                  Asked 2021-Jun-09 at 05:00

                                                                                  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 that com.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:00

                                                                                  Hi 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

                                                                                  Source https://stackoverflow.com/questions/67782807

                                                                                  QUESTION

                                                                                  Postman returns 401 with valid token
                                                                                  Asked 2021-Jun-08 at 14:28

                                                                                  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:28

                                                                                  Thanks @so-cal-cheesehead you are correct the API was faulty

                                                                                  Source https://stackoverflow.com/questions/67722825

                                                                                  QUESTION

                                                                                  Gzip header forces file download
                                                                                  Asked 2021-Jun-07 at 21:50

                                                                                  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:50

                                                                                  1. 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.

                                                                                  Source https://stackoverflow.com/questions/67878281

                                                                                  QUESTION

                                                                                  Password hashing using CryptoKit
                                                                                  Asked 2021-May-29 at 21:03

                                                                                  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:03

                                                                                  HKDF 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).

                                                                                  Source https://stackoverflow.com/questions/67747650

                                                                                  Community Discussions, Code Snippets contain sources that include Stack Exchange Network

                                                                                  Vulnerabilities

                                                                                  No vulnerabilities reported

                                                                                  Install gcm

                                                                                  or in your Gemfile just include it:.

                                                                                  Support

                                                                                  For any new features, suggestions and bugs create an issue on GitHub. If you have any questions check and ask questions on community page Stack Overflow .
                                                                                  Find more information at:
                                                                                  Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from over 650 million Knowledge Items
                                                                                  Find more libraries
                                                                                  Explore Kits - Develop, implement, customize Projects, Custom Functions and Applications with kandi kits​
                                                                                  Save this library and start creating your kit
                                                                                  CLONE
                                                                                • HTTPS

                                                                                  https://github.com/decision-labs/gcm.git

                                                                                • CLI

                                                                                  gh repo clone decision-labs/gcm

                                                                                • sshUrl

                                                                                  git@github.com:decision-labs/gcm.git

                                                                                • Share this Page

                                                                                  share link

                                                                                  Consider Popular Ruby Libraries

                                                                                  rails

                                                                                  by rails

                                                                                  jekyll

                                                                                  by jekyll

                                                                                  discourse

                                                                                  by discourse

                                                                                  fastlane

                                                                                  by fastlane

                                                                                  huginn

                                                                                  by huginn

                                                                                  Try Top Libraries by decision-labs

                                                                                  fcm

                                                                                  by decision-labsRuby

                                                                                  libpq.framework

                                                                                  by decision-labsC

                                                                                  libpq-ios

                                                                                  by decision-labsC

                                                                                  spacialdb-devcenter

                                                                                  by decision-labsRuby

                                                                                  parse_fdw

                                                                                  by decision-labsPython

                                                                                  Compare Ruby Libraries with Highest Support

                                                                                  rails

                                                                                  by rails

                                                                                  fastlane

                                                                                  by fastlane

                                                                                  jekyll

                                                                                  by jekyll

                                                                                  mastodon

                                                                                  by mastodon

                                                                                  brew

                                                                                  by Homebrew

                                                                                  Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from over 650 million Knowledge Items
                                                                                  Find more libraries
                                                                                  Explore Kits - Develop, implement, customize Projects, Custom Functions and Applications with kandi kits​
                                                                                  Save this library and start creating your kit