Как шифровать в VBScript с помощью AES?

Я хочу зашифровать некоторые данные, используя Rijndael/AES в VBScript с использованием определенного ключа и IV. Есть ли хорошие библиотеки функций или COM-компоненты, которые будут полезны для использования?

Я посмотрел CAPICOM; он допускает только кодовую фразу и не позволяет устанавливать определенные значения ключа и IV.

Ответ 1

Один ответ предложил обернуть класс RijndaelManaged в COM. Вы также можете перенести некоторую другую реализацию AES в COM. Я просто попробовал SlowAES, который является реализацией JavaScript AES. Обтекание его в COM через компонент Windows Script делает его вызываемым из VBScript. Я бы рекомендовал это, только если вы не можете использовать подход .NET; Я бы предположил, что AES для .NET будет быстрее, чем AES, реализованный в JavaScript.

В моих тестах с COM-wrapped-SlowAE я использовал режим CBC, и шифрование было полностью совместимо с классом RijndaelManaged в .NET.

Здесь WSC; Я оставил файлы .js, предоставленные SlowAES. Вам нужно вставить их без изменений, когда я пометил файл.

<?xml version="1.0"?>

<!--

//
// Ionic.COM.SlowAES.wsc
//
// This is a Windows Script Component that exposes the SlowAES
// encryption engine via COM. This AES can be used from any 
// COM-capable environment, including Javascript or VBScript. 
//
//
// This code is licensed under the Microsoft Public License. See the
// accompanying License.txt file for details.
//
// Copyright 2009 Dino Chiesa
//

-->

<package>

<component id="Ionic.Com.SlowAES">

  <comment>
SlowAES is a Javascript implementation of AES.  
     See http://code.google.com/p/slowaes.  
This is a COM package for SlowAES.
  </comment>

<?component error="true" debug="true"?>

<registration
  description="WSC Component for SlowAES"
  progid="Ionic.Com.SlowAES"
  version="1.00"
  classid="{ba78383f-1bcc-4df6-9fb9-61cd639ebc94}"
  remotable="False">

  <!-- boilerplate registration/unregistration logic -->
  <script language="VBScript">
  <![CDATA[

strComponent = "Ionic SlowAES"

Function Register
  MsgBox strComponent & " - registered."
End Function

Function Unregister
  MsgBox strComponent & " - unregistered."
End Function

  ]]>
  </script>
</registration>

<public>
  <method name="EncryptString">
<parameter name="plainText"/>
  </method>

  <method name="DecryptBytes">
<parameter name="cipherText"/>
  </method>

  <method name="DecryptBytesToString">
<parameter name="cipherText"/>
  </method>

  <method name="DecryptHexString">
<parameter name="hexStringCipherText"/>
  </method>

  <method name="DecryptCommaDelimitedStringToString">
<parameter name="cipherText"/>
  </method>

  <property name="Key">
  <put/>
  </property>

  <property name="Mode">
  <put/>
  <get/>
  </property>

  <property name="IV">
  <put/>
  <get/>
  </property>

  <property name="KeySize">
  <put/>
  <get/>
  </property>
</public>

<script language="JavaScript">
<![CDATA[

// ...insert slowAES code here... //

// defaults
var _keysize = slowAES.aes.SIZE_128;
var _mode = slowAES.modeOfOperation.CBC;
var _iv = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
var _key;

/* 
* byteArrayToHexString
* convert a byte array to hex string.
*/
function byteArrayToHexString(a)
{
try { hexcase } catch(e) { hexcase=0; }
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var r= "";
for (var i = 0; i < a.length; i++)
{
    var b  = hex_tab.charAt((a[i] >> 4) & 0x0F) + 
    hex_tab.charAt(a[i] & 0x0F);
    r+= b;
}
return r;
}

/* 
* hexStringToByteArray
* convert a string of hex byts to a byte array
*/
function hexStringToByteArray(s)
{
var r= Array(s.length/2);
for (var i = 0; i < s.length; i+=2)
{
    r[i/2] = parseInt(s.substr(i,2),16);
}
return r;
}

function EncryptString(plainText)
{
 var bytesToEncrypt = cryptoHelpers.convertStringToByteArray(plainText);
 var result = slowAES.encrypt(bytesToEncrypt, 
     _mode,
     _key,
     _keysize,
     _iv);
return result['cipher'];
}

function DecryptBytesToString(cipherText)
{
var d = DecryptBytes(cipherText);
var s = cryptoHelpers.convertByteArrayToString(d);
s[cipherText.length]= 0;
return s;
}

function DecryptHexString(hexStringCipherText)
{
var cipherText = hexStringToByteArray(hexStringCipherText);
return DecryptBytesToString(cipherText);
}

function DecryptCommaDelimitedStringToString(cipherText)
{
var c = [];
var atoms = cipherText.split(",");
for (i=0; i < atoms.length; i++)
{
    c.push(parseInt(atoms[i], 10));
}
var d = DecryptBytes(c);
return cryptoHelpers.convertByteArrayToString(d);
}

function DecryptBytes(cipherText)
{
if (cipherText == undefined) return null;

var originalSize = cipherText.length;

var result = slowAES.decrypt(cipherText, 
    originalSize,
    _mode,
    _key,
    _keysize,
    _iv);

return result;
}

function put_Key(keyString)
{
  _key = hexStringToByteArray(keyString);
}

function put_KeySize(size)
{
if (size == 128) _keysize = slowAES.aes.keySize.SIZE_128;
else if (size == 192) _keysize = slowAES.aes.keySize.SIZE_192;
else if (size == 256) _keysize = slowAES.aes.keySize.SIZE_256;
else
    throw "Unsupported key size.  Must be one of { 128, 192, 256 }.";
}

function get_KeySize()
{
if (_keysize == slowAES.aes.keySize.SIZE_128) return 128;
else if (_keysize == slowAES.aes.keySize.SIZE_192) return 192;
else if (_keysize == slowAES.aes.keySize.SIZE_256) return 256;
else return -1;
}

function put_IV(ivString)
{
    _iv = hexStringToByteArray(ivString);
}

function get_IV()
{
return byteArrayToHexString(_iv);
}

function put_Mode(mode)
{
if (mode == "CBC") _mode= slowAES.modeOfOperation.CBC;
else if (mode == "OFB") _mode= slowAES.modeOfOperation.OFB;
else if (mode == "CFB") _mode= slowAES.modeOfOperation.CFB;
else throw "Unsupported mode.  Must be one of {CBC, OFB, CFB}";
}

function get_Mode()
{
if (_mode == slowAES.modeOfOperation.CBC) return "CBC";
if (_mode == slowAES.modeOfOperation.OFB) return "OFB";
if (_mode == slowAES.modeOfOperation.CFB) return "CFB";
return "???";
}

]]>

</script>

</component>

</package>

Сохраните это в файле SlowAES.wsc. Зарегистрируйте его с помощью "regsvr32 SlowAES.wsc". Вот код VBScript, который использует этот компонент.

' '
' byteArrayToHexString'
' convert a byte array to hex string.'
' '
Function byteArrayToHexString(a)
Dim r,b,i
r = ""
For i = 0 To UBound(a)
    b = Hex( (a(i) And &HF0) / 16) & Hex(a(i) And &HF)
    r= r & b
Next
byteArrayToHexString= r
End Function

' '
' hexStringToByteArray'
' convert a string of hex byts to a byte array'
' '
Function hexStringToByteArray(s)
Dim r()
ReDim r(Len(s)/2-1)
Dim x
For i = 0 To  Len(s)-2 Step 2
    x= "&H" & Mid(s,i+1,2)
    r(i/2) = CInt(x)
Next
hexStringToByteArray= r
End Function

Function DemoEncryption()
WScript.echo "Testing Ionic.Com.SlowAES..."

WScript.echo "key:              " & byteArrayToHexString(key)
WScript.echo "iv:               " & byteArrayToHexString(iv)
WScript.echo "key length:       " & keyLengthInBytes & " bytes"
WScript.echo "key length:       " & (keyLengthInBytes*8) & " bits"
WScript.echo "plaintext:        " & plaintext
WScript.echo "plaintext.length: " & Len(plaintext)

WScript.echo "instantiate Ionic.Com.SlowAES"
Dim aes
set aes = CreateObject("Ionic.Com.SlowAES")

WScript.echo "keysize"
aes.KeySize = keyLengthInBytes * 8

WScript.echo "key"
aes.Key = byteArrayToHexString(key)

WScript.echo "iv "
aes.IV= byteArrayToHexString(iv)

WScript.echo "mode "
aes.Mode = "CBC"

WScript.echo "encrypting... "
Dim result
result= aes.EncryptString(plaintext)

' result is a comma-separated string '
' if we Eval() on it we convert it to an array '
Dim expr
expr = "Array(" & result & ")" 

result= Eval( expr )

WScript.echo "Cryptotext/Eval: " & byteArrayToHexString(result)
WScript.echo "Cryptotext.length: " & UBound(result)+1

WScript.echo "decrypting... "
Dim decrypted
'The javascript way to do this is to pass the byte array.'
' Like so:'
'    var decrypted = aes.DecryptBytesToString(result);'
' '
'This does not work from VBScript. So, convert to a hexstring,'
'pass the hex string, and then convert back, in the COM component.'
decrypted= aes.DecryptHexString(byteArrayToHexString(result))

WScript.echo "decrypted: " & decrypted
End Function

dim plaintext, iv, key, keyLengthInBytes

plaintext= "Hello. This is a test. of the emergency broadcasting system."
' iv must be a hexstring representation of an array of bytes, length=16'
iv =  hexStringToByteArray("feedbeeffeedbeefbaadf00dbaadf00d")
' key must be a hexstring representation of an array of bytes, length=16 or 32'
key = hexStringToByteArray("cafebabe0099887766554433221100AA")
keyLengthInBytes= UBound(key)+1

If Err.Number <> 0 Then Err.Clear

Call DemoEncryption

If (Err.Number <> 0) Then WScript.echo("Error: " & Err.Description)

Если вы также хотите использовать функцию деривации ключей на основе пароля, вы можете получить сам код кода succint для PBKDF2 здесь и создать еще один WSC для этого без особых проблем.


EDIT: я сделал то, что я описал, - захватил источник для PBKDF2 и интегрировал его в код для SlowAES. Я также выпустил вторую независимую реализацию на С#, которая использует встроенные библиотеки классов .NET для выполнения RFC 2898-ключа и шифрования AES.

В результате получается три тестовых приложения: одно в С#, одно в JavaScript и другое в VBScript. Источник доступен. Все они принимают один и тот же набор аргументов. Каждый из них использует RFC 2898 - совместимую функцию деривации ключа. Вы можете указать пароль, salt, IV и открытый текст, а также количество итераций RFC 2898 для использования в PBKDF2. Вы можете легко убедиться, что зашифрованный текст одинаковый для каждой из этих тестовых программ. Может быть, этот пример будет полезен для кого-то.

Ответ 2

Старый вопрос, который действительно никогда не стареет! Один из способов - объявить классы шифрования в vbscript, не требуя внешних добавленных COM-объектов или обертки. Следующий пример принимает строку, шифрует и расшифровывает, используя управляемый класс Rijndael:

'-----------------------------------------------------
Dim obj,arr,i,r,str,enc,asc
dim bytes,bytesd,s,sc,sd
set obj=WScript.CreateObject("System.Security.Cryptography.RijndaelManaged")
Set asc = CreateObject("System.Text.UTF8Encoding")
s="This is a private message"
bytes=asc.GetBytes_4(s)
obj.GenerateKey()
obj.GenerateIV()
set enc=obj.CreateEncryptor()
set dec=obj.CreateDecryptor()

bytec=enc.TransformFinalBlock((bytes),0,lenb(bytes))
sc=asc.GetString((bytec))
msgbox sc

byted=dec.TransformFinalBlock((bytec),0,lenb(bytec))
sd=asc.GetString((byted))
msgbox sd
'-----------------------------------------------------

Бест,

Ответ 4

Я знаю, что этот вопрос старый, и OP исчез, но стоит упомянуть будущих пользователей vb6, что VbCorLib теперь поддерживает криптографию, включая страшный Rijndael.

Ссылка: http://vbcorlib.blogspot.com/

Ответ 5

Одним из вариантов было бы создать простой класс-оболочку в .NET для RijndaelManaged class из платформы .NET и выставить его через COM Interop, чтобы вы могли вызывать его из VBScript.

Ответ 6

Вот мое решение. Он сохраняет ключ шифрования и вектор инициализации в файл, чтобы их можно было повторно использовать.

Dim objAes, objAesEncryptor, objAesDecryptor, objUtf8Encoder
Dim objStream, objFileSystem
Dim strMyTextInUtf8, strMyEncyptedInUtf8, strMyText, strEncryptedInAnsi, strDecryptedInAnsi
Dim strMyAesKeyFilename,strMyAesIvFilename
Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2
Const adSaveCreateNotExist = 1

' https://stackoverflow.com/info/270510/how-to-encrypt-in-vbscript-using-aes#28129895

Set objAes=WScript.CreateObject("System.Security.Cryptography.RijndaelManaged")
Set objUtf8Encoder = CreateObject("System.Text.UTF8Encoding")
strMyText = "This is a private message"
strMyTextInUtf8=objUtf8Encoder.GetBytes_4(strMyText)

strMyAesKeyFilename = "c:\Temp\objAes.Key" 'objAes.Key
strMyAesIvFilename  = "c:\Temp\objAes.IV" 'objAes.IV
Set objFileSystem = CreateObject("Scripting.FileSystemObject")
set objStream = createobject("Adodb.Stream")
objStream.Type = adTypeBinary
objStream.open
If (objFileSystem.FileExists(strMyAesKeyFilename) And objFileSystem.FileExists(strMyAesKeyFilename)) Then   
   objStream.LoadFromFile strMyAesKeyFilename
   objAes.Key = objStream.Read
   objStream.Close
   objStream.Open
   objStream.LoadFromFile strMyAesIvFilename
   objAes.IV = objStream.Read
Else
   objAes.GenerateKey()
   objAes.GenerateIV()
   objStream.write objAes.Key
   objStream.savetofile strMyAesKeyFilename, adSaveCreateOverWrite
   objStream.Close
   objStream.open
   objStream.write objAes.IV
   objStream.savetofile strMyAesIvFilename, adSaveCreateOverWrite
   objStream.Close
End IF

Set objAesEncryptor = objAes.CreateEncryptor()
Set objAesDecryptor = objAes.CreateDecryptor()

strMyEncyptedInUtf8 = objAesEncryptor.TransformFinalBlock((strMyTextInUtf8),0,lenb(strMyTextInUtf8))
strEncryptedInAnsi = objUtf8Encoder.GetString((strMyEncyptedInUtf8))
WScript.Echo "Encrypted In Ansi: " & strEncryptedInAnsi

strMyDecyptedInUtf8 = objAesDecryptor.TransformFinalBlock((strMyEncyptedInUtf8),0,lenb(strMyEncyptedInUtf8))
strDecryptedInAnsi = objUtf8Encoder.GetString((strMyDecyptedInUtf8))
WScript.Echo "Decrypted In Ansi: " & strDecryptedInAnsi

Запуск script выглядит следующим образом:

c:\Temp>cscript //nologo TestAesCipher2.vbs
Encrypted In Ansi:  M!???↔???I?!?Q?%&↑?M?n?(?\??o?
Decrypted In Ansi: This is a private message

c:\Temp>cscript //nologo TestAesCipher2.vbs
Encrypted In Ansi:  M!???↔???I?!?Q?%&↑?M?n?(?\??o?
Decrypted In Ansi: This is a private message