/// <summary> /// /// </summary> /// <param name="secret">密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串。</param> /// <returns></returns> public static string GetSignParam(string secret) { long timestamp = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds; string stringToSign = timestamp + "\n" + secret; Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(System.Text.Encoding.Default.GetBytes(secret), "HmacSHA256")); byte[] signData = mac.doFinal(System.Text.Encoding.Default.GetBytes(stringToSign)); string sign = URLEncoder.encode(Convert.ToBase64String(signData), "UTF-8"); return("×tamp=" + Convert.ToString(timestamp) + "&sign=" + sign); }
/// <summary> /// Create <b>HmacSHA1</b> byte[] signature for data and key /// </summary> /// <param name="data"> byte[] </param> /// <param name="key"> byte[] </param> /// <returns> signature byte[] </returns> /// <exception cref="SignatureException"> </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public byte[] sign(byte[] data, byte[] key) throws java.security.SignatureException public virtual sbyte[] sign(sbyte[] data, sbyte[] key) { try { Mac mac = Mac.getInstance(HmacSHA1); mac.init(new SecretKeySpec(key, HmacSHA1)); return(mac.doFinal(data)); } catch (Exception e) { throw new SignatureException("Unable to calculate a request signature: " + e.Message, e); } }
/** * Calculates the verification code of the provided key at the specified * instant of time using the algorithm specified in RFC 6238. * * @param key the secret key in binary format. * @param tm the instant of time. * @return the validation code for the provided key at the specified instant * of time. */ int calculateCode(byte[] key, long tm) { // Allocating an array of bytes to represent the specified instant // of time. byte[] data = new byte[8]; long value = tm; // Converting the instant of time from the long representation to a // big-endian array of bytes (RFC4226, 5.2. Description). for (int i = 8; i-- > 0; value >> >= 8) { data[i] = (byte)value; } // Building the secret key specification for the HmacSHA1 algorithm. System.Security.Cryptography.HMACSHA1 signKey = new SecretKeySpec(key, config.getHmacHashFunction().toString()); try { // Getting an HmacSHA1/HmacSHA256 algorithm implementation from the JCE. Mac mac = Mac.getInstance(config.getHmacHashFunction().toString()); // Initializing the MAC algorithm. mac.init(signKey); // Processing the instant of time and getting the encrypted data. byte[] hash = mac.doFinal(data); // Building the validation code performing dynamic truncation // (RFC4226, 5.3. Generating an HOTP value) int offset = hash[hash.length - 1] & 0xF; // We are using a long because Java hasn't got an unsigned int type // and we need 32 unsigned bits). long truncatedHash = 0; for (int i = 0; i < 4; ++i) { truncatedHash <<= 8; // Java bytes are signed but we need an unsigned int: // cleaning off all but the LSB. truncatedHash |= (hash[offset + i] & 0xFF); } // Clean bits higher than the 32nd (inclusive) and calculate the // module with the maximum validation code value. truncatedHash &= 0x7FFFFFFF; truncatedHash %= config.getKeyModulus(); // Returning the validation code to the caller. return((int)truncatedHash); } catch (NoSuchAlgorithmException | InvalidKeyException ex) { // Logging the exception. LOGGER.log(Level.SEVERE, ex.getMessage(), ex); // We're not disclosing internal error details to our clients. throw new AuthenticatorException("The operation cannot be " + "performed now."); } }