1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Runtime.InteropServices;
using IronRuby.Builtins;
using IronRuby.Runtime;
using Microsoft.Scripting.Math;
using Microsoft.Scripting.Runtime;
using Crypto = System.Security.Cryptography;
using System.Text;
namespace IronRuby.StandardLibrary.OpenSsl {
[RubyModule("OpenSSL")]
public static class OpenSsl {
// TODO: constants
// Config,HMACError,PKCS12,Random,OPENSSL_VERSION,PKCS7,BN,ConfigError,PKey,Engine,BNError,Netscape,OCSP
// OpenSSLError,CipherError,SSL,VERSION,X509,ASN1,OPENSSL_VERSION_NUMBER,Cipher
[RubyConstant]
public const string OPENSSL_VERSION = "OpenSSL 0.9.8d 28 Sep 2006";
[RubyConstant]
public const double OPENSSL_VERSION_NUMBER = 9470031;
[RubyConstant]
public const string VERSION = "1.0.0";
[RubyModule("Digest")]
public static class DigestFactory {
// TODO: constants:
// SHA224,MDC2,DSS1,SHA512,SHA1,MD5,DSS,SHA384,SHA,MD4,SHA256,DigestError,RIPEMD160,MD2
[RubyClass("Digest")]
public class Digest {
private Crypto.HMAC _algorithm;
public Crypto.HMAC Algorithm {
get { return _algorithm; }
}
protected Digest() {
}
[RubyConstructor]
public static Digest/*!*/ CreateDigest(RubyClass/*!*/ self, [NotNull]MutableString/*!*/ algorithmName) {
return Initialize(new Digest(), algorithmName);
}
// Reinitialization. Not called when a factory/non-default ctor is called.
[RubyMethod("initialize", RubyMethodAttributes.PrivateInstance)]
public static Digest/*!*/ Initialize(Digest/*!*/ self, [NotNull]MutableString/*!*/ algorithmName) {
Crypto.HMAC algorithm;
#if SILVERLIGHT
switch (algorithmName.ToString()) {
case "SHA1": algorithm = new Crypto.HMACSHA1(); break;
case "SHA256": algorithm = new Crypto.HMACSHA256(); break;
default: algorithm = null; break;
}
#else
algorithm = Crypto.HMAC.Create("HMAC" + algorithmName.ConvertToString());
#endif
if (algorithm == null) {
throw new RuntimeError(String.Format("Unsupported digest algorithm ({0}).", algorithmName));
}
self._algorithm = algorithm;
return self;
}
}
}
[RubyClass("HMAC")]
public class HMAC {
[RubyMethod("hexdigest", RubyMethodAttributes.PublicSingleton)]
public static MutableString/*!*/ HexDigest(RubyClass/*!*/ self, [NotNull]DigestFactory.Digest/*!*/ digest,
[NotNull]MutableString/*!*/ key, [NotNull]MutableString/*!*/ data) {
// TODO: does MRI really modify the digest object?
digest.Algorithm.Key = key.ConvertToBytes();
byte[] hash = digest.Algorithm.ComputeHash(data.ConvertToBytes());
return MutableString.Create(BitConverter.ToString(hash).Replace("-", "").ToLower());
}
}
[RubyModule("Random")]
public static class RandomModule {
// This is a no-op method since our random number generator uses the .NET crypto random number generator
// that gets its seed values from the OS
[RubyMethod("seed", RubyMethodAttributes.PublicSingleton)]
public static MutableString/*!*/ Seed(RubyModule/*!*/ self, [DefaultProtocol, NotNull]MutableString/*!*/ seed) {
return seed;
}
[RubyMethod("pseudo_bytes", RubyMethodAttributes.PublicSingleton)]
[RubyMethod("random_bytes", RubyMethodAttributes.PublicSingleton)]
public static MutableString/*!*/ RandomBytes(RubyModule/*!*/ self, [DefaultProtocol, NotNull]int/*!*/ length) {
if (length < 0) {
throw RubyExceptions.CreateArgumentError("negative string size");
}
if (length == 0) {
return MutableString.Create("");
}
byte[] data = new byte[length];
var generator = new Crypto.RNGCryptoServiceProvider();
generator.GetBytes(data);
return MutableString.CreateBinary(data);
}
// add(str, entropy) -> self
// load_random_file(filename) -> true
}
[RubyClass("BN")]
public class BN {
// new => aBN
// new(bn) => aBN
// new(string) => aBN
// new(string, 0 | 2 | 10 | 16) => aBN
[RubyMethod("rand", RubyMethodAttributes.PublicSingleton)]
public static BigInteger/*!*/ Rand(RubyClass/*!*/ self, [DefaultProtocol]int bits, [DefaultProtocol, Optional]int someFlag, [Optional]bool otherFlag) { // TODO: figure out someFlag and otherFlag
byte[] data = new byte[bits >> 3];
var generator = new Crypto.RNGCryptoServiceProvider();
generator.GetBytes(data);
uint[] transformed = new uint[data.Length >> 2];
int j = 0;
for (int i = 0; i < transformed.Length; ++i) {
transformed[i] = data[j] + (uint)(data[j + 1] << 8) + (uint)(data[j + 2] << 16) + (uint)(data[j + 3] << 24);
j += 4;
}
return new BigInteger(1, transformed);
}
}
}
}
|