3

I'm working on some Matlab code to perform something called the Index Calculus attack on a given cryptosystem (this involves calculating discrete log values), and I've gotten it all done except for one small thing. I cant figure out (in Matlab) how to solve a linear system of congruences mod p, where p is not prime. Also, this system has more than one variable, so, unless I'm missing something, the Chinese remainder theorem wont work.

I asked a question on the mathematics stackexchange with more detail/formatted mathjax here. I solved the issue in my question at that link, and now I'm attempting to find a utility that will allow me to solve the system of congruences modulo a non-prime. I did find a suite that includes a solver supporting modular arithmetic, but the modulus must be prime (here). I also tried stepping through to modify it to work with non-primes, but whatever method is used doesn't work, because it requires all elements of the system have inverses modulo p.

I've looked into using the ability in Matlab to call MuPAD functions, but from my testing, the MuPAD function linsolve (which seemed to be the best candidate) doesn't support non-prime modulus values either. Additionally, I've verified with Maple that this system is solvable modulo my integer of interest (8), so it can be done.

To be more specific, this is the exact command I'm trying to run in MuPAD:

linsolve([0*x + 5*y + 4*z + q = 2946321, x + 7*y + 2*q = 5851213, 8*x + y + 2*q = 2563617, 10*x + 5*y + z = 10670279],[x,y,z,q], Domain = Dom::IntegerMod(8))

Error: expecting 'Domain=R', where R is a domain of category 'Cat::Field' [linsolve]

The same command returns correct values if I change the domain to IntegerMod(23) and IntegerMod(59407), so I believe 8 is unsuitable because it's not prime. Here is the output when I try the above command with each 23 and 59407 as my domain:

[x = 1 mod 23, y = 1 mod 23, z = 12 mod 23, q = 14 mod 23]

[x = 14087 mod 59407, y = 1 mod 59407, z = 14365 mod 59407, q = 37320 mod 59407]

These answers are correct- x, y, z, and q correspond to L1, L2, L3, and L4 in the system of congruences located at my Math.StackExchange link above.

Community
  • 1
  • 1
dkhaupt
  • 2,220
  • 3
  • 23
  • 37
  • I wonder if you might get more help (and be more on-topic) at [Computational Science Stack Exchange](http://scicomp.stackexchange.com) for this sort of question? – horchler Dec 01 '13 at 21:09
  • Sure, I'll ask there as well, thanks for the tip! Any particular reason why I may be off-topic here? – dkhaupt Dec 01 '13 at 21:11
  • This is a programing site so showing some code and the expected output is always helpful. For example, the Matlab code you're using for the 4-by-4 example that you showed in your Math.StackExchange link. I'm not clear on what you mean by `linsolve` not working (and even which of the three `linsolve` functions you mean). Is it that you expect more than one solution, but the solvers are [returning just one](http://mathematica.stackexchange.com/questions/31696/solving-a-system-of-linear-equations-modulo-n)? Is there any C code that implements this? – you might be able to create a mex function. – horchler Dec 01 '13 at 22:31
  • Thanks for the reply- sorry I didn't have any code beforehand. I've added the exact issue I'm seeing. If there's anything more I can provide, let me know. I apologize- I'm new to StackOverflow and StackExchange – dkhaupt Dec 01 '13 at 22:44
  • I'm horribly ignorant, but can't you "bruteforce" an approximate solution to the linear system with other numerical methods (e.g. `nlinfit`)? – Landak Dec 01 '13 at 23:14
  • Not ignorant- you're exactly right, exhaustive search is pretty easy for this problem. Since I'm supposed to emulate an attack on a cryptosystem, however, I'm not allowed to have any brute forcing! The frustrating part is that I can proceed through this as required, but I'm not tripped up by the algorithm, just the trouble in solving this system with MATLAB. I've also looked into executing Maple in MATLAB but it seems it only goes the other way, despite Maple advertising "2 way communication" – dkhaupt Dec 01 '13 at 23:16
  • @Landak: Since these are equivalent to linear Diophantine equations, [`bintprog`](http://www.mathworks.com/help/optim/ug/bintprog.html) might be the better option. – horchler Dec 01 '13 at 23:36

1 Answers1

3

I'm wondering if you tried to use sym/linsolve and sym/solve previously, but may have passed in numeric rather than symbolic values. For example, this returns nonsense in terms of what you're looking for:

A = [0 5 4 1;1 7 0 2;8 1 0 2;10 5 1 0];
b = [2946321;5851213;2563617;10670279];
s = mod(linsolve(A,b),8)

But if you convert the numeric values to symbolic integers, sym/linsolve will keep everything in terms of rational fractions. Then

s = mod(linsolve(sym(A),sym(b)),8)

returns the expected answer

s =

 6
 1
 6
 4

This just solves the system linear system using symbolic math as if it were a normal matrix. For large systems this can be expensive, but I'd imagine no more than using MuPAD's numeric::linsolve or linalg::matlinsolve. sym/mod should return the modulus of the numerator of each solution component. I believe that you will get an error if the modulus and the denominator are not at least coprime.

sym/solve can also be used to solve this in a similar manner:

L = sym('L',[4,1]);
[L1,L2,L3,L4] = solve(A*L==b);
s = mod([L1;L2;L3;L4],8)

A possible issue with using either sym/solve or sym/linsolve is that if there are multiple solutions to the linear congruence problem (as opposed to the linear system), this approach may not return all of them.

Finally, using the MuPAD function numlib::ichrem (chinese remainder theorem for integers), here's some code that attempts to obtain the complete solution:

A = [0 5 4 1;1 7 0 2;8 1 0 2;10 5 1 0];
b = [2946321;5851213;2563617;10670279];
m = 10930888;

mf = str2num(strrep(char(factor(sym(m))),'*',' '));
A = sym(A);
b = sym(b);
s = sym(zeros(length(b),length(mf)));
for i = 1:length(mf)
    s(:,i) = mod(linsolve(A,b),mf(i));
end

mstr = ['[' sprintf('%d,',mf)];
mstr(end) = ']';
r = sym(zeros(length(b),1));
for i = 1:length(b)
    sstr = char(s(i,:));
    r(i) = feval(symengine,'numlib::ichrem',sstr(9:end-2),mstr);
end
check = isequal(mod(A*r,m),b)

I'm not sure if any of this is what you're looking for, but hopefully it might be helpful. I think that it might be a good idea to put in a enhancement/service request with the MathWorks so that MuPAD and the other solvers can handle systems better in the future.

horchler
  • 18,384
  • 4
  • 37
  • 73
  • This all looks great, especially the top part about converting the matrices to symbolic- thanks a ton! I've just tried to replicated it on my own machine, and I get an error that linsolve doesn't support sym arguments. Is that a new feature? I'm using 7.11.0 (R2010b) – dkhaupt Dec 02 '13 at 09:05
  • After trying examples from the sym/linsolve help page, I get the same error: " Undefined function or method 'linsolve' for input arguments of type 'sym'." so I guess sym/linsolve isn't present in R2010b? – dkhaupt Dec 02 '13 at 09:21
  • 1
    Sorry about the late reply. The Symbolic Math toolbox math toolbox has changed a lot over the years so you should probably not look at the online documentation that Google turns up (though archived documentation for old versions is [here](http://www.mathworks.com/help/doc-archives.html)). Instead use the `doc` and `help` functions. Even if `sym/linsolve` doesn't exist in R201b, I imagine that you can use the `sym/solve` version I showed above. You may need to convert the matrix equation to four string equations – I don't know. – horchler Dec 04 '13 at 15:18
  • No worries- thanks for any reply at all! I actually have been trying to use the solve function, but I'm having trouble with it. I asked for help with solve in a different question [here](http://stackoverflow.com/questions/20372917/using-solve-and-or-linsolve-with-the-symbolic-toolbox-in-r2010b) – dkhaupt Dec 04 '13 at 19:25