{"id":3014,"date":"2014-09-11T10:01:00","date_gmt":"2014-09-11T14:01:00","guid":{"rendered":"http:\/\/irreal.org\/blog\/?p=3014"},"modified":"2014-09-11T10:18:45","modified_gmt":"2014-09-11T14:18:45","slug":"shamir-secret-sharing-implementation","status":"publish","type":"post","link":"https:\/\/irreal.org\/blog\/?p=3014","title":{"rendered":"Shamir&#8217;s Secret Sharing Implementation"},"content":{"rendered":"<p> Yesterday, I discussed Shamir&#8217;s secret sharing and how it works. The TL;DR was a method to give \\(n\\) people a secret number so that any \\(k\\) of the recipients \\((k\\lt n)\\) can reveal the secret. The method works by defining a \\((k-1)\\)-degree polynomial with the secret number as the constant term and then distributing \\(n\\) points on the polynomial. Once we have \\(k\\) points, we can recover the polynomial&#x2014;and therefore the secret constant term&#x2014;by interpolation. <\/p>\n<p> We begin with a couple of constants and a function. The <code>randp<\/code> function uses <code>strong-random<\/code> from the ironclad library to generate cryptographically secure random integers between 0 and \\(p-1\\). We use it to generate the coefficients for the polynomial and the \\(x\\)-coordinates of the \\(n\\) points. The <code>*prng*<\/code> parameter holds the state for <code>randp<\/code>. <\/p>\n<p> <code>*P*<\/code> is a 256 bit prime number. It&#8217;s the default size for the number of elements in our finite field. Because \\(\\mathbb{Z}_{p}\\) is a finite field, you might think that we could simply try each element of the field to recover an encryption key based on the constant term of the polynomial. That would work for a low order field but using <code>*P*<\/code> gives us a field with \\(2^{256}\\) members rendering a brute force attack infeasible. <\/p>\n<div class=\"org-src-container\">\n<pre class=\"src src-lisp\">(<span style=\"color: #a020f0;\">defparameter<\/span> <span style=\"color: #a0522d;\">*prng*<\/span> (ironclad:make-prng <span style=\"color: #483d8b;\">:fortuna<\/span>) <span style=\"color: #8b2252;\">\"Holds the RNG state.\"<\/span>)\n(<span style=\"color: #a020f0;\">defparameter<\/span> <span style=\"color: #a0522d;\">*P*<\/span> 108838049659940303356103757286832107246140775791152305372594007835539736018383 <span style=\"color: #8b2252;\">\"256 bit prime\"<\/span>)\n\n(<span style=\"color: #a020f0;\">defun<\/span> <span style=\"color: #0000ff;\">randp<\/span> (p)\n  <span style=\"color: #8b2252;\">\"Generate a random number for the polynomial coefficents and sample points.\"<\/span>\n  (ironclad:strong-random p *prng*))\n<\/pre>\n<\/p><\/div>\n<p> Because we&#8217;re working in \\(\\mathbb{Z}_{p}\\), \u201cdivision\u201d is a bit more complicated. The <code>modinv<\/code> function uses the Euclidean algorithm to compute the (mod \\(m\\)) inverse of a number. When we need to divide by some number, \\(x\\), we use <code>modinv<\/code> to compute its inverse and then multiply by that inverse to \u201cdivide.\u201d <\/p>\n<div class=\"org-src-container\">\n<pre class=\"src src-lisp\">(<span style=\"color: #a020f0;\">defun<\/span> <span style=\"color: #0000ff;\">modinv<\/span> (a p)\n  <span style=\"color: #8b2252;\">\"Find the inverse of a mod p, p a prime. Uses the Euclidian algorithm.<\/span>\n<span style=\"color: #8b2252;\">This is Algorithm X of Section 4.5.2 of TAOCP.\"<\/span>\n  (<span style=\"color: #a020f0;\">labels<\/span> ((euclid (u v)\n             (<span style=\"color: #a020f0;\">if<\/span> (= (caddr v) 0)\n                 (<span style=\"color: #a020f0;\">let<\/span> ((u0 (car u)))\n                   (<span style=\"color: #a020f0;\">if<\/span> (minusp u0)\n                       (+ u0 p)\n                       u0))\n                 (<span style=\"color: #a020f0;\">let<\/span> ((q (floor (\/ (caddr u) (caddr v)))))\n                   (euclid v (mapcar (<span style=\"color: #a020f0;\">lambda<\/span> (x y) (- x (* q y))) u v))))))\n    (euclid (list 1 0 a) (list 0 1 p))))\n<\/pre>\n<\/p><\/div>\n<p> We&#8217;ll generate the \\(n\\) points by choosing \\(n\\) random, non-zero \\(x\\) values and evaluating the polynomial at those points. The efficient way to evaluate polynomials is with Horner&#8217;s methods. I wrote about Horner&#8217;s method <a href=\"http:\/\/irreal.org\/blog\/?p=2430\">previously<\/a>. <\/p>\n<div class=\"org-src-container\">\n<pre class=\"src src-lisp\">(<span style=\"color: #a020f0;\">defun<\/span> <span style=\"color: #0000ff;\">horner<\/span> (a x)\n  <span style=\"color: #8b2252;\">\"Evaluate the polynomial with coefficients in the array a at x.\"<\/span>\n  (<span style=\"color: #a020f0;\">if<\/span> (= (length a) 1)\n      (aref a 0)\n      (<span style=\"color: #a020f0;\">do*<\/span> ((k (1- (length a)) (1- k))\n            (val (* (aref a k) x) (* (+ val (aref a k)) x)))\n           ((&lt;= k 1) (+ val (aref a 0))))))\n<\/pre>\n<\/p><\/div>\n<p> The <code>make-keys<\/code> function uses <code>randp<\/code> to choose the polynomial&#8217;s coefficients (and thus the secret) and the \\(x\\)-values of the \\(n\\) points. Then it uses <code>horner<\/code> to generate the \\(n\\) points. <\/p>\n<p> The <code>xvals<\/code> list is initialized to (0) so that 0 will not be chosen as an \\(x\\)-value. It&#8217;s discarded before <code>xvals<\/code> is input to the <code>mapcar<\/code> by the <code>butlast<\/code>. <\/p>\n<div class=\"org-src-container\">\n<pre class=\"src src-lisp\">(<span style=\"color: #a020f0;\">defun<\/span> <span style=\"color: #0000ff;\">make-keys<\/span> (n k <span style=\"color: #228b22;\">&amp;optional<\/span> (p *P*))\n  <span style=\"color: #8b2252;\">\"Returns a random secret and n distinct keys.<\/span>\n<span style=\"color: #8b2252;\">K keys are sufficient to recover the secret. Each key is a pair, a point<\/span>\n<span style=\"color: #8b2252;\">on a random polynomial over the field Z\/p.\"<\/span>\n  (<span style=\"color: #a020f0;\">let<\/span> ((a (make-array k))\n        (xvals '(0)))                   <span style=\"color: #b22222;\">;<\/span><span style=\"color: #b22222;\">ensure x=0 not chosen as a point<\/span>\n    (<span style=\"color: #a020f0;\">dotimes<\/span> (i k)\n      (setf (aref a i) (randp p)))\n    (<span style=\"color: #a020f0;\">while<\/span> (&lt; (length xvals) (1+ n))\n      (setq xvals (adjoin (randp p) xvals)))\n    (cons (aref a 0)\n          (mapcar (<span style=\"color: #a020f0;\">lambda<\/span> (x) (list x (mod (horner a x) p))) (butlast xvals)))))\n<\/pre>\n<\/p><\/div>\n<p> Given the \\(k\\) points \\((x_{0}, y_{0}) \\ldots (x_{k-1}, y_{k-1})\\), we retrieve the secret by evaluating the polynomial resulting from the Lagrangian interpolation of the \\(k\\) points at 0. We can do this all at once by computing \\[\\sum_{i=0}^{k-1} y_{i} \\prod_{\\substack{0\\leq{}j\\leq{}k-1 \\\\ j\\neq{}i}} \\frac{-x_{j}}{x_{i}-x_{j}}\\] as explained in yesterday&#8217;s post. Notice that <code>retrieve-secret<\/code> is an almost literal translation of the above. <\/p>\n<div class=\"org-src-container\">\n<pre class=\"src src-lisp\">(<span style=\"color: #a020f0;\">defun<\/span> <span style=\"color: #0000ff;\">retrieve-secret<\/span> (v <span style=\"color: #228b22;\">&amp;optional<\/span> (p *P*))\n  <span style=\"color: #8b2252;\">\"Recover the secret given k points and the prime.\"<\/span>\n  (<span style=\"color: #a020f0;\">let<\/span> ((k (length v))\n        (secret 0)\n        prod)\n    (<span style=\"color: #a020f0;\">dotimes<\/span> (i k (mod secret p))\n      (setq prod (cadr (aref v i)))\n      (setq secret (+ secret \n                      (<span style=\"color: #a020f0;\">dotimes<\/span> (j k prod)\n                        (<span style=\"color: #a020f0;\">unless<\/span> (= j i)\n                          (setq prod (* prod\n                                        (car (aref v j))\n                                        (modinv\n                                         (- (car (aref v j))\n                                            (car (aref v i)))\n                                         p))))))))))\n<\/pre>\n<\/p><\/div>\n<p> As you can see, Shamir&#8217;s method is easy to understand and implement. None-the-less, it&#8217;s a powerful way of having a distributed secret. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Yesterday, I discussed Shamir&#8217;s secret sharing and how it works. The TL;DR was a method to give \\(n\\) people a secret number so that any \\(k\\) of the recipients \\((k\\lt n)\\) can reveal the secret. The method works by defining &hellip; <a href=\"https:\/\/irreal.org\/blog\/?p=3014\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[39,14],"class_list":["post-3014","post","type-post","status-publish","format-standard","hentry","category-programming","tag-common-lisp","tag-lisp"],"_links":{"self":[{"href":"https:\/\/irreal.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3014","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/irreal.org\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/irreal.org\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/irreal.org\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/irreal.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3014"}],"version-history":[{"count":3,"href":"https:\/\/irreal.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3014\/revisions"}],"predecessor-version":[{"id":3017,"href":"https:\/\/irreal.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3014\/revisions\/3017"}],"wp:attachment":[{"href":"https:\/\/irreal.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3014"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/irreal.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3014"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/irreal.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3014"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}