Encrypts using AES GCM for data with limited visibility and long rest

This is the third iteration of my venture on creating an encryption/decryption solution. I asked a question here, which led to this question here, which led to this answer here, which led me to introducing Bouncy Castle into my solution to gain better security under the circumstances and application requirements.

Requirements: To encrypt and decrypt a string using AES 256 with a password/key (stored in web.config) in an ASP.net application.

History: If you follow the above links you’ll find that I originally tried to stick with the core .net provided solutions without the inclusion of any additional libraries. This requirement has changed and I’ve added Bouncy Castle to my solution.

Thanks to @SEJPM regularly pointing me in the right direction I decided to implement AES GCM and ditch my previous attempts.

I found this example here from @jbtule who seems to have a pretty good handle on things, and honestly I didn’t change a thing other than convert it to VB. However, based on previous suggestions given to me to use Argon2, I read that Bouncy Castle supports this now but I’m currently uncertain as how to properly implement it.

Although my code is essentially a copy @jbtule’s original post on CodeReview, that was 6 years ago.

So based on the fact that I pull the encryption key/pass from web.config and I need simple encrypt/decrypt, how does this solution stack up?

Usage:

Dim password = RetrieveFromWebConfig() Dim plainText = "Hello World" Dim encrypted = SimpleEncryptWithPassword(plainText, password) Dim decrypted = SimpleDecryptWithPassword(encrypted, password) 

Code:

Imports System Imports System.IO Imports System.Text Imports Org.BouncyCastle.Crypto Imports Org.BouncyCastle.Crypto.Engines Imports Org.BouncyCastle.Crypto.Generators Imports Org.BouncyCastle.Crypto.Modes Imports Org.BouncyCastle.Crypto.Parameters Imports Org.BouncyCastle.Security  Namespace Utilities.Encryption     Public Class Aesgcm         Public Shared ReadOnly Random As SecureRandom = New SecureRandom()         Public Shared ReadOnly NonceBitSize As Integer = 128         Public Shared ReadOnly MacBitSize As Integer = 128         Public Shared ReadOnly KeyBitSize As Integer = 256         Public Shared ReadOnly SaltBitSize As Integer = 128         Public Shared ReadOnly Iterations As Integer = 10000         Public Shared ReadOnly MinPasswordLength As Integer = 12           Shared Function SimpleEncryptWithPassword(secretMessage As String, password As String, ByVal Optional nonSecretPayload As Byte() = Nothing) As String             If String.IsNullOrEmpty(secretMessage) Then Throw New ArgumentException("Secret Message Required!", "secretMessage")             Dim plainText = Encoding.UTF8.GetBytes(secretMessage)             Dim cipherText = SimpleEncryptWithPassword(plainText, password, nonSecretPayload)             Return Convert.ToBase64String(cipherText)         End Function          Shared Function SimpleDecryptWithPassword(encryptedMessage As String, password As String, ByVal Optional nonSecretPayloadLength As Integer = 0) As String             If String.IsNullOrWhiteSpace(encryptedMessage) Then Throw New ArgumentException("Encrypted Message Required!", "encryptedMessage")             Dim cipherText = Convert.FromBase64String(encryptedMessage)             Dim plainText = SimpleDecryptWithPassword(cipherText, password, nonSecretPayloadLength)             Return If(plainText Is Nothing, Nothing, Encoding.UTF8.GetString(plainText))         End Function          Shared Function SimpleEncrypt(secretMessage As Byte(), key As Byte(), ByVal Optional nonSecretPayload As Byte() = Nothing) As Byte()             If key Is Nothing OrElse key.Length <> KeyBitSize / 8 Then Throw New ArgumentException($  "Key needs to be {KeyBitSize} bit!", "key")             If secretMessage Is Nothing OrElse secretMessage.Length = 0 Then Throw New ArgumentException("Secret Message Required!", "secretMessage")             nonSecretPayload = If(nonSecretPayload, New Byte() {})             Dim nonce = New Byte(CInt(NonceBitSize / 8 - 1)) {}             Random.NextBytes(nonce, 0, nonce.Length)             Dim cipher = New GcmBlockCipher(New AesEngine())             Dim parameters = New AeadParameters(New KeyParameter(key), MacBitSize, nonce, nonSecretPayload)             cipher.Init(True, parameters)             Dim cipherText = New Byte(cipher.GetOutputSize(secretMessage.Length) - 1) {}             Dim len = cipher.ProcessBytes(secretMessage, 0, secretMessage.Length, cipherText, 0)             cipher.DoFinal(cipherText, len)              Using combinedStream = New MemoryStream()                  Using binaryWriter = New BinaryWriter(combinedStream)                     binaryWriter.Write(nonSecretPayload)                     binaryWriter.Write(nonce)                     binaryWriter.Write(cipherText)                 End Using                  Return combinedStream.ToArray()             End Using         End Function          Shared Function SimpleDecrypt(encryptedMessage As Byte(), key As Byte(), ByVal Optional nonSecretPayloadLength As Integer = 0) As Byte()             If key Is Nothing OrElse key.Length <> KeyBitSize / 8 Then Throw New ArgumentException($  "Key needs to be {KeyBitSize} bit!", "key")             If encryptedMessage Is Nothing OrElse encryptedMessage.Length = 0 Then Throw New ArgumentException("Encrypted Message Required!", "encryptedMessage")              Using cipherStream = New MemoryStream(encryptedMessage)                  Using cipherReader = New BinaryReader(cipherStream)                     Dim nonSecretPayload = cipherReader.ReadBytes(nonSecretPayloadLength)                     Dim nonce = cipherReader.ReadBytes(CInt(NonceBitSize / 8))                     Dim cipher = New GcmBlockCipher(New AesEngine())                     Dim parameters = New AeadParameters(New KeyParameter(key), MacBitSize, nonce, nonSecretPayload)                     cipher.Init(False, parameters)                     Dim cipherText = cipherReader.ReadBytes(encryptedMessage.Length - nonSecretPayloadLength - nonce.Length)                     Dim plainText = New Byte(cipher.GetOutputSize(cipherText.Length) - 1) {}                      Try                         Dim len = cipher.ProcessBytes(cipherText, 0, cipherText.Length, plainText, 0)                         cipher.DoFinal(plainText, len)                     Catch unusedInvalidCipherTextException1 As InvalidCipherTextException                         Return Nothing                     End Try                      Return plainText                 End Using             End Using         End Function          Shared Function SimpleEncryptWithPassword(secretMessage As Byte(), password As String, ByVal Optional nonSecretPayload As Byte() = Nothing) As Byte()             nonSecretPayload = If(nonSecretPayload, New Byte() {})             If String.IsNullOrWhiteSpace(password) OrElse password.Length < MinPasswordLength Then Throw New ArgumentException($  "Must have a password of at least {MinPasswordLength} characters!", "password")             If secretMessage Is Nothing OrElse secretMessage.Length = 0 Then Throw New ArgumentException("Secret Message Required!", "secretMessage")             Dim generator = New Pkcs5S2ParametersGenerator()             Dim salt = New Byte(CInt(SaltBitSize / 8 - 1)) {}             Random.NextBytes(salt)             generator.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password.ToCharArray()), salt, Iterations)             Dim key = CType(generator.GenerateDerivedMacParameters(KeyBitSize), KeyParameter)             Dim payload = New Byte(salt.Length + nonSecretPayload.Length - 1) {}             Array.Copy(nonSecretPayload, payload, nonSecretPayload.Length)             Array.Copy(salt, 0, payload, nonSecretPayload.Length, salt.Length)             Return SimpleEncrypt(secretMessage, key.GetKey(), payload)         End Function          Shared Function SimpleDecryptWithPassword(encryptedMessage As Byte(), password As String, ByVal Optional nonSecretPayloadLength As Integer = 0) As Byte()             If String.IsNullOrWhiteSpace(password) OrElse password.Length < MinPasswordLength Then Throw New ArgumentException($  "Must have a password of at least {MinPasswordLength} characters!", "password")             If encryptedMessage Is Nothing OrElse encryptedMessage.Length = 0 Then Throw New ArgumentException("Encrypted Message Required!", "encryptedMessage")             Dim generator = New Pkcs5S2ParametersGenerator()             Dim salt = New Byte(CInt(SaltBitSize / 8 - 1)) {}             Array.Copy(encryptedMessage, nonSecretPayloadLength, salt, 0, salt.Length)             generator.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password.ToCharArray()), salt, Iterations)              Dim key = CType(generator.GenerateDerivedMacParameters(KeyBitSize), KeyParameter)             Return SimpleDecrypt(encryptedMessage, key.GetKey(), salt.Length + nonSecretPayloadLength)         End Function     End Class End Namespace 

google services has stopped wont stop long enough for me to fix the problem cant even get into my settings

google services keeps looping gives me no time to fix due to it just keeps forcing me back to same looping message cant even get into my settings for long enough to repair because it just throws me back to the same looping error screen

How long does it take to use first aid to save a dying character?

In the PHB, it says that a character can perform first aid in order to stabilize a dying character. The Heal DC is 15 and if the character makes it, then the character immediately stops losing HP and is stabilized. This takes one standard action. (Given that you get a move and a standard action in one round and one round is 6 seconds, then this action takes approximately 3 seconds to perform.)

Yet on page 138 under “The Combat Round”, it says

Anything a person could reasonably do in 6 seconds, your character can do in one round.

My issue is the discrepancy here. You cannot reasonably stabilize someone and stop them from losing blood, etc. in 3 seconds; it’s impossible without some form of magical aid. So how is it a person can perform a Heal check in 3 seconds and stabilize a dying person, when doing so is unreasonable?

Why does google use 1000 char long image links?

When I copy an image address from the gallery on google.fr/images it copies this to my clipboard, why?

data:image/jpeg;base64,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 

data:image/jpeg;base64,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

??? it’s a bit overkill for a hyperlink? what is google doing? I know that if i click on it again i get the real link, but it’s a new thing from google, it’s weird!

How long does one remain sudo in terminal? [duplicate]

This question already has an answer here:

  • How often is the password asked for sudo commands? Where can I set it up? 3 answers

When you run a command as sudo in terminal, you will have the sudo rights for some time. This means you can run several sudo commands right after another but you only have to enter the password for the very first command, for example in

sudo apt-get update sudo apt-get dist-upgrade 

you only have to enter the sudo-password for the first line but not for the second one, if you execute the second command immediately after the first one.

If you leave the terminal open and wait for some time, say 5 hours, and you want to run another sudo command, you are asked for the password again (which makes a lot of sense, for security reasons, for example). So, I was wondering for how long is one granted sudo rights after entering the password? Moreover, is there a way to increase or decrease the time until you lose sudo-rights after entering the password?

Why does it take so long to proof optimality when wam-starting from optimal solution

So I’m solving bigger instances of some binary-linear-program using cplex. The formulations of the problem I am using is integer friendly, meaning nearly all of my instances can be solved at the root node. Additionally I have a pretty good heuristic for calculating solutions. The heuristic is quite fast and nearly always gives the globally optimal solution.

When combining cplex with the heuristic I do not achieve the performance gains I expected. I feed the globally optimal solution to cplex as a “warm-start-solution”, but it still takes quite some time for cplex to proof its optimality (cplex chooses the dual-simplex for the relaxation).

I might lack some theoretical understanding, but why can’t the dual-simplex just build a basis for the supplied optimal solution and show that there is nothing else to do?

How do I determine if the rules for a long jump or high jump are applicable for Monks?

Inspired by this question

At 9th level, Monks can:

…you gain the ability to move along vertical surfaces and across liquids on your turns without falling during the move.

I interpret this to mean that the Monk can simply treat horizontal and vertical movement as the same for the purposes of determining how far they can move on their turn.

Suppose a 10th level Monk with 50′ of movement is in front of a 20′ tall building. 10′ above the building is a flying opponent.

      O      -|- (pitiable fool)      / \ 10' ------      |      | 20'  |     O bldg.|    \|/ (Mr. T in Monk form)      |____/ \ 

Can the monk simply run up the wall and perform a horizontal long jump to reach the flying opponent (assume Monk’s strength is at least 10)? This seems appropriate as from the Monk’s point of view, they would be traveling in a horizontal line towards their opponent and their class feature suggests that for the duration of their turn gravity seems to be effectively turned off.

Alternately, are the high jump rules applicable because from the overall point of view, the Monk’s movement is vertical.

Items with long title in Android

In an Android application, I have a “Grid Layout” with fixed size cells for describing Three-line items:

mockup

download bmml source – Wireframes created with Balsamiq Mockups

Number of columns and rows in Grid depend to the device dimensions. Also above items (boxes) will created by users and this may cause a problem:

What we have to do if a user enter a long title which exceeds bound of item? Of course we can do:

  1. ellipsis title
  2. limit input characters of title
  3. break long title text into two lines
  4. use “list” instead of grid; but it cause empty/blank spaces on “tablets” around items

What is the best choice?