| 'use strict'; | 
|   | 
| var BN = require('bn.js'); | 
|   | 
| var utils = require('../utils'); | 
| var assert = utils.assert; | 
|   | 
| function Signature(options, enc) { | 
|   if (options instanceof Signature) | 
|     return options; | 
|   | 
|   if (this._importDER(options, enc)) | 
|     return; | 
|   | 
|   assert(options.r && options.s, 'Signature without r or s'); | 
|   this.r = new BN(options.r, 16); | 
|   this.s = new BN(options.s, 16); | 
|   if (options.recoveryParam === undefined) | 
|     this.recoveryParam = null; | 
|   else | 
|     this.recoveryParam = options.recoveryParam; | 
| } | 
| module.exports = Signature; | 
|   | 
| function Position() { | 
|   this.place = 0; | 
| } | 
|   | 
| function getLength(buf, p) { | 
|   var initial = buf[p.place++]; | 
|   if (!(initial & 0x80)) { | 
|     return initial; | 
|   } | 
|   var octetLen = initial & 0xf; | 
|   | 
|   // Indefinite length or overflow | 
|   if (octetLen === 0 || octetLen > 4) { | 
|     return false; | 
|   } | 
|   | 
|   var val = 0; | 
|   for (var i = 0, off = p.place; i < octetLen; i++, off++) { | 
|     val <<= 8; | 
|     val |= buf[off]; | 
|     val >>>= 0; | 
|   } | 
|   | 
|   // Leading zeroes | 
|   if (val <= 0x7f) { | 
|     return false; | 
|   } | 
|   | 
|   p.place = off; | 
|   return val; | 
| } | 
|   | 
| function rmPadding(buf) { | 
|   var i = 0; | 
|   var len = buf.length - 1; | 
|   while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) { | 
|     i++; | 
|   } | 
|   if (i === 0) { | 
|     return buf; | 
|   } | 
|   return buf.slice(i); | 
| } | 
|   | 
| Signature.prototype._importDER = function _importDER(data, enc) { | 
|   data = utils.toArray(data, enc); | 
|   var p = new Position(); | 
|   if (data[p.place++] !== 0x30) { | 
|     return false; | 
|   } | 
|   var len = getLength(data, p); | 
|   if (len === false) { | 
|     return false; | 
|   } | 
|   if ((len + p.place) !== data.length) { | 
|     return false; | 
|   } | 
|   if (data[p.place++] !== 0x02) { | 
|     return false; | 
|   } | 
|   var rlen = getLength(data, p); | 
|   if (rlen === false) { | 
|     return false; | 
|   } | 
|   var r = data.slice(p.place, rlen + p.place); | 
|   p.place += rlen; | 
|   if (data[p.place++] !== 0x02) { | 
|     return false; | 
|   } | 
|   var slen = getLength(data, p); | 
|   if (slen === false) { | 
|     return false; | 
|   } | 
|   if (data.length !== slen + p.place) { | 
|     return false; | 
|   } | 
|   var s = data.slice(p.place, slen + p.place); | 
|   if (r[0] === 0) { | 
|     if (r[1] & 0x80) { | 
|       r = r.slice(1); | 
|     } else { | 
|       // Leading zeroes | 
|       return false; | 
|     } | 
|   } | 
|   if (s[0] === 0) { | 
|     if (s[1] & 0x80) { | 
|       s = s.slice(1); | 
|     } else { | 
|       // Leading zeroes | 
|       return false; | 
|     } | 
|   } | 
|   | 
|   this.r = new BN(r); | 
|   this.s = new BN(s); | 
|   this.recoveryParam = null; | 
|   | 
|   return true; | 
| }; | 
|   | 
| function constructLength(arr, len) { | 
|   if (len < 0x80) { | 
|     arr.push(len); | 
|     return; | 
|   } | 
|   var octets = 1 + (Math.log(len) / Math.LN2 >>> 3); | 
|   arr.push(octets | 0x80); | 
|   while (--octets) { | 
|     arr.push((len >>> (octets << 3)) & 0xff); | 
|   } | 
|   arr.push(len); | 
| } | 
|   | 
| Signature.prototype.toDER = function toDER(enc) { | 
|   var r = this.r.toArray(); | 
|   var s = this.s.toArray(); | 
|   | 
|   // Pad values | 
|   if (r[0] & 0x80) | 
|     r = [ 0 ].concat(r); | 
|   // Pad values | 
|   if (s[0] & 0x80) | 
|     s = [ 0 ].concat(s); | 
|   | 
|   r = rmPadding(r); | 
|   s = rmPadding(s); | 
|   | 
|   while (!s[0] && !(s[1] & 0x80)) { | 
|     s = s.slice(1); | 
|   } | 
|   var arr = [ 0x02 ]; | 
|   constructLength(arr, r.length); | 
|   arr = arr.concat(r); | 
|   arr.push(0x02); | 
|   constructLength(arr, s.length); | 
|   var backHalf = arr.concat(s); | 
|   var res = [ 0x30 ]; | 
|   constructLength(res, backHalf.length); | 
|   res = res.concat(backHalf); | 
|   return utils.encode(res, enc); | 
| }; |