크롬이든 Powerherll이든 Openssl equivalent의 AES를 사용할 수 있습니다

가져오기

  • 회사용 PC에 임의의 앱을 넣지 않는 것이 어른들의 취미다.
  • 비밀번호의 메모 등은 평범한 PC 환경에서도 미리 암호화해야 한다.
  • 크롬의 API를 사용하지만 js 라이브러리의 방향은 사용하지 않습니다.
  • 오픈스sl과 동작이 같아 서로 활용하기 편할 수 있습니다.
  • (면책) 본 구현 방식은 안전을 보장할 수 없습니다.
  • encrypt


    우선 CLI
      echo "message" | openssl enc -aes-256-cbc -a -pbkdf2 -md sha512 -p -pass pass:hoge
    
    javascript(chrome에서만 확인)로 이 등가의 일을 합니다.
      c={text:"message",algenc:"AES-CBC",algbit:256,algkd:"pbkdf2",alghash:"SHA-512",kdi:10000,c:crypto,u:Uint8Array,e:x=>(new TextEncoder()).encode(x)};
      c.passbin=(new TextEncoder()).encode("hoge");
      c.salt=c.c.getRandomValues(new c.u(8))
      c.c.subtle.importKey("raw",c.passbin,{name:c.algkd},!1,["deriveBits"])
        .then(km => c.c.subtle.deriveBits( { name: c.algkd, salt: c.salt, iterations: c.kdi, hash: c.alghash }, km, 8*(32+16) )) // key(32)+iv(16)
        .then(b => (c.db=b)&&(c.iv=b.slice(32,48))&&c.c.subtle.importKey("raw",b.slice(0,32),c.algenc,!1,["encrypt"]))
        .then(k  => (c.key=k)&&c.c.subtle.encrypt({name:c.algenc,iv:c.iv},c.key,c.e(c.text)))
        .then(e=>c.encrypted=window.btoa(String.fromCharCode(...([...c.e("Salted__"),...c.salt,...(new c.u(e))]))))
        .finally(()=>console.log(c.encrypted))
    
    파워힐도 합니다.
      function enc($s, $p){
        $salt = New-Object byte[] 8
        $rng  = New-Object System.Security.Cryptography.RNGCryptoServiceProvider
        $rng.getBytes($salt)
        $kiv  = (New-Object System.Security.Cryptography.Rfc2898DeriveBytes([System.Text.Encoding]::UTF8.GetBytes($p), $salt, 10000, [System.Security.Cryptography.HashAlgorithmName]::SHA512)).GetBytes(48)
        $aes = New-Object System.Security.Cryptography.AesManaged
        $aes.KeySize   = 256
        $aes.BlockSize = 128
        $aes.Mode      = [System.Security.Cryptography.CipherMode]::CBC
        $aes.Padding   = [System.Security.Cryptography.PaddingMode]::PKCS7
        $aes.Key       = $kiv[0..31]
        $aes.IV        = $kiv[32..47]
        $encryptor = $aes.CreateEncryptor($aes.Key, $aes.IV)
        $bytes = [System.Text.Encoding]::UTF8.GetBytes($s)
        $ms = [System.IO.MemoryStream]::new()
        $ms.Write([System.Text.Encoding]::UTF8.GetBytes("Salted__") + $salt, 0, 16)
        $cs = New-Object System.Security.Cryptography.CryptoStream($ms, $encryptor, [System.Security.Cryptography.CryptoStreamMode]::Write)
        $cs.Write($bytes, 0, $bytes.length)
        $cs.FlushFinalBlock()
        $cs.Close()
        [System.Convert]::ToBase64String($ms.ToArray())
        $ms.Close()
        $encryptor.Dispose()
        $aes.Dispose()
      }
      enc "message" "hoge"
    

    decrypt


    그리고 cli에서 decrype.
    echo "U2FsdGVkX1+6SGosjqp5QKdNOwVIn5KAvOQtTqObCAE=" | openssl enc -aes-256-cbc -a -d -pbkdf2 -md sha512 -p -pass pass:hoge
    
    등효javascript
      c={enctext:"U2FsdGVkX1+6SGosjqp5QKdNOwVIn5KAvOQtTqObCAE=",algenc:"AES-CBC",algbit:256,algkd:"pbkdf2",alghash:"SHA-512",kdi:10000,c:crypto,u:Uint8Array};
      c.passbin=(new TextEncoder()).encode("hoge");
      c.encbin=new c.u(window.atob(c.enctext).split("").map(a=>a.charCodeAt(0)));
      c.salt=c.encbin.slice(8,16);
      c.c.subtle.importKey("raw",c.passbin,{name:c.algkd},!1,["deriveBits"])
        .then(km => c.c.subtle.deriveBits( { name: c.algkd, salt: c.salt, iterations: c.kdi, hash: c.alghash }, km, 8*(32+16)) ) // key(32)+iv(16)
        .then(b => (c.db=b)&&(c.iv=b.slice(32,48))&&c.c.subtle.importKey("raw",b.slice(0,32),c.algenc,!1,["decrypt"]))
        .then(k  => (c.key=k)&&c.c.subtle.decrypt({name:c.algenc,iv:c.iv},c.key,c.encbin.slice(16)))
        .then(d=>c.decodedtext=(new TextDecoder("utf-8")).decode(new c.u(d)))
        .finally(()=>console.log(c.decodedtext))
    
    powershell
      function dec($s, $p){ # base64str
        $encText = [System.Convert]::FromBase64String($s);
        $salt = $encText[8..15]
        $kiv  = (New-Object System.Security.Cryptography.Rfc2898DeriveBytes([System.Text.Encoding]::UTF8.GetBytes($p), $salt, 10000, [System.Security.Cryptography.HashAlgorithmName]::SHA512)).GetBytes(48)
        $aes = New-Object System.Security.Cryptography.AesManaged
        $aes.KeySize   = 256
        $aes.BlockSize = 128
        $aes.Mode      = [System.Security.Cryptography.CipherMode]::CBC
        $aes.Padding   = [System.Security.Cryptography.PaddingMode]::PKCS7
        $aes.Key       = $kiv[0..31]
        $aes.IV        = $kiv[32..47]
        $decryptor = $aes.CreateDecryptor()
        $ms1 = [System.IO.MemoryStream]::new($encText[16..($encText.Length-1)])
        $cs = New-Object System.Security.Cryptography.CryptoStream($ms1, $decryptor, [System.Security.Cryptography.CryptoStreamMode]::Read)
        $ms2 = [System.IO.MemoryStream]::new()
        $cs.CopyTo($ms2)
        $ms1.Close()
        $ms2.Close()
        $cs.Close()
        [System.Text.Encoding]::UTF8.GetString($ms2.ToArray())
        $decryptor.Dispose()
        $aes.Dispose()
      }
      dec "U2FsdGVkX1+6SGosjqp5QKdNOwVIn5KAvOQtTqObCAE=" "hoge"
    

    배우다

  • 매번 encrypt 결과가 다른 것은 랜덤량
  • 이 추가되었기 때문이다
  • openssl의 표준 형식은 최초로 Salted__라는 문자열과 염량값(8bytes)
  • 을 추가했다.
  • solt는 8bytes면 충분한가요? 16bytes 이상이면 좋을 것 같다는 정보를 알아봤는데, 오픈스sl과 과거의 호환성으로 인해 이 포맷이 바뀌지 않고 미래의 아이슈
  • 가 되었습니다.
  • 베타의 Openssl 3.0을 컴파일하여 동작을 보았지만 Openssl 3.0도 8bytes solt가 표준 형식에 해당한다.
  • encrypt에서openssl을 사용하지 않으면 표준 형식에 구애될 필요가 없습니다.
  • 좋은 웹페이지 즐겨찾기