OpenSSL で復号できる暗号化ファイルを PowerShell で作る

RSA鍵を使う場合。

# OpenSSL のみの場合

公開鍵を使って暗号化:

```
ken@EXELION-X1:/mnt/d/pki$ cat plain.txt
Original Message
ken@EXELION-X1:/mnt/d/pki$ openssl rsautl -encrypt -pubin -inkey client01pub.pem -in ./plain.txt -out encdata.dat
ken@EXELION-X1:/mnt/d/pki$ ls -l encdata.dat
-rwxrwxrwx 1 ken ken 256  1月 14 21:40 encdata.dat
```
秘密鍵を使って復号:

```
ken@EXELION-X1:/mnt/d/pki$ openssl rsautl -decrypt -inkey pki/private/client01.key -in ./encdata.dat
Enter pass phrase for pki/private/client01.key:
Original Message
```

前者の暗号化を、PowerShell でやりたい。

# PowerShell で暗号化

PowerShell の暗号化は、System.Security.Cryptography.RSACryptoServiceProvider が使えるらしい。

* System.Security.Cryptography.RSACryptoServiceProvider をインスタンス化

```
PS D:\pki> $rsa = New-Object -TypeName System.Security.Cryptography.RSACryptoServiceProvider
PS D:\pki> $rsa


PublicOnly           : False
CspKeyContainerInfo  : System.Security.Cryptography.CspKeyContainerInfo
KeySize              : 1024
KeyExchangeAlgorithm : RSA-PKCS1-KeyEx
SignatureAlgorithm   : http://www.w3.org/2000/09/xmldsig#rsa-sha1
PersistKeyInCsp      : False
LegalKeySizes        : {System.Security.Cryptography.KeySizes}
```
* 暗号化に使う公開鍵をセットする

```
$rsa.FromXmlString($xml) 
```
でできるのだが、$xml は「XML形式」の公開鍵 (String型) である必要がある。
OpenSSL では通常「PEM形式」なので、PEMからXMLに変換する必要がある。

とりあえず変換するだけなら https://superdry.apphb.com/tools/online-rsa-key-converter で変換できるので、いまはこれで変換して PowerShell に張り付ける。

```
PS D:\pki> $xml="<RSAKeyValue>
>>   <Exponent>AQAB</Exponent>
>>   <Modulus>qeiYX/ckHOIA9nB9KcIKsLbSaiM0lEiVptPnUeXBo/EA+Qgt1143B9Jr9rHxm4DDcdsBKS5lsSnSGu6RDNDpQiLOpFTIyEz/9uCIkPtFIiykjpQP7z4Y7h9+pGvQ03eK6sQtaz47vC6tAoFfiOw7Zp4sQ+42ge1Ak+Ug5O5std6DD2NPAZ2eaBxNmuHlpnP3Qzee2tWdT1Co5rluA5d2h7P5JVow22m2Zj8HKlfURg+DvLOgG/4lZE9JyIkrvKM9faW1te2qiMvKNH08ZmCtmXcx2ZBueujWx6aW15MeAghzM5NbIRzeIsQWpPZHS+Rm0cGnhj1fxffl148l+UwGdw==</Modulus>
>> </RSAKeyValue>"
```

プログラム化するなら、PEM は base64 なので各行を base64 decode したうえで Exponent と Modulus を取り出し XML 形式にする、という処理が必要と思われる。
https://gist.github.com/stormwild/7887264 や https://qiita.com/rawr/items/9492e7fc93be7ca99ac1 のような方法。

* 暗号化に使う公開鍵をセットする(別の方法)

XMLではなく System.Security.Cryptography.RSAParameters で鍵を設定することもできる (ImportParameters)。 ただ、RSAParameters はただの構造体でコンストラクタはない模様。XML の場合と同じように PEM をでコードして取り出した値で埋めたうえで ImportParameters する必要がある。

* 暗号化するデータをファイルから読み出す

```
PS D:\pki> $d = Get-Content "D:\pki\plain.txt" -Encoding Byte
PS D:\pki> $d.Length
17
PS D:\pki> $d | Get-Member


   TypeName: System.Byte

Name         MemberType   Definition
----         ----------   ----------
CompareTo    Method       int CompareTo(System.Object value), int CompareTo(byte value), int IComparable.CompareTo(S...
Equals       Method       bool Equals(System.Object obj), bool Equals(byte obj), bool IEquatable[byte].Equals(byte o...
GetHashCode  Method       int GetHashCode()
(snip)
```

* 暗号化

```
PS D:\pki> $enc = $rsa.Encrypt($d, $false)
PS D:\pki> $enc.Length
256
PS D:\pki> $enc | Get-Member


   TypeName: System.Byte

Name        MemberType Definition
----        ---------- ----------
CompareTo   Method     int CompareTo(System.Object value), int CompareTo(byte value), int IComparable.CompareTo(Syst...
Equals      Method     bool Equals(System.Object obj), bool Equals(byte obj), bool IEquatable[byte].Equals(byte other)
GetHashCode Method     int GetHashCode()
(snip)
```

* 暗号化されたデータをファイルに書き出す

```
PS D:\pki> Set-Content -Encoding Byte -value $enc "D:\pki\enc_ps.data"
```

* できたファイルを OpenSSL で復号してみる

```
ken@EXELION-X1:/mnt/d/pki$ ls -l enc_ps.data
-rwxrwxrwx 1 ken ken 256  1月 14 21:55 enc_ps.data
ken@EXELION-X1:/mnt/d/pki$ openssl rsautl -decrypt -inkey pki/private/client01.key -in ./enc_ps.data
Enter pass phrase for pki/private/client01.key:
Original Message
```

できた!